2015-03-04 18 views
5

Tôi đã tìm kiếm trên internet ví dụ về cách Kéo và Thả JButton vào một đối tượng nhưng tôi không thể làm cho nó hoạt động.Kéo và Thả từ JButton vào JComponent trong Java

Chương trình của tôi làm gì, là khi tôi nhấp vào một nút, đối tượng đã cập nhật một trường (với một selectedobject.setField()). Tôi muốn có thể làm điều này không bằng cách nhấp vào, nhưng bằng cách kéo JButton.

Tôi làm cách nào để thực hiện việc này? Tôi thấy điều này, và tôi đã cố gắng để đưa vào mã của tôi:

btn.setTransferHandler(new ImageHandler()); 
btn.addMouseListener(new MouseAdapter() { 
public void mousePressed(MouseEvent e) { 
     JComponent c = (JComponent)e.getSource(); 
     TransferHandler handler = c.getTransferHandler(); 
     handler.exportAsDrag(c, e, TransferHandler.COPY); 
      }   
}); 

tôi mất lớp ImageHandler từ here.

+0

Những gì bạn làm có nghĩa là "nhận được một giá trị mới"? Bạn có muốn kéo "giá trị" của nút lên cái gì khác không? – MadProgrammer

+0

Nút thêm hoạt ảnh vào đối tượng đã chọn. Tôi muốn có thể thêm cùng một hình động vào một đối tượng ngẫu nhiên bằng cách kéo và thả. – user3450862

Trả lời

9

Drag'n'drop là một túi cà rốt giòn, giòn ... không được hỗ trợ bởi thực tế là có API "cốt lõi" và API "chuyển" mới hơn, do đó rất dễ bị nhầm lẫn

Ví dụ sau sử dụng API "chuyển" và về cơ bản chuyển giá trị String từ nút sang số JLabel.

Drag Numbers

import java.awt.Color; 
import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.StringSelection; 
import java.awt.datatransfer.Transferable; 
import java.awt.dnd.DnDConstants; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.TransferHandler; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.CompoundBorder; 
import javax.swing.border.EmptyBorder; 
import javax.swing.border.LineBorder; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setLayout(new GridLayout(1, 2)); 
      add(createLeftPanel()); 
      add(createRightPanel()); 

     } 

     protected JPanel createLeftPanel() { 
      JPanel panel = new JPanel(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridwidth = GridBagConstraints.REMAINDER; 
      gbc.fill = GridBagConstraints.HORIZONTAL; 
      gbc.weightx = 1; 
      for (int index = 0; index < 10; index++) { 
       JButton btn = new JButton(Integer.toString(index + 1)); 
       panel.add(btn, gbc); 
       btn.setTransferHandler(new ValueExportTransferHandler(Integer.toString(index + 1))); 

       btn.addMouseMotionListener(new MouseAdapter() { 
        @Override 
        public void mouseDragged(MouseEvent e) { 
         JButton button = (JButton) e.getSource(); 
         TransferHandler handle = button.getTransferHandler(); 
         handle.exportAsDrag(button, e, TransferHandler.COPY); 
        } 
       }); 
      } 
      return panel; 
     } 

     protected JPanel createRightPanel() { 
      JPanel panel = new JPanel(new GridBagLayout()); 
      JLabel label = new JLabel("Drop in"); 
      label.setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY), new EmptyBorder(20, 20, 20, 20))); 
      label.setTransferHandler(new ValueImportTransferHandler()); 
      panel.add(label); 
      return panel; 
     } 

    } 

    public static class ValueExportTransferHandler extends TransferHandler { 

     public static final DataFlavor SUPPORTED_DATE_FLAVOR = DataFlavor.stringFlavor; 
     private String value; 

     public ValueExportTransferHandler(String value) { 
      this.value = value; 
     } 

     public String getValue() { 
      return value; 
     } 

     @Override 
     public int getSourceActions(JComponent c) { 
      return DnDConstants.ACTION_COPY_OR_MOVE; 
     } 

     @Override 
     protected Transferable createTransferable(JComponent c) { 
      Transferable t = new StringSelection(getValue()); 
      return t; 
     } 

     @Override 
     protected void exportDone(JComponent source, Transferable data, int action) { 
      super.exportDone(source, data, action); 
      // Decide what to do after the drop has been accepted 
     } 

    } 

    public static class ValueImportTransferHandler extends TransferHandler { 

     public static final DataFlavor SUPPORTED_DATE_FLAVOR = DataFlavor.stringFlavor; 

     public ValueImportTransferHandler() { 
     } 

     @Override 
     public boolean canImport(TransferHandler.TransferSupport support) { 
      return support.isDataFlavorSupported(SUPPORTED_DATE_FLAVOR); 
     } 

     @Override 
     public boolean importData(TransferHandler.TransferSupport support) { 
      boolean accept = false; 
      if (canImport(support)) { 
       try { 
        Transferable t = support.getTransferable(); 
        Object value = t.getTransferData(SUPPORTED_DATE_FLAVOR); 
        if (value instanceof String) { 
         Component component = support.getComponent(); 
         if (component instanceof JLabel) { 
          ((JLabel) component).setText(value.toString()); 
          accept = true; 
         } 
        } 
       } catch (Exception exp) { 
        exp.printStackTrace(); 
       } 
      } 
      return accept; 
     } 
    } 
} 

tôi đã đi ra ngoài đường để tách TransferHandler s cho phép một "kéo" và "thả" phiên bản. Bạn không "có" để làm điều này và bạn "có thể" sử dụng một đơn TransferHandler để thực hiện cả hai thao tác, tùy thuộc vào bạn.

Bạn sẽ phải thay đổi ValueExportTransferHandler để chấp nhận giá trị khác nhau và thay đổi SUPPORTED_DATE_FLAVOR accordingingly, nhưng đó là những điều cơ bản

Bạn cũng có thể có một cái nhìn tại Drag and Drop custom object from JList into JLabel như một ví dụ khác ...

+0

Đã xảy ra sự cố ở đó. Ý tôi là, "exportAsDrag" không nên được gọi cho * mọi sự kiện kéo đơn *, phải không? Ngay cả khi nó có thể làm việc trong thực tế. EDIT: Tôi chỉ cần chạy nó. Nó hoạt động và phương pháp mouseDragged là vì một số lý do, chỉ được thực hiện * một lần *, vì vậy tất cả dường như là tốt. –

+0

@DreamspacePresident Tại sao không? 'exportAsDrag' được gọi trên' mouseDragged', nếu không thì, khi nào nó nên được gọi? ps- Tôi nghĩ rằng bạn đang nghĩ đến 'mouseMoved';) – MadProgrammer

+0

Bởi vì các tài liệu của exportAsDrag nói "Nguyên nhân hỗ trợ kéo Swing được bắt đầu." và "Việc chuyển tiền sẽ không nhất thiết phải được hoàn thành khi trả lời cuộc gọi này (tức là cuộc gọi không chặn chờ lệnh thả)." mà, với tôi, ngụ ý rõ ràng rằng điều này được gọi là * một lần * cho mỗi D & D. Nhưng hãy xem chỉnh sửa của tôi về bình luận khác của tôi, tất cả dường như là tốt. –