2014-12-02 41 views
2

好吧,所以我設置瞭如下。我有一個使用javax.swing的java 1.7項目。這是我在接下來的教程之外的第一個項目,它是那些熟悉桌面的人的主動跟蹤器。我有一個擴展JPanel的類(並且實現了Comparable <>),所以我可以動態地添加它併爲每個類添加故事不同的數據。爪哇,拖放改變面板的順序

面板被添加到佈局,其y位置取決於已經有多少面板。它們也被添加到ArrayList中按順序對它們進行排序。 該列表可以按類的其中一個屬性進行排序。

我現在遇到的問題是我想要手動拖放它們來更改佈局和ArrayList中的順序。還有一個附加說明,我不能刪除並重新添加一個,因爲我將失去班級中保存的值。

走向爲此我做了需要做下面的一個JButton:

  • 只要按下鼠標按鈕,面板屬於需要用鼠標拖動。
  • 當鼠標被釋放時,它需要檢查它的位置,如果有必要的話去那個位置。

So for example

我嘗試過的一些下降,拖累教程,但我似乎無法找到一個我可以調整到我想要的東西。

編輯1:這是我試過的。

MouseListener listener = new DragMouseAdapter(); 
dragButton.addMouseListener(listener); 
dragButton.setTransferHandler(new TransferHandler("text")); 

然後

class DragMouseAdapter extends MouseAdapter { 
    public void mousePressed(MouseEvent e) { 
     JComponent c = (JComponent) e.getSource(); 
     TransferHandler handler = c.getTransferHandler(); 
     handler.exportAsDrag(c, e, TransferHandler.COPY); 
     // TODO make it a swap location drag and drop 
    } 
} 

這是從一個教程,它成功地改變了文本和所有,但不是在所有我想要什麼,我不知道如何去改變它最多做我想做的事。

編輯2:This tutorial描述了我想要做的,除非它不起作用。它給出了以下錯誤:

