我有一个包含自定义对象的ArrayList的JList,我试图创建拖放到字段中。我无法理解如何在Transferable中打包和接收对象。
据我所知:
import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.util.*; public class FlightProjectInterface extends JFrame{ //create GUI Objects private JFrame primaryFrame; private JPanel createFlightPanel; private JPanel aircraftLayout; private JList personsJList, personsOnFlightJList; private JTextField pilotLabel, coPilotLabel, backseat1Label, backseat2Label; public FlightProjectInterface(){ //establish frame super("Create Flight"); setLayout( new FlowLayout()); //aircraftPanel aircraftLayout = new JPanel(); aircraftLayout.setLayout(new GridLayout(2,2)); pilotLabel = new JTextField("Drag Pilot Here"); //build person load list DefaultListModel listModel = new DefaultListModel(); for (Person person : Database.persons) listModel.addElement(person); personsJList = new JList(listModel); personsJList.setVisibleRowCount(5); personsJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); personsJList.setDragEnabled(true); add( new JScrollPane(personsJList) ); aircraftLayout.add(pilotLabel); add(aircraftLayout); }//end constructor }
澄清:我在从JList中选择对象并从中创建一个Transferable时遇到麻烦。使用上面的代码,对象的toString表示形式只是粘贴在文本字段中,因此我无法从放置的位置提取对象数据。如何“打包”对象本身并将其放入可以从GUI引用对象本身的占位符?
理想情况下,将有4个字段,每个字段都包含一个可以删除的对象。如果将其放下,该人将从列表中删除,但如果被替换,则返回到列表中。
拖放可能是一个复杂的野兽,但可用的冲突信息并没有使它变得更容易。就个人而言,我喜欢避免使用Transfer API,但是我很老。
DnD的粘合剂确实是DataFlavor。我更喜欢自己动手,让生活更轻松。
DataFlavor
在此示例中,我使用了一个TransferHandler,但实际上,您确实应该有一个拖放对象,特别是对于要拖放到的每个组件都有一个对象。
TransferHandler
这样做的主要原因是,canImport如果您将鼠标拖到上,我会在方法中放入陷阱以拒绝它JList,因此您只能将其放在上JLabel,这是一个小技巧,可能不是最好的主意。
canImport
JList
JLabel
import java.awt.BorderLayout; import java.awt.Component; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.io.IOException; import javax.swing.DefaultListModel; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class DnDTransferableTest { public static void main(String[] args) { new DnDTransferableTest(); } public DnDTransferableTest() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } @SuppressWarnings("serial") public class TestPane extends JPanel { private JList<ListItem> list; private JLabel label; public TestPane() { list = new JList<ListItem>(); list.setDragEnabled(true); list.setTransferHandler(new ListTransferHandler()); DefaultListModel<ListItem> model = new DefaultListModel<ListItem>(); for (int index = 0; index < 10; index++) { model.addElement(new ListItem("Item " + index)); } list.setModel(model); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weighty = 1; gbc.weightx = 1; gbc.fill = GridBagConstraints.BOTH; add(new JScrollPane(list), gbc); label = new JLabel("Drag on me..."); gbc.gridx++; gbc.weightx = 1; gbc.fill = GridBagConstraints.NONE; add(label, gbc); label.setTransferHandler(new ListTransferHandler()); } } @SuppressWarnings("serial") public class ListTransferHandler extends TransferHandler { @Override public boolean canImport(TransferSupport support) { return (support.getComponent() instanceof JLabel) && support.isDataFlavorSupported(ListItemTransferable.LIST_ITEM_DATA_FLAVOR); } @Override public boolean importData(TransferSupport support) { boolean accept = false; if (canImport(support)) { try { Transferable t = support.getTransferable(); Object value = t.getTransferData(ListItemTransferable.LIST_ITEM_DATA_FLAVOR); if (value instanceof ListItem) { Component component = support.getComponent(); if (component instanceof JLabel) { ((JLabel)component).setText(((ListItem)value).getText()); accept = true; } } } catch (Exception exp) { exp.printStackTrace(); } } return accept; } @Override public int getSourceActions(JComponent c) { return DnDConstants.ACTION_COPY_OR_MOVE; } @Override protected Transferable createTransferable(JComponent c) { Transferable t = null; if (c instanceof JList) { @SuppressWarnings("unchecked") JList<ListItem> list = (JList<ListItem>) c; Object value = list.getSelectedValue(); if (value instanceof ListItem) { ListItem li = (ListItem) value; t = new ListItemTransferable(li); } } return t; } @Override protected void exportDone(JComponent source, Transferable data, int action) { System.out.println("ExportDone"); // Here you need to decide how to handle the completion of the transfer, // should you remove the item from the list or not... } } public static class ListItemTransferable implements Transferable { public static final DataFlavor LIST_ITEM_DATA_FLAVOR = new DataFlavor(ListItem.class, "java/ListItem"); private ListItem listItem; public ListItemTransferable(ListItem listItem) { this.listItem = listItem; } @Override public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{LIST_ITEM_DATA_FLAVOR}; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.equals(LIST_ITEM_DATA_FLAVOR); } @Override public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { return listItem; } } public static class ListItem { private String text; public ListItem(String text) { this.text = text; } public String getText() { return text; } @Override public String toString() { return getText(); } } }