【问题标题】:Unexpected actionPerformed after a drag意外的操作在拖动后执行
【发布时间】:2013-07-05 08:54:34
【问题描述】:

当我将 ActionListeners 与 Drag'n'Drop 结合使用时,我遇到了意外的行为。

运行以下示例并尝试以下操作:

  1. 将按钮 A 拖动到某处并释放鼠标按钮
  2. 不要再将鼠标移到按钮 A 上
  3. 点击按钮B
  4. 在 System.out 上,您会看到按钮 AB 都会调用 actionPerformed

我不想为按钮 A 调用 actionPerformed。我究竟做错了什么?

这是完整的例子:

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.io.IOException;
import javax.swing.*;

public class DragDropTest{

private static Color slightlyRed = new Color(255, 220, 220);
private static Color slightlyGreen = new Color(220, 255, 220);

private static class DragDropButton extends JButton implements DragSourceListener, DragGestureListener, Transferable, ActionListener{
    private DragSource dragSource;

    public DragDropButton(String string) {
        super(string);
        addActionListener(this);
        dragSource = new DragSource();
        dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, this);
    }

    // Interface DragSourceListener
    @Override public void dragEnter(DragSourceDragEvent dsde) {}
    @Override public void dragOver(DragSourceDragEvent dsde) {}
    @Override public void dropActionChanged(DragSourceDragEvent dsde) {}
    @Override public void dragExit(DragSourceEvent dse) {}
    @Override public void dragDropEnd(DragSourceDropEvent dsde) {
        System.out.println("Dragging of [" + getText() + "] ended");
    }
    // Interface DragGestureListener
    @Override public void dragGestureRecognized(DragGestureEvent dge) {
        dragSource.startDrag(dge, DragSource.DefaultMoveDrop, this, this);
    }
    // Interface Transferable
    @Override public DataFlavor[] getTransferDataFlavors() {return null;}
    @Override public boolean isDataFlavorSupported(DataFlavor flavor) {return false;}
    @Override public Object getTransferData(DataFlavor flavor)
            throws UnsupportedFlavorException, IOException {return null;}
    // Interface ActionListener
    @Override public void actionPerformed(ActionEvent e) {
        System.out.println("Action on [" + getText() + "]");
    }
}

private static class DropPanel extends JPanel implements DropTargetListener{

    public DropPanel(){
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
        setPreferredSize(new Dimension(300, 300));
        setBackground(slightlyGreen);

        new DropTarget(this, this);
    }

    @Override public void dragEnter(DropTargetDragEvent dtde) {}
    @Override public void dragOver(DropTargetDragEvent dtde) {}
    @Override public void dropActionChanged(DropTargetDragEvent dtde) {}
    @Override public void dragExit(DropTargetEvent dte) {}
    @Override public void drop(DropTargetDropEvent dtde) {
        System.out.println("Drop complete");
        dtde.dropComplete(true);
    }

}



// Create Panels

private static JPanel leftSide(){
    JPanel leftPanel = new JPanel();
    leftPanel.setPreferredSize(new Dimension(300, 300));
    leftPanel.setBackground(slightlyRed);
    leftPanel.add(new DragDropButton("A"));
    leftPanel.add(new DragDropButton("B"));
    return leftPanel;
}
private static JPanel rightSide(){
    JPanel leftPanel = new DropPanel();
    return leftPanel;
}

// Create Window

private static JFrame boringFrame(String text){

    JFrame boringFrame = new JFrame(text);
    boringFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    boringFrame.getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER));

    boringFrame.setVisible(true);
    return boringFrame;
}

public static void main(String[] args){

    JFrame boringFrame = boringFrame("boring");

    boringFrame.add(leftSide());
    boringFrame.add(rightSide());   // try to comment out this line!
    boringFrame.pack();


}

}

我的项目中还有一些问题,但我不会用它们来打扰你,因为这似乎是我问题的主要来源,但这是我的另一个观察结果:

如果没有 DropTargetListener(如我的 DropPanel),问题就会消失。尝试注释掉以下行:

boringFrame.add(rightSide());

【问题讨论】:

  • 您是否希望发生鼠标拖动事件而不是执行操作?
  • 拖动事件按预期发生。之前拖动的按钮的附加 actionPerformed 让我很困扰。
  • 因此您可以将鼠标拖动事件侦听器添加到表单而不是按钮。
  • “表格”是什么意思?顺便说一句:user2471439 已经帮助了我,但还是感谢您的支持
  • 放置按钮的 JframeForm。

标签: java swing drag-and-drop actionlistener


【解决方案1】:

问题是按钮单击的鼠标释放处理和拖动处理之间的冲突。您可以通过在您的dragGestureRecognized() 中调用getModel().setArmed(false) 来解决它。这告诉按钮在下次将按下的属性设置为 false 时不要触发操作。

缺点是按钮点击并不意味着拖动,但无论如何都会触发拖动,因为用户稍微移动鼠标,不会导致按钮点击。另一方面,对于可拖动按钮,无论如何用户的意图在这种情况下都不太清楚。

【讨论】:

  • 谢谢!这有帮助!而且我不认为这是一个缺点,“返回”拖动不会触发 actionPerformed。我会称之为功能:-)
猜你喜欢
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-04
相关资源
最近更新 更多