java move components with mouse
Asked Answered
K

4

16

I tried to make any Component draggable by simply adding mouse listeners and using the setLocation function of java.awt.Component. I started with JButton to test if it were possible the way i thought.

Here is a code example for what I am trying to do:

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);
    }
}

Somehow this fails to work properly and I don't get why. The actual distance dragged is half the distance of the mouse movement and it flickers around that distance while dragging as if two mouse positions are competing over the MouseMotionListener.

May anyone help a swing/awt noob? =) Many thanks in advance.

Edit:

Ok, so the problem was that I did not know that the event would refire at each mouse location with the position being relative(!) to the firing JComponent. So this is the corrected and working code:

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);
    }
}

Thanks Adel for your efforts and mKorbel for the link.

Kirkcudbright answered 27/1, 2012 at 16:32 Comment(2)
See also ChessBoard.Headwork
Yep, glass pane is certainly the way to go here, but I tried to keep the example as simple as possible, but still compilable. I hope this won't confuse future readers though. USE GLASSPANE! (Or a layered pane with its DRAG_LAYER)Kirkcudbright
I
13

You have to move with JComponent, I miss this definitions in voids mousePressed/mouseDragged; in other hands, there nothing better around as @[camickr][1] excellent code for ComponentMover.

Intimist answered 31/1, 2012 at 10:56 Comment(5)
Oh my god, thank you so much for that link! The first few sentances made me hit my head. ^^ I edited my post to show the correct code.Kirkcudbright
Well I could not, quite recently. ;)Kirkcudbright
+1 for ComponentMover. Saved me a lot of trouble. ThanksDerosa
I know this is old, but do you know how to get ComponentMover to work on multiple monitors?Unreserved
@Unreserved no idea right now, nor in Java8 (can't awaiting some changes in comparing with Java6), is there some issue with, then create a new question with description about issue, link to code repository, your code and Java version, event. with Native OS, maybe someone can test that :-)Intimist
P
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();
    }
}
Peder answered 22/8, 2013 at 8:8 Comment(1)
Works and adequate for what I need to do but mouse pointer is offset from the actual component when dragging? Any ideas?Derosa
A
2

Why don't you use the java Transferable interface instead?

Here's a tutorial on how to do it: http://www.javaworld.com/javaworld/jw-03-1999/jw-03-dragndrop.html

Appendicle answered 27/1, 2012 at 17:23 Comment(5)
Does java.awt.dnd support the moving animation of components? I do not need the data dropping portion of Drag and Drop (well I do need it but thats a minor problem) rather than the animation itself. The most tutorials I found only described the data transfer portion, where only the cursor indicates a drag and drop. I want the whole Component to move. (sry for my english^^)Kirkcudbright
@Kirkcudbright Transferable comes from the package java.awt.datatransfer So it can support drag and drop in awtAppendicle
Sry, but this does not answer my question, however I found a working example of a drag and drop animation(!) using java.awt.dnd and java.awt.datatransfer: link. Working through it is not fun though, since he only linked his source code.Kirkcudbright
I read through those articles but in my understanding it is not common to make a drag animation without using Graphics and drawing it manually. So I even more want my approach to work. =) If it is even possible that way, that is...Kirkcudbright
The interface i proposed to you is what we are using in your company. The only problem is that it's not me who does it, i just use it. So can't help you on that. SorryAppendicle
A
0

It is better if you would do

int X=E.getX() + button.getX();
int Y=E.getY() + button.getY();
Autopilot answered 14/11, 2013 at 15:18 Comment(1)
I don't think your answer is proper - firstly you don't provide any comment about using that snippet, and secondly you're using different letter size.Ayana

© 2022 - 2024 — McMap. All rights reserved.