源代码:
public class LabelDnd扩展了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(); 指向这里= e.getLocationOnScreen(); c.setLocation(l.x + here.x - p.x,l.y + here.y - p.y); p =这里; } }; this.labels = new JLabel [4]; (int i = 0; i< this.labels.length; i ++){ this.labels [i] = new JLabel(String.valueOf(i),JLabel) 中央); 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); } }); } }解决方案
你不会更改标签在代码中添加或正在绘制的顺序。考虑将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; 私人JLabel []标签; 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; 容器parentContainer = null; 容器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(); 组件[] comps = parentContainer.getComponents(); //从父中删除所有标签parentContainer.removeAll(); //添加标签,除了选定的一个(Component comp:comps){ if(comp!= selectedLabel){ parentContainer.add ); } else { //添加占位符代替所选组件 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; } //根据屏幕上的x位置对标签进行排序 PriorityQueue< JComponent> compQueue = new PriorityQueue< JComponent>( 4,new Comparator< JComponent>(){ @Override public int compare(JComponent o1,JComponent o2){ //排序一个kludge - 检查客户端属性 //持有x位置整数i1 =(整数)o1.getClientProperty(X_POS); 整数i2 =(整数)o2.getClientProperty(X_POS); return i1pareTo(i2); } }); //排序一个kludge - 将x位置删除组件 //到客户端属性中以将其与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()){//如果占位符! label.putClientProperty(X_POS,label.getLocationOnScreen()。x); compQueue.add(label); //添加到队列} } parentContainer.removeAll(); //添加由屏幕上的x位置排序的标签 while(compQueue.size()> 0){ parentContainer.add(compQueue.remove()) ; } parentContainer.revalidate(); parentContainer.repaint(); glasspane.repaint(); } }; this.labels = new JLabel [4]; (int i = 0; i< this.labels.length; i ++){ this.labels [i] = new JLabel(String.valueOf(i),JLabel) 中央); 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); } }); } }
I've written a basic DnD program that has four JLabels in a row. I've noticed that when I drag a label to the left, it is displayed below the next label. However, when I drag the label to the right, it is displayed above the next label. The labels are added in order, left to right. So the dragged label is being displayed below other labels that were added before the dragged label, and displayed above other labels that were added after the dragged label. Can anyone explain why this happens? Can anyone offer a fix so that the dragged label is displayed above the other labels? Thanks.
source code:
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); } }); } }解决方案
You are not changing the order that the labels have been added or are being painted in your code. Consider elevating the JLabel to the glasspane when dragging (after removing it from the main container), and then re-adding it to the main container on mouse release.
For example:
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 i1pareTo(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); } }); } }
更多推荐
DnD
发布评论