我写了一个基本的DnD程序,它连续有四个JLabel。我发觉到 当我将标签拖到左侧时,它会显示在下一个标签下方。然而, 当我将标签向右拖动时,它会显示在下一个标签上方。 标签按顺序从左到右添加。所以被拖动的标签正在存在 显示在拖动标签之前添加的其他标签下方并显示 在拖动标签后添加的其他标签之上。 谁能解释为什么会这样?任何人都可以提供修复,以便拖动标签 显示在其他标签上方? 感谢。
源代码:
public class LabelDnd extends JPanel {
private JLabel[] labels;
private Color[] colors = { Color.BLUE, Color.BLACK, Color.RED, Color.MAGENTA };
public LabelDnd() {
super();
this.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JPanel basePanel = new JPanel();
basePanel.setLayout(new GridLayout(1, 4, 4, 4));
basePanel.setBackground(Color.CYAN);
MouseAdapter listener = new MouseAdapter() {
Point p = null;
@Override
public void mousePressed(MouseEvent e) {
p = e.getLocationOnScreen();
}
@Override
public void mouseDragged(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
Point l = c.getLocation();
Point here = e.getLocationOnScreen();
c.setLocation(l.x + here.x - p.x, l.y + here.y - p.y);
p = here;
}
};
this.labels = new JLabel[4];
for (int i = 0; i < this.labels.length; i++) {
this.labels[i] = new JLabel(String.valueOf(i), JLabel.CENTER);
this.labels[i].setOpaque(true);
this.labels[i].setPreferredSize(new Dimension(100, 100));
this.labels[i].setBackground(this.colors[i]);
this.labels[i].setForeground(Color.WHITE);
this.labels[i].addMouseListener(listener);
this.labels[i].addMouseMotionListener(listener);
basePanel.add(this.labels[i]);
}
this.add(basePanel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("LabelDnd");
frame.getContentPane().setLayout(new BorderLayout());
LabelDnd panel = new LabelDnd();
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
答案 0 :(得分:3)
您不会更改代码中添加或正在绘制标签的顺序。在拖动时(将其从主容器中取出后)将JLabel提升到玻璃板,然后在鼠标释放时将其重新添加到主容器中。
例如:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.*;
import java.util.Comparator;
import java.util.PriorityQueue;
import javax.swing.*;
@SuppressWarnings("serial")
public class LabelDnd extends JPanel {
private static final String X_POS = "x position";
private JLabel[] labels;
private Color[] colors = { Color.BLUE, Color.BLACK, Color.RED, Color.MAGENTA };
public LabelDnd() {
super();
// this.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JPanel basePanel = new JPanel();
basePanel.setLayout(new GridLayout(1, 4, 4, 4));
basePanel.setBackground(Color.CYAN);
MouseAdapter listener = new MouseAdapter() {
Point loc = null;
Container parentContainer = null;
Container glasspane = null;
JLabel placeHolder = new JLabel("");
private Point glassLocOnScn;
@Override
public void mousePressed(MouseEvent e) {
JComponent selectedLabel = (JComponent) e.getSource();
loc = e.getPoint();
Point currLocOnScn = e.getLocationOnScreen();
parentContainer = selectedLabel.getParent();
JRootPane rootPane = SwingUtilities.getRootPane(selectedLabel);
glasspane = (Container) rootPane.getGlassPane();
glasspane.setVisible(true);
glasspane.setLayout(null);
glassLocOnScn = glasspane.getLocationOnScreen();
Component[] comps = parentContainer.getComponents();
// remove all labels from parent
parentContainer.removeAll();
// add labels back except for selected one
for (Component comp : comps) {
if (comp != selectedLabel) {
parentContainer.add(comp);
} else {
// add placeholder in place of selected component
parentContainer.add(placeHolder);
}
}
selectedLabel.setLocation(currLocOnScn.x - loc.x - glassLocOnScn.x,
currLocOnScn.y - loc.y - glassLocOnScn.y);
glasspane.add(selectedLabel);
glasspane.setVisible(true);
parentContainer.revalidate();
parentContainer.repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
JComponent selectedLabel = (JComponent) e.getSource();
glassLocOnScn = glasspane.getLocationOnScreen();
Point currLocOnScn = e.getLocationOnScreen();
selectedLabel.setLocation(currLocOnScn.x - loc.x - glassLocOnScn.x,
currLocOnScn.y - loc.y - glassLocOnScn.y);
glasspane.repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
JComponent selectedLabel = (JComponent) e.getSource();
if (parentContainer == null || glasspane == null) {
return;
}
// sort the labels based on their x position on screen
PriorityQueue<JComponent> compQueue = new PriorityQueue<JComponent>(
4, new Comparator<JComponent>() {
@Override
public int compare(JComponent o1, JComponent o2) {
// sort of a kludge -- checking a client property that
// holds the x-position
Integer i1 = (Integer) o1.getClientProperty(X_POS);
Integer i2 = (Integer) o2.getClientProperty(X_POS);
return i1.compareTo(i2);
}
});
// sort of a kludge -- putting x position before removing component
// into a client property to associate it with the JLabel
selectedLabel.putClientProperty(X_POS, selectedLabel.getLocationOnScreen().x);
glasspane.remove(selectedLabel);
compQueue.add(selectedLabel);
Component[] comps = parentContainer.getComponents();
for (Component comp : comps) {
JLabel label = (JLabel) comp;
if (!label.getText().trim().isEmpty()) { // if placeholder!
label.putClientProperty(X_POS, label.getLocationOnScreen().x);
compQueue.add(label); // add to queue
}
}
parentContainer.removeAll();
// add back labels sorted by x-position on screen
while (compQueue.size() > 0) {
parentContainer.add(compQueue.remove());
}
parentContainer.revalidate();
parentContainer.repaint();
glasspane.repaint();
}
};
this.labels = new JLabel[4];
for (int i = 0; i < this.labels.length; i++) {
this.labels[i] = new JLabel(String.valueOf(i), JLabel.CENTER);
this.labels[i].setOpaque(true);
this.labels[i].setPreferredSize(new Dimension(100, 100));
this.labels[i].setBackground(this.colors[i]);
this.labels[i].setForeground(Color.WHITE);
this.labels[i].addMouseListener(listener);
this.labels[i].addMouseMotionListener(listener);
basePanel.add(this.labels[i]);
}
this.add(basePanel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("LabelDnd");
frame.getContentPane().setLayout(new BorderLayout());
LabelDnd panel = new LabelDnd();
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
答案 1 :(得分:1)
由于Swing组件的z-index
。拖动后,您应该使用setComponentZOrder
更改组件的z-index
值。
请查看this链接以获取更多详情