2012-12-13 22 views
8

我有一個JList包含自定義對象的ArrayList,我試圖創建一個拖放到字段。我無法理解如何在Transferable中打包和接收對象。從JList拖放自定義對象到JLabel

這是關於據我已經得到了:

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中的對象選擇和創建可轉讓出來。使用上面的代碼,對象的toString表示只是簡單地粘貼到文本字段中,所以我無法從丟棄的位置提取對象數據。我如何「包裝」對象本身並將其放入可以從GUI引用對象本身的佔位符中?

理想情況下,會有4個字段,每個字段都包含可以被刪除的對象。如果這個人被丟棄,這個人將被從列表中刪除,但如果被替換,則會返回到列表中。

+0

*「我無法理解如何在Transferable中打包和接收對象。」*請參閱[拖放和數據傳輸](http://docs.oracle.com/javase/tutorial /uiswing/dnd/index.html),當您嘗試並可以提出具體問題時,請回到我們這裏。 –

+0

我一直在讀它幾個小時。我無法從JList中選擇對象並創建一個可移植的對象。使用上面的代碼,對象的toString表示只是簡單地粘貼在文本字段中,所以我無法從放置的位置獲取對象數據。 –

+0

'無法找到符號 符號:變量數據庫 位置:類FlightProjectInterface' - 爲了更好地幫助更快,發佈[SSCCE](http://sscce.org/)。 –

回答

15

拖放可能是一個複雜的野獸,並不容易通過可用的衝突信息。就我個人而言,我喜歡避開Transfer API,但我是那樣的老派。

對DnD的膠水確實是DataFlavor。我更喜歡自己動手,讓生活變得更輕鬆。

在這個例子中,我使用了一個TransferHandler,但實際上,您確實應該有一個用於拖動和一個用於放置,特別是您應該爲每個要放置的組件設置一個。

主要的原因是,我放個陷阱,我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(); 
     } 
    } 
} 
+0

這正是我所尋找的,完美解釋!謝謝! –

+0

你是指單個'Transferable'還是單個'TransferHandler'? – johnchen902

+0

@ johnchen902誰知道我的意思,我認爲你的權利,這聽起來像TransferHandler – MadProgrammer