我有一个扩展 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 并刷新面板的代码,因为这个问题没有必要。
感谢您提前提供任何帮助