本文介绍了使用DnD在JPanel中移动和重新排序JLabel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我有一个正在使用的程序,该程序使用输入名称并创建JLabel并将其填充到ArrayList中。当用户单击开始按钮时,JLabel将填充在左侧的JPanel中。我一直在尝试使用DnD来允许用户在左侧面板中拖动标签并重新排序。到目前为止,我只能将其从一个标签复制到另一个标签。我的目标是在列表中向上或向下拖动标签,并根据其在JPanel中的放置位置,让其余JLabel在面板中向上或向下移动。我在面板上使用了FlowLayout,标签的宽度足以创建垂直对齐方式。这是我的代码: import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.TransferHandler; import javax.swing.border.Border; 公共类Gui扩展了JFrame { / ** * * / private static final long serialVersionUID = 1L; private ArrayList< JLabel>玩家=新的ArrayList< JLabel>(); private ArrayList< JLabel> monsters =新的ArrayList< JLabel>(); 私人JButton addPlayer = new JButton(); 私人JButton removePlayer = new JButton(); 私人JButton addMonster = new JButton(); 私人JButton removeMonster = new JButton(); 私人JTextField名称= new JTextField(); 私人JPanel listPanel = new JPanel(); private JPanel buttonPanel = new JPanel(); 私人JButton遇到=新的JButton(); 私人JButton begin = new JButton(); //私有JButton移除; // = new JButton(); int x_pressed; int y_pressed; 公共Gui(){超级( D& D Initiative); final Container container = getContentPane(); container.setLayout(new FlowLayout()); //更改为GridBagLayout container.setPreferredSize(new Dimension(800,500)); listPanel.setPreferredSize(new Dimension(600,500)); listPanel.setBackground(Color.BLUE); listPanel.setOpaque(true); buttonPanel.setPreferredSize(new Dimension(200,500)); buttonPanel.setBackground(Color.GREEN); buttonPanel.setOpaque(true); 维度大小=新维度(190,30); name.setPreferredSize(new Dimension(190,30)); addPlayer.setText( Add Player); removePlayer.setText(删除播放器); addPlayer.setPreferredSize(size); removePlayer.setPreferredSize(size); addMonster.setText(添加怪物); removeMonster.setText( Remove Monster); addMonster.setPreferredSize(size); removeMonster.setPreferredSize(size); begin.setText( Begin Encounter); begin.setPreferredSize(size); buttonPanel.add(name); buttonPanel.add(addPlayer); buttonPanel.add(addMonster); buttonPanel.add(removePlayer); buttonPanel.add(removeMonster); buttonPanel.add(开始); 最后的Border paddingBorder = BorderFactory.createEmptyBorder(0,10,0,0); addPlayer.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ if(name.getText()。compareToIgnoreCase()!= 0) { final JLabel temp = new JLabel(); temp.setPreferredSize(new Dimension(590,50)); temp.setText(name.getText()); temp.setBackground(Color.GRAY); temp.setForeground(Color.WHITE); temp.setOpaque(true); temp.setLayout(new BorderLayout()); temp.setBorder(BorderFactory.createCompoundBorder(null,paddingBorder)); //bPane.setPreferredSize(new Dimension(100,temp.getHeight())); JButton remove = new JButton(); remove.setText( Remove); remove.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ System.out。 println(听众人数: +(((JButton)e.getSource())。getActionListeners()。length); //调试 listPanel.remove(temp); listPanel.revalidate(); System.out.println( remove); listPanel.repaint(); } }); temp.add(删除,BorderLayout.EAST); MouseListener监听器= new DragMouseAdapter(); temp.setTransferHandler(new TransferHandler( text)); temp.addMouseListener(listener); player.add(temp); name.setText(); name.requestFocusInWindow(); } else { //抛出错误} } }); begin.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ for(int i = 0; i< players.size(); i ++) { JLabel h = player.get(i); h.setMinimumSize(new Dimension(590,30)); int s = container.getHeight()/ players.size() ; if(s< 50){ h.setPreferredSize(new Dimension(590,listPanel.getHeight()/(players.size()+ 1))); } else { h.setPreferredSize(new Dimension(590,30)); } listPanel.add(h,new Integer(1),0); } listPanel.revalidate(); } }); container.add(listPanel); container.add(buttonPanel); pack(); //包装框架以使其适合 setLocation(150,150);中的容器; //在监视器上设置位置 setVisible(true); setResizable(false); } / ** * @param args * / public static void main(String [] args){ // TODO自动生成的方法存根 Gui application = new Gui(); application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } } //拖放开始 类DragMouseAdapter扩展MouseAdapter { public void mousePressed( MouseEvent e){ JComponent c =(JComponent)e.getSource(); TransferHandler处理程序= c.getTransferHandler(); handler.exportAsDrag(c,e,TransferHandler.COPY); System.out.println(c); } } 仍有一些事情来自不同的尝试(例如未使用的变量)。解决方案考虑使用 JList 比创建自己的标签组件要多,它具有很多巧妙的功能,可以简化您的生活,例如拖放... 看看如何使用列表以获取更多详细信息。 拖放操作是一个非常复杂的API,一开始可能会造成混乱,而 Transfer API的加入并没有帮助,这只会增加混乱。 p> 在这种情况下, Transfer API正是您要寻找的... import java.awt.EventQueue; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.activation.ActivationDataFlavor; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; 公共类DragList { public static void main(String [] args){ new DragList(); } public DragList(){ EventQueue.invokeLater(new Runnable(){ @Override public void run(){试试{ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){ ex.printStackTrace(); } DefaultListModel< String> listModel = new DefaultListModel<>(); listModel.addElement( Clara Holmes); listModel.addElement( Bill Moss); listModel.addElement( Della Reeves); listModel.addElement( Lloyd Gross); listModel.addElement( Cecilia Floyd); listModel.addElement( Delia Cummings); listModel .addElement( Tommy Benson); listModel.addElement(柯克·凯西); listModel.addElement( Chester Manning); listModel.addElement( Elsa Chapman); JList namesList = new JList(listModel); namesList.setDragEnabled(true); namesList.setDropMode(DropMode.ON_OR_INSERT); namesList.setTransferHandler(new ListItemTransferHandler()); JFrame frame = new JFrame( Testing); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(namesList)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } 公共类ListItemTransferHandler扩展了TransferHandler { 私有DataFlavor风格; public ListItemTransferHandler(){ super( ListMove); flavour = new ActivationDataFlavor(int []。class,DataFlavor.javaJVMLocalObjectMimeType,值列表); } @Override 受保护Transferable createTransferable(JComponent c){ System.out.println( createTransferable); JList list =(JList)c; DefaultListModel< String>模型=(DefaultListModel< String>)list.getModel(); int [] selectedValues = list.getSelectedIndices(); List< ValuePair>值=新的ArrayList<>(selectedValues.length); for(int index:selectedValues){ values.add(new ValuePair(index,model.getElementAt(index)));; } 返回新的ListOfValues(values); } @Override public boolean canImport(TransferSupport support){ boolean canImport = support.isDrop()&& support.isDataFlavorSupported(flavor); return canImport; } @Override public int getSourceActions(JComponent c){ return MOVE; } @Override public boolean importData(TransferSupport support){ boolean import = false; if(canImport(support)){ JList目标=(JList)support.getComponent(); target.clearSelection(); JList.DropLocation dl =(JList.DropLocation)support.getDropLocation(); DefaultListModel< String>模型=(DefaultListModel< String>)target.getModel(); int addIndex = dl.getIndex(); if(addIndex< 0 || addIndex> = model.size()){ addIndex = model.size(); } 试试{ List< ValuePair>值=(List< ValuePair>)support.getTransferable()。getTransferData(flavor); for(ValuePair vp:values){ int index = vp.getIndex(); 字符串值= model.get(index); model.add(addIndex,value); target.addSelectionInterval(addIndex,addIndex); addIndex ++; } import = true; } catch(UnsupportedFlavorException | IOException ex){ ex.printStackTrace(); } } 进口退货; } @Override protected void exportDone(JComponent source,Transferable data,int action){ if(action == MOVE){ JList列表=(JList)源; DefaultListModel< String>模型=(DefaultListModel< String>)list.getModel(); try { //获取值列表并以降序排序 List< ValuePair>值=(List< ValuePair>)data.getTransferData(flavor); Collections.sort(值,新Comparator< ValuePair>(){ @Override public int compare(ValuePair o1,ValuePair o2){ return o2.getIndex()- o1.getIndex(); } }); //遍历每个项目... for(ValuePair vp:values){ //获取值的最后已知索引... 字符串modelValue = model.get(vp.getIndex()); 字符串值= vp.getValue(); int index = vp.getIndex(); //如果值不再位于其最后一个位置,我们需要找到它, //我们不能依赖包含,因为存在两个相同值的值... if(modelValue!= value){ //看我们后面,只有先前选择的值的长度... int startIndex = Math.max(vp.getIndex()-values.size(),0); int endIndex = vp.getIndex(); index = getIndexFor(value,model,startIndex,endIndex); if(index< 0){ //向前看,仅是先前选择的值的长度... endIndex = Math.min( vp.getIndex()+ values.size(),model.size()-1); startIndex = vp.getIndex(); index = getIndexFor(value,model,startIndex,endIndex); } } if(index< 0){ //我们丢失了该项? 抛出新的IOException(缺少值?); }否则{ model.remove(index); } } } catch(UnsupportedFlavorException | IOException ex){ ex.printStackTrace(); } } } protected int getIndexFor(String value,DefaultListModel< String>模型,int startIndex,int endIndex){ while(model.get(startIndex)!= value&& startIndex< = endIndex){ startIndex ++; } return model.get(startIndex)== value? startIndex:-1; } 公共类ValuePair { private int index; 私有字符串值; public ValuePair(int index,String value){ this.index = index; this.value = value; } public int getIndex(){返回索引; } public String getValue(){返回值; } } 公共类ListOfValues实现可转让{{b $ b private List< ValuePair>价值观 public ListOfValues(List< ValuePair>值){ this.values =值; } @Override public DataFlavor [] getTransferDataFlavors(){ return new DataFlavor [] {flavor}; } @Override public boolean isDataFlavorSupported(DataFlavor flavour){ return Arrays.asList(getTransferDataFlavors())。contains(flavor); } @Override public Object getTransferData(DataFlavor flavour)抛出UnsupportedFlavorException,IOException {返回值; } } } } 看看演示-BasicDnD 用于另一个演示,以及有关传输API的更多信息。 I have a program I'm working on that takes input names and creates JLabels and populates them into an ArrayList. When the user clicks the Begin button, the JLabels populate in the left JPanel. What I've been trying to do it use DnD to allow the user to drag and re-order the labels in the left panel. So far, I've only been able to get it to copy the text from one label to another. My goal is to drag a label up or down in the list, and depending on where it's dropped in the JPanel, have the remaining JLabels move up or down in the panel. I'm using a FlowLayout for the panel, and the labels are wide enough to create vertical alignment. Here is my code:import java.awt.BorderLayout;import java.awt.Color;import java.awt.Container;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.util.ArrayList;import javax.swing.BorderFactory;import javax.swing.JButton;import javax.swing.JComponent;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JTextField;import javax.swing.TransferHandler;import javax.swing.border.Border;public class Gui extends JFrame {/** * */private static final long serialVersionUID = 1L;private ArrayList<JLabel> players = new ArrayList<JLabel>();private ArrayList<JLabel> monsters = new ArrayList<JLabel>();private JButton addPlayer = new JButton();private JButton removePlayer = new JButton();private JButton addMonster = new JButton();private JButton removeMonster = new JButton();private JTextField name = new JTextField();private JPanel listPanel = new JPanel();private JPanel buttonPanel = new JPanel();private JButton encounter = new JButton();private JButton begin = new JButton();//private JButton remove;// = new JButton();int x_pressed;int y_pressed;public Gui(){ super("D&D Initiative"); final Container container = getContentPane(); container.setLayout(new FlowLayout()); //change to GridBagLayout container.setPreferredSize(new Dimension(800, 500)); listPanel.setPreferredSize(new Dimension(600, 500)); listPanel.setBackground(Color.BLUE); listPanel.setOpaque(true); buttonPanel.setPreferredSize(new Dimension(200,500)); buttonPanel.setBackground(Color.GREEN); buttonPanel.setOpaque(true); Dimension size = new Dimension(190,30); name.setPreferredSize(new Dimension(190,30)); addPlayer.setText("Add Player"); removePlayer.setText("Remove Player"); addPlayer.setPreferredSize(size); removePlayer.setPreferredSize(size); addMonster.setText("Add Monster"); removeMonster.setText("Remove Monster"); addMonster.setPreferredSize(size); removeMonster.setPreferredSize(size); begin.setText("Begin Encounter"); begin.setPreferredSize(size); buttonPanel.add(name); buttonPanel.add(addPlayer); buttonPanel.add(addMonster); buttonPanel.add(removePlayer); buttonPanel.add(removeMonster); buttonPanel.add(begin); final Border paddingBorder = BorderFactory.createEmptyBorder(0,10,0,0); addPlayer.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ if(name.getText().compareToIgnoreCase("") != 0){ final JLabel temp=new JLabel(); temp.setPreferredSize(new Dimension(590,50)); temp.setText(name.getText()); temp.setBackground(Color.GRAY); temp.setForeground(Color.WHITE); temp.setOpaque(true); temp.setLayout(new BorderLayout()); temp.setBorder(BorderFactory.createCompoundBorder(null,paddingBorder)); //bPane.setPreferredSize(new Dimension(100,temp.getHeight())); JButton remove = new JButton(); remove.setText("Remove"); remove.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ System.out.println("Count of listeners: " + ((JButton) e.getSource()).getActionListeners().length); //debugging listPanel.remove(temp); listPanel.revalidate(); System.out.println("remove"); listPanel.repaint(); } }); temp.add(remove, BorderLayout.EAST); MouseListener listener = new DragMouseAdapter(); temp.setTransferHandler(new TransferHandler("text")); temp.addMouseListener(listener); players.add(temp); name.setText(""); name.requestFocusInWindow(); }else{ //throw error } } }); begin.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ for(int i=0;i<players.size();i++){ JLabel h = players.get(i); h.setMinimumSize(new Dimension(590,30)); int s = container.getHeight()/players.size(); if(s < 50){ h.setPreferredSize(new Dimension(590,listPanel.getHeight()/(players.size()+1))); }else{ h.setPreferredSize(new Dimension(590,30)); } listPanel.add(h, new Integer(1), 0); } listPanel.revalidate(); } }); container.add(listPanel); container.add(buttonPanel); pack(); // pack the frame to fit the container inside setLocation(150, 150); // set the location on the monitor setVisible(true); setResizable(false);}/** * @param args */public static void main(String[] args) { // TODO Auto-generated method stub Gui application = new Gui(); application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}}//start of drag and dropclass DragMouseAdapter extends MouseAdapter { public void mousePressed(MouseEvent e) { JComponent c = (JComponent) e.getSource(); TransferHandler handler = c.getTransferHandler(); handler.exportAsDrag(c, e, TransferHandler.COPY); System.out.println(c); }}There are a few things in there still from different attempts (such as unused variables). 解决方案 Consider using a JList rather than creating you own component of labels, this has a lot of neat functionality that will just make your life simpler, like drag and drop...Have a look at How to Use Lists for more details.Drag and Drop is quite a complex API and can be quite confusing to begin with, which isn't helped by the inclusion of the "Transfer API" which just adds to the confusion.Having said that, the "Transfer API" is exactly what you're look for in this case...import java.awt.EventQueue;import java.awt.datatransfer.DataFlavor;import java.awt.datatransfer.Transferable;import java.awt.datatransfer.UnsupportedFlavorException;import java.io.IOException;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;import javax.activation.ActivationDataFlavor;import javax.swing.DefaultListModel;import javax.swing.DropMode;import javax.swing.JComponent;import javax.swing.JFrame;import javax.swing.JList;import javax.swing.JScrollPane;import javax.swing.TransferHandler;import javax.swing.UIManager;import javax.swing.UnsupportedLookAndFeelException;public class DragList { public static void main(String[] args) { new DragList(); } public DragList() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } DefaultListModel<String> listModel = new DefaultListModel<>(); listModel.addElement("Clara Holmes"); listModel.addElement("Bill Moss"); listModel.addElement("Della Reeves"); listModel.addElement("Lloyd Gross"); listModel.addElement("Cecilia Floyd"); listModel.addElement("Delia Cummings"); listModel.addElement("Tommy Benson"); listModel.addElement("Kirk Casey"); listModel.addElement("Chester Manning"); listModel.addElement("Elsa Chapman"); JList namesList = new JList(listModel); namesList.setDragEnabled(true); namesList.setDropMode(DropMode.ON_OR_INSERT); namesList.setTransferHandler(new ListItemTransferHandler()); JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(namesList)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class ListItemTransferHandler extends TransferHandler { private DataFlavor flavor; public ListItemTransferHandler() { super("ListMove"); flavor = new ActivationDataFlavor(int[].class, DataFlavor.javaJVMLocalObjectMimeType, "List of values"); } @Override protected Transferable createTransferable(JComponent c) { System.out.println("createTransferable"); JList list = (JList) c; DefaultListModel<String> model = (DefaultListModel<String>) list.getModel(); int[] selectedValues = list.getSelectedIndices(); List<ValuePair> values = new ArrayList<>(selectedValues.length); for (int index : selectedValues) { values.add(new ValuePair(index, model.getElementAt(index))); } return new ListOfValues(values); } @Override public boolean canImport(TransferSupport support) { boolean canImport = support.isDrop() && support.isDataFlavorSupported(flavor); return canImport; } @Override public int getSourceActions(JComponent c) { return MOVE; } @Override public boolean importData(TransferSupport support) { boolean imported = false; if (canImport(support)) { JList target = (JList) support.getComponent(); target.clearSelection(); JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); DefaultListModel<String> model = (DefaultListModel<String>) target.getModel(); int addIndex = dl.getIndex(); if (addIndex < 0 || addIndex >= model.size()) { addIndex = model.size(); } try { List<ValuePair> values = (List<ValuePair>) support.getTransferable().getTransferData(flavor); for (ValuePair vp : values) { int index = vp.getIndex(); String value = model.get(index); model.add(addIndex, value); target.addSelectionInterval(addIndex, addIndex); addIndex++; } imported = true; } catch (UnsupportedFlavorException | IOException ex) { ex.printStackTrace(); } } return imported; } @Override protected void exportDone(JComponent source, Transferable data, int action) { if (action == MOVE) { JList list = (JList) source; DefaultListModel<String> model = (DefaultListModel<String>) list.getModel(); try { // Get the list of values and sort in decending order List<ValuePair> values = (List<ValuePair>) data.getTransferData(flavor); Collections.sort(values, new Comparator<ValuePair>() { @Override public int compare(ValuePair o1, ValuePair o2) { return o2.getIndex() - o1.getIndex(); } }); // Loop through for each item... for (ValuePair vp : values) { // Get the "last known" index of the value... String modelValue = model.get(vp.getIndex()); String value = vp.getValue(); int index = vp.getIndex(); // If the value no long resides at it's last location, we need to find it, // we can't rely on contains, as there are two values of the same value... if (modelValue != value) { // Look behind us, only the length of the number of values that were previously selected... int startIndex = Math.max(vp.getIndex() - values.size(), 0); int endIndex = vp.getIndex(); index = getIndexFor(value, model, startIndex, endIndex); if (index < 0) { // Look forward, only the length of the number of values that were previously selected... endIndex = Math.min(vp.getIndex() + values.size(), model.size() - 1); startIndex = vp.getIndex(); index = getIndexFor(value, model, startIndex, endIndex); } } if (index < 0) { // We lost the item ?? throw new IOException("Missing value?"); } else { model.remove(index); } } } catch (UnsupportedFlavorException | IOException ex) { ex.printStackTrace(); } } } protected int getIndexFor(String value, DefaultListModel<String> model, int startIndex, int endIndex) { while (model.get(startIndex) != value && startIndex <= endIndex) { startIndex++; } return model.get(startIndex) == value ? startIndex : -1; } public class ValuePair { private int index; private String value; public ValuePair(int index, String value) { this.index = index; this.value = value; } public int getIndex() { return index; } public String getValue() { return value; } } public class ListOfValues implements Transferable { private List<ValuePair> values; public ListOfValues(List<ValuePair> values) { this.values = values; } @Override public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{flavor}; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { return Arrays.asList(getTransferDataFlavors()).contains(flavor); } @Override public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { return values; } } }}Take a look at Demo - BasicDnD for another demo as well as more information on the transfer API in general. 这篇关于使用DnD在JPanel中移动和重新排序JLabel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!