Java使用鼠标移动组件

16

我尝试通过添加鼠标监听器和使用java.awt.ComponentsetLocation函数来使任何组件可拖动。我从JButton开始测试是否可以按照我想象的方式实现。

这里是一个示例代码,展示了我正在尝试做的事情:

import java.awt.*;
import javax.swing.*;

public class DragButton extends JButton{

private volatile int draggedAtX, draggedAtY;

public DragButton(String text){
    super(text);
    setDoubleBuffered(false);
    setMargin(new Insets(0, 0, 0, 0));
    setSize(25, 25);
    setPreferredSize(new Dimension(25, 25));

    addMouseListener(new MouseAdapter(){
        public void mousePressed(MouseEvent e){
            draggedAtX = e.getX() - getLocation().x;
            draggedAtY = e.getY() - getLocation().y;
        }
    });

    addMouseMotionListener(new MouseMotionAdapter(){
        public void mouseDragged(MouseEvent e){
            setLocation(e.getX() - draggedAtX, e.getY() - draggedAtY);
        }
    });
}

public static void main(String[] args){
    JFrame frame = new JFrame("DragButton");
    frame.setLayout(null);
    frame.getContentPane().add(new DragButton("1"));
    frame.getContentPane().add(new DragButton("2"));
    frame.getContentPane().add(new DragButton("3"));
    frame.setSize(300, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    }
}
一些问题出现了,我不知道为什么会这样。拖动的实际距离是鼠标移动距离的一半,并且在拖动时它会闪烁该距离,就像两个鼠标位置在竞争MouseMotionListener一样。
能否有人帮忙解决swing/awt的问题吗?=) 提前致谢。
编辑: 好的,问题在于我不知道事件会在每个鼠标位置重新触发,并且位置是相对于触发JComponent的位置。所以这是已校正并运行的代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class DragButton extends JButton{

    private volatile int draggedAtX, draggedAtY;

    public DragButton(String text){
        super(text);
        setDoubleBuffered(false);
        setMargin(new Insets(0, 0, 0, 0));
        setSize(25, 25);
        setPreferredSize(new Dimension(25, 25));

        addMouseListener(new MouseAdapter(){
            public void mousePressed(MouseEvent e){
                draggedAtX = e.getX();
                draggedAtY = e.getY();
            }
        });

        addMouseMotionListener(new MouseMotionAdapter(){
            public void mouseDragged(MouseEvent e){
                setLocation(e.getX() - draggedAtX + getLocation().x,
                        e.getY() - draggedAtY + getLocation().y);
            }
        });
    }

    public static void main(String[] args){
        JFrame frame = new JFrame("DragButton");
        frame.setLayout(null);
        frame.getContentPane().add(new DragButton("1"));
        frame.getContentPane().add(new DragButton("2"));
        frame.getContentPane().add(new DragButton("3"));
        frame.setSize(300, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

感谢 Adel 的努力和 mKorbel 提供的链接。


请参见ChessBoard - trashgod
1
是的,玻璃窗格绝对是在这里前进的道路,但我试图让示例尽可能简单,但仍然可以编译。 我希望这不会困惑未来的读者。使用GLASSPANE!(或其DRAG_LAYER的分层窗格) - Stephan
4个回答

13

您需要使用JComponent来移动,我想在mousePressed/mouseDragged方法中添加这些定义;另一方面,没有比@[camickr][1]ComponentMover更好的代码了。


哦天啊,非常感谢你提供的链接!前几个句子让我感到很头痛。^^我已经编辑了我的帖子以展示正确的代码。 - Stephan
最近我做不到, ;) - Stephan
+1 给 ComponentMover。省了我很多麻烦。谢谢。 - Emmanuel John
我知道这很老了,但是你知道如何让ComponentMover在多个显示器上工作吗? - Ryan
@Ryan 目前没有头绪,Java8 也不行(与 Java6 相比有一些变化,无法等待),如果有问题,请创建一个新的问题,并描述问题,链接到代码库、你的代码和 Java 版本,甚至包括本地操作系统,也许有人可以测试 :-) - mKorbel

5
import javax.swing.*;
import java.awt.event.*;    

public class movingButton extends JFrame{

    private JButton button ;

    public movingButton ()
    {
     super("Position helper");
       super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       super.setSize(500,520);
       super.setVisible(true);
       super.setLayout(null);
       button = new JButton ("drag me ");
       add(button);
       button.setBounds(100, 100, 150, 40);         
       button.addMouseMotionListener(new MouseAdapter(){

            public void mouseDragged(MouseEvent E)
            {
               int X=E.getX()+button.getX();
               int Y=E.getY()+button.getY;
               button.setBounds(X,Y,150,40);
            }
        });
    }

    public static void main (String x[])
    {           
        new movingButton();
    }
}

工作正常,对我需要做的事情来说足够了,但是拖动时鼠标指针与实际组件有偏移?有什么想法吗? - Emmanuel John

2

java.awt.dnd是否支持组件的移动动画?我不需要拖放的数据丢弃部分(好吧,我确实需要它,但那只是个小问题),而是仅需要动画本身。我找到的大多数教程只描述了数据传输部分,其中只有光标指示拖放。我想要整个组件移动。(对我的英语感到抱歉^^) - Stephan
@Stephan Transferable来自包_java.awt.datatransfer_,因此它可以支持_awt_中的拖放。 - Adel Boutros
抱歉,这并没有回答我的问题,但我找到了一个使用java.awt.dnd和java.awt.datatransfer的拖放动画的工作示例(!):链接。不过,阅读这个示例并不有趣,因为他只提供了源代码链接。 - Stephan
我阅读了那些文章,但在我的理解中,不使用Graphics并手动绘制的情况下进行拖动动画并不常见。所以我更希望我的方法能够奏效。=) 如果这种方式真的可行的话... - Stephan
我向您提出的界面是贵公司正在使用的。唯一的问题是,不是我做的,我只是使用它。所以对此无法帮助您。抱歉。 - Adel Boutros

0

如果你这样做会更好

int X=E.getX() + button.getX();
int Y=E.getY() + button.getY();

我认为你的回答不太合适 - 首先,你没有提供任何有关使用该片段的评论,其次,你使用了不同的字母大小写。 - Eel Lee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接