Step 1 of 7: Mouse pressed. Going to export our RandomDragAndDropPanel so that it is draggable. 
Step 2 of 7: Returning the acceptable TransferHandler action. Our RandomDragAndDropPanel accepts Copy only. 
Step 3 of 7: Casting the RandomDragAndDropPanel as Transferable. The Transferable RandomDragAndDropPanel will be queried for acceptable DataFlavors as it enters drop targets, as well as eventually present the target with the Object it transfers. 
Step 4 of 7: Querying for acceptable DataFlavors to determine what is available. Our example only supports our custom RandomDragAndDropPanel DataFlavor. 
Problem lazy loading: RandomDragAndDropPanel 
java.lang.ClassNotFoundException: RandomDragAndDropPanel 
    at java.lang.Class.forName0(Native Method) 
    at java.lang.Class.forName(Unknown Source) 
    at java.awt.datatransfer.DataFlavor.tryToLoadClass(Unknown Source) 
    at java.awt.datatransfer.DataFlavor.initialize(Unknown Source) 
    at java.awt.datatransfer.DataFlavor.<init>(Unknown Source) 
    at DnD.DragAndDropPanelsDemo.getDragAndDropPanelDataFlavor(DragAndDropPanelsDemo.java:197) 
    at DnD.RandomDragAndDropPanel.getTransferDataFlavors(DragAndDropPanelsDemo.java:392) 
    at sun.awt.datatransfer.DataTransferer.getFormatsForTransferable(Unknown Source) 
    at sun.awt.dnd.SunDragSourceContextPeer.startDrag(Unknown Source) 
    at java.awt.dnd.DragSource.startDrag(Unknown Source) 
    at java.awt.dnd.DragSource.startDrag(Unknown Source) 
    at java.awt.dnd.DragGestureEvent.startDrag(Unknown Source) 
    at javax.swing.TransferHandler$DragHandler.dragGestureRecognized(Unknown Source) 
    at java.awt.dnd.DragGestureRecognizer.fireDragGestureRecognized(Unknown Source) 
    at javax.swing.TransferHandler$SwingDragGestureRecognizer.gestured(Unknown Source) 
    at javax.swing.TransferHandler.exportAsDrag(Unknown Source) 
    at DnD.DraggableMouseListener.mousePressed(DragAndDropPanelsDemo.java:456) 
    at java.awt.Component.processMouseEvent(Unknown Source) 
    at javax.swing.JComponent.processMouseEvent(Unknown Source) 
    at java.awt.Component.processEvent(Unknown Source) 
    at java.awt.Container.processEvent(Unknown Source) 
    at java.awt.Component.dispatchEventImpl(Unknown Source) 
    at java.awt.Container.dispatchEventImpl(Unknown Source) 
    at java.awt.Component.dispatchEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) 
    at java.awt.Container.dispatchEventImpl(Unknown Source) 
    at java.awt.Window.dispatchEventImpl(Unknown Source) 
    at java.awt.Component.dispatchEvent(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue$4.run(Unknown Source) 
    at java.awt.EventQueue$4.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
+0

請,你能不能發佈您的嘗試,這樣我們可以幫助你找出什麼是錯的? – BackSlash 2014-12-02 08:54:15

+0

我將編輯它,但問題大部分不是我的代碼不工作,但我不知道代碼應該是什麼。 – 2014-12-02 08:57:05

回答

3

這裏是拖放以更改面板順序(不支持排序)的示例。

enter image description here

  1. DragMouseAdapter#mouseDragged(...):搜索拖動面板,刪除形式父面板和打開的遊標的窗口。
  2. DragMouseAdapter#mouseReleased(...):搜索放置位置,插入拖動面板,關閉光標窗口。
import java.awt.*; 
import java.awt.dnd.*; 
import java.awt.event.*; 
import java.net.*; 
import java.util.*; 
import javax.swing.*; 

public class RearrangeOrderOfPanelsTest2 { 
    public JComponent makeUI() { 
    Box box = Box.createVerticalBox(); 
    DragMouseAdapter dh = new DragMouseAdapter(); 
    box.addMouseListener(dh); 
    box.addMouseMotionListener(dh); 

    int idx = 0; 
    for (JComponent c : Arrays.asList(
      new JLabel("<html>111<br>11<br>11"), 
      new JButton("2"), new JCheckBox("3"), new JTextField(14))) { 
     box.add(createToolbarButton(idx++, c)); 
    } 
    JPanel p = new JPanel(new BorderLayout()); 
    p.add(box, BorderLayout.NORTH); 
    return p; 
    } 

    private static JComponent createToolbarButton(int i, JComponent c) { 
    JLabel l = new JLabel(String.format(" %04d ", i)); 
    l.setOpaque(true); 
    l.setBackground(Color.RED); 
    JPanel p = new JPanel(new BorderLayout()); 
    p.setBorder(BorderFactory.createCompoundBorder(
        BorderFactory.createEmptyBorder(5, 5, 5, 5), 
        BorderFactory.createLineBorder(Color.BLUE, 2))); 
    p.add(l, BorderLayout.WEST); 
    p.add(c); 
    p.setOpaque(false); 
    return p; 
    } 

    public static void main(String... args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override public void run() { 
     createAndShowGUI(); 
     } 
    }); 
    } 

    public static void createAndShowGUI() { 
    JFrame f = new JFrame(); 
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    f.getContentPane().add(new RearrangeOrderOfPanelsTest2().makeUI()); 
    f.setSize(320, 240); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
    } 
} 

class DragMouseAdapter extends MouseAdapter { 
    private static final int xoffset = 16; 
    private static final Rectangle R1 = new Rectangle(); 
    private static final Rectangle R2 = new Rectangle(); 
    private static Rectangle prevRect; 
    private final JWindow window = new JWindow(); 
    private Component draggingComonent; 
    private int index = -1; 
    private Component gap; 
    private Point startPt; 
    private Point dragOffset; 
    private final int gestureMotionThreshold = DragSource.getDragThreshold(); 

    public DragMouseAdapter() { 
    super(); 
    window.setBackground(new Color(0, true)); 
    } 

    @Override public void mousePressed(MouseEvent e) { 
    JComponent parent = (JComponent) e.getComponent(); 
    if (parent.getComponentCount() <= 1) { 
     startPt = null; 
     return; 
    } 
    startPt = e.getPoint(); 
    } 

