0

我有一个扩展 JPanel 的类 ExamplePanel,它由 2 个 JPanel-labelsPanel 和 subPanel 组成。Labelspanel 包含任意 JLabels,而 subPanel 包含 ExamplePanel 嵌套实例的不同实例。

我希望能够将 JLabels 拖到嵌套实例中,但是当我这样做时,它们最终会出现在 subPanel 后面。我相信答案在于 setComponentZOrder 方法,但我没有取得任何进展。它使 JLabel 被绘制在 labelsPanel 中的其他 JLabel 之上,但一旦 JLabel 超出该面板的范围,则没有效果。我尝试将 JLabel 和 JPanel 都带到 Z 顺序位置 0 和 1,并首先绘制 subPanel,但这些都没有达到预期的效果。简化代码如下。(我已经尽量删减了,如果还有一些异常的代码部分,请见谅)

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;


public class ExamplePanel extends JPanel implements MouseListener,
    MouseMotionListener {

public JPanel labelsPanel;
public JPanel subPanel;

public ArrayList<JLabel> labels;
public ArrayList<ExamplePanel> panels;


private int xOffset = 0, yOffset = 0;
private Rectangle prevBounds = null;

private boolean isDragged;

public ExamplePanel(ArrayList<JLabel> labels, ArrayList<ExamplePanel> panels) {
    this.invalidate();

    this.labels = labels;
    this.panels = panels;
    addMouseListener(this);
    this.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(Color.GRAY),
            BorderFactory.createEmptyBorder(10, 10, 10, 10)));
    this.setLayout(new BorderLayout());
    this.setAlignmentX(Component.LEFT_ALIGNMENT);
    addLabels();
    addPanels();
    this.validate();

}

public void addLabels() {
    if (labelsPanel != null) {
        this.remove(labelsPanel);
    }

    labelsPanel = new JPanel(new GridBagLayout());
    labelsPanel.setBorder(BorderFactory.createLineBorder(Color.GREEN));


    GridBagConstraints c = new GridBagConstraints();
    c.anchor = GridBagConstraints.CENTER;
    c.ipadx = 50;
    c.ipady = 30;
    c.gridx = 0;
    c.gridy = 0;

    System.out.println("labels size: " + labels.size());

    for (int i = 0; i < labels.size(); i++) {
        c.gridx = i;

        labels.get(i).addMouseListener(this);
        labels.get(i).addMouseMotionListener(this);

        labelsPanel.add(labels.get(i), c);
    }

    this.add(labelsPanel, BorderLayout.NORTH);
}

public void addPanels() {

    System.out.println("panels size: " + panels.size());
    if (subPanel != null) {
        this.remove(subPanel);
    }

    subPanel = new JPanel(new BorderLayout());
    subPanel.setBorder(BorderFactory.createLineBorder(Color.RED));
    subPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

    subPanel.setOpaque(false);

    for (ExamplePanel panel : panels) {
        subPanel.add(panel);
        this.validate();
    }

    this.add(subPanel, BorderLayout.CENTER);
}

public void addLabel(JLabel label) {
    labels.add(label);
}

public void addPanel(ExamplePanel panel) {
    panels.add(panel);
}

@Override
public void mouseDragged(MouseEvent e) {
    isDragged = true;
    JLabel dragged = (JLabel) e.getSource();

    int newX = (e.getX() + dragged.getBounds().x - xOffset < 0) ? 0 : e
            .getX() + dragged.getBounds().x - xOffset;
    int newY = (e.getY() + dragged.getBounds().y - yOffset < 0) ? 0 : e
            .getY() + dragged.getBounds().y - yOffset;
    dragged.setLocation(newX, newY);

}

@Override
public void mouseMoved(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mouseClicked(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mouseEntered(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mousePressed(MouseEvent arg0) {
    System.out.println("++++++ Start Of Pressed ++++++");

    System.out.println("Mouse Pressed At: " + arg0.getX() + " "
            + arg0.getY());

    // Collect the clicked source and return if it's
    // not a JLabel (might have to be modified if we
    // want to click on other things than JLabels.
    Object source = (Object) arg0.getSource();

    if (source instanceof JLabel) {
        JLabel jlb = (JLabel) arg0.getSource();
        prevBounds = jlb.getBounds();
        xOffset = arg0.getX();
        yOffset = arg0.getY();

        ((JLabel) arg0.getSource()).getParent().setComponentZOrder(
                ((JLabel) arg0.getSource()), 0);

    }
    JLabel clicked = null;
    if (source instanceof JLabel) {
        clicked = (JLabel) source;
    } else {
        System.out.println("++++++ End Of Pressed ++++++");
        return;
    }

    System.out.println("++++++ End Of Pressed ++++++");

}

@Override
public void mouseReleased(MouseEvent arg0) {
    System.out.println("++++++ Start Of Released ++++++");


    if (!isDragged) {
        System.out.println("++++++ End Of Released, not dragging ++++++");
        return;
    }

    isDragged = false;
    xOffset = yOffset = 0;

    // The object being dragged
    JLabel source = (JLabel) arg0.getSource();
    System.out.println("Source is: " + source.toString());

    source.setBounds(prevBounds);


    System.out.println("++++++ End Of Released ++++++");

}
}

一个基本的主类如下;

import java.awt.Dimension;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JLabel;


public class Main extends JFrame {

public Main() {
    setSize(new Dimension(600, 600));

    ArrayList<JLabel> labels = new ArrayList<JLabel>();
    JLabel label1 = new JLabel("Example 1");
    JLabel label2 = new JLabel("Example 2");
    labels.add(label1);
    labels.add(label2);

    ArrayList<ExamplePanel> panels = new ArrayList<ExamplePanel>();
    ArrayList<ExamplePanel> panels2 = new ArrayList<ExamplePanel>();
    System.out.println("LAbels size = " + labels.size());
    ExamplePanel secondPanel = new ExamplePanel(labels, panels2);
    panels.add(secondPanel);

    ExamplePanel firstPanel = new ExamplePanel(labels, panels);

    this.add(firstPanel);
    this.setVisible(true);
}

public static void main (String [] args) {
    Main main = new Main();
}
}

我省略了将 JLabel 实际添加到 subPanel 并刷新面板的代码,因为这个问题没有必要。

感谢您提前提供任何帮助

4

1 回答 1

3

最简单的选择是从当前容器中删除标签并将其移动到框架玻璃窗格中,允许标签在玻璃窗格中移动并将其添加回它被丢弃的容器。

查看如何使用玻璃板了解更多信息

于 2013-01-24T19:51:51.527 回答