    private void startDragging(JComponent parent, Point pt) { 
    //get a dragging panel 
    Component c = parent.getComponentAt(pt); 
    index = parent.getComponentZOrder(c); 
    if (Objects.equals(c, parent) || index < 0) { 
     return; 
    } 
    draggingComonent = c; 
    Dimension d = draggingComonent.getSize(); 

    Point dp = draggingComonent.getLocation(); 
    dragOffset = new Point(pt.x - dp.x, pt.y - dp.y); 

    //make a dummy filler 
    gap = Box.createRigidArea(d); 
    swapComponentLocation(parent, c, gap, index); 

    //make a cursor window 
    window.add(draggingComonent); 
    window.pack(); 

    updateWindowLocation(pt, parent); 
    window.setVisible(true); 
    } 

    private void updateWindowLocation(Point pt, JComponent parent) { 
    Point p = new Point(pt.x - dragOffset.x, pt.y - dragOffset.y); 
    SwingUtilities.convertPointToScreen(p, parent); 
    window.setLocation(p); 
    } 

    private static int getTargetIndex(Rectangle r, Point pt, int i) { 
    int ht2 = (int)(.5 + r.height * .5); 
    R1.setBounds(r.x, r.y,  r.width, ht2); 
    R2.setBounds(r.x, r.y + ht2, r.width, ht2); 
    if (R1.contains(pt)) { 
     prevRect = R1; 
     return i - 1 > 0 ? i : 0; 
    } else if (R2.contains(pt)) { 
     prevRect = R2; 
     return i; 
    } 
    return -1; 
    } 
    private static void swapComponentLocation(
     Container parent, Component remove, Component add, int idx) { 
    parent.remove(remove); 
    parent.add(add, idx); 
    parent.revalidate(); 
    parent.repaint(); 
    } 

    @Override public void mouseDragged(MouseEvent e) { 
    Point pt = e.getPoint(); 
    JComponent parent = (JComponent) e.getComponent(); 

    //MotionThreshold 
    double a = Math.pow(pt.x - startPt.x, 2); 
    double b = Math.pow(pt.y - startPt.y, 2); 
    if (draggingComonent == null && 
     Math.sqrt(a + b) > gestureMotionThreshold) { 
     startDragging(parent, pt); 
     return; 
    } 
    if (!window.isVisible() || draggingComonent == null) { 
     return; 
    } 

    //update the cursor window location 
    updateWindowLocation(pt, parent); 
    if (prevRect != null && prevRect.contains(pt)) { 
     return; 
    } 

    //change the dummy filler location 
    for (int i = 0; i < parent.getComponentCount(); i++) { 
     Component c = parent.getComponent(i); 
     Rectangle r = c.getBounds(); 
     if (Objects.equals(c, gap) && r.contains(pt)) { 
     return; 
     } 
     int tgt = getTargetIndex(r, pt, i); 
     if (tgt >= 0) { 
     swapComponentLocation(parent, gap, gap, tgt); 
     return; 
     } 
    } 
    parent.remove(gap); 
    parent.revalidate(); 
    } 

    @Override public void mouseReleased(MouseEvent e) { 
    startPt = null; 
    if (!window.isVisible() || draggingComonent == null) { 
     return; 
    } 
    Point pt = e.getPoint(); 
    JComponent parent = (JComponent) e.getComponent(); 

    //close the cursor window 
    Component cmp = draggingComonent; 
    draggingComonent = null; 
    prevRect = null; 
    startPt = null; 
    dragOffset = null; 
    window.setVisible(false); 

    //swap the dragging panel and the dummy filler 
    for (int i = 0; i < parent.getComponentCount(); i++) { 
     Component c = parent.getComponent(i); 
     if (Objects.equals(c, gap)) { 
     swapComponentLocation(parent, gap, cmp, i); 
     return; 
     } 
     int tgt = getTargetIndex(c.getBounds(), pt, i); 
     if (tgt >= 0) { 
     swapComponentLocation(parent, gap, cmp, tgt); 
     return; 
     } 
    } 
    if (parent.getParent().getBounds().contains(pt)) { 
     swapComponentLocation(parent, gap, cmp, parent.getComponentCount()); 
    } else { 
     swapComponentLocation(parent, gap, cmp, index); 
    } 
    } 
} 
+0

這確實是我想要的,它不支持排序並不是什麼大事,我可能稍後在我自己中添加。但是,問題是我不明白代碼的哪一部分做什麼,幾乎沒有解釋什麼是爲什麼或者爲什麼使用某些東西。你能詳細說明一下嗎? – 2014-12-02 10:40:31

+0

向源代碼添加一些註釋以解釋'DragMouseAdapter'。 – aterai 2014-12-02 11:37:17