Is it possible to make a component able to be dragged around a frame?
If so could you give me an idea of how to do this?
Printable View
Is it possible to make a component able to be dragged around a frame?
If so could you give me an idea of how to do this?
Here is my attempt. When the component is redrawn things seem to go a bit haywire. :lol: Ill see if i can fix this.
Code:import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GUI{
public static void main(String[] args){
new GUI();
}
private JFrame gui;
private Container c;
private JButton jb;
public GUI(){
gui = new JFrame("GUI");
gui.addWindowListener(new WindowMonitor());
c = gui.getContentPane();
c.setLayout(null);
jb = new JButton("JButton");
jb.addMouseMotionListener(new X(c,jb));
jb.setBounds(new Rectangle(30, 20, 80, 40));
c.add(jb);
gui.setSize(400,400);
gui.setVisible(true);
}
}
class X extends MouseMotionAdapter{
private Container c;
private JButton jb;
int x, y;
public X(Container c,JButton jb){
this.c = c;
this.jb = jb;
}
public void mouseDragged(MouseEvent me){
jb.setLocation(me.getX(), me.getY());
}
}
class WindowMonitor extends WindowAdapter{
public void windowClosing(WindowEvent we){
System.exit(0);
}
}
There is also a java.awt.dnd.DragSourceAdapter class that can be extended but this is for dragging and dropping. You just seem to want to be able to drag a component around.
Thanks for the help. The example you gave is just what I was asking for. I'll take a look at the java.awt.dnd.DragSourceAdapter class and see what I can do with that.
I was able to fix it and make it more smoother.
Here is the code if anyone cares.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MoveButton extends JFrame implements MouseListener, MouseMotionListener
{
Point location;
MouseEvent pressed;
JButton btn;
public MoveButton()
{
btn = new JButton("Drag");
getContentPane().add(btn,BorderLayout.NORTH);
btn.addMouseMotionListener(this);
btn.addMouseListener(this);
setSize(400,400);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void mousePressed(MouseEvent e)
{
pressed = e;
}
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseDragged(MouseEvent e)
{
location = btn.getLocation(location);
int x = location.x - pressed.getX() + e.getX();
int y = location.y - pressed.getY() + e.getY();
btn.setLocation(x,y);
}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public static void main(String[] arguments)
{
MoveButton b = new MoveButton();
}
}
Very smooth. Yes yes me likes. :lol: I set the layout manager to null because contentpane uses BorderLayout as it's default layout manager. This enabled me to set dimensions of the button with out the layout manager getting in the way. Now i have plenty of space for the full drag action. :DI am interested in this piece of code though. Can you explain?Code:import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MoveButton extends JFrame implements MouseListener, MouseMotionListener{
Point location;
MouseEvent pressed;
JButton btn;
public MoveButton(){
btn = new JButton("Drag");
btn.setBounds(new Rectangle(60,50,80,40));
//getContentPane().add(btn,BorderLayout.NORTH)
getContentPane().setLayout(null);
getContentPane().add(btn);
btn.addMouseMotionListener(this);
btn.addMouseListener(this);
setSize(400,400);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void mousePressed(MouseEvent e){
pressed = e;
}
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseDragged(MouseEvent e){
location = btn.getLocation(location);
int x = location.x - pressed.getX() + e.getX();
int y = location.y - pressed.getY() + e.getY();
btn.setLocation(x,y);
}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public static void main(String[] arguments){
MoveButton b = new MoveButton();
}
}
Code:public void mouseDragged(MouseEvent e){
location = btn.getLocation(location);
int x = location.x - pressed.getX() + e.getX();
int y = location.y - pressed.getY() + e.getY();
btn.setLocation(x,y);
}
It is an interesting piece of code, especially when you try and break it down to have better undestanding of it. Here is my explanation - hope its clear enough:
location = btn.getLocation(location);
location.x is set to btn's x coordinate
location.y is set to btn's y coordinate
Well say that the location of btn is the upper left corner of the frame - so that would be 0,0
which means:
location = 0,0
int x = location.x - pressed.getX() + e.getX();
btnLocation - were we pressed + were we drag to;
(location.x - pressed.getX()) :
what this does is if you pressed in the middle of the button it sets it back to the top left corner of the button when the pressed coordinate is subtracted by the location.x
Then you would have :
int x = 0(or what the top left cord is) + e.getX(){were we drag to}
So after this :
int x = the coordinates of were you dragged the button to and the top left corner of the buttons Xcoordinate now equal that.
Then you do the same for the y coord.
A simpler way would be the example you gave: just set the coordinates of the button to the coordinate of the mouse when your dragging but of course we found out there is some problems with that.
So this example makes it much smoother, although I'm not sure why it works better than the example you gave.
Im sorry if this is not clear enough
:(
I like the idea of setting the layout manager to null:bigyello: never thought of that.
location = btn.getLocation(location);
This threw me off because a new Point object created invoking it's empty
constructor constructs and initializes a point at the origin (0, 0) of
the coordinate space. But in the MoveButton class a Point type is
only declared and not initialized. btn.getLocation(Point p) returns
a Point which does infact initalize the Point type but a null reference is still being passed to the getLocation(Point p) method.
Code:import java.awt.*;
public class RefTest{
private Point p1 = new Point(50,50);
private Point p2;
public static void main(String[] args){
RefTest ref = new RefTest();
String x1 = ref.p1.equals(null)? "p1 is null": "p1 is not null";
System.out.println(x1);
String x2 = ref.equals(null)? "ref is null": "ref is not null";
System.out.println(x2);
/* NullPointerException
String x3 = ref.p2.equals(null)? "p2 is null": "p2 is not null";
System.out.println(x3);
*/
}
}
Quote:
Posted by System_Error
Well say that the location of btn is the upper left corner of the frame - so that would be 0,0
(location.x - pressed.getX()) :
what this does is if you pressed in the middle of the button it sets it back to the top left corner of the button when the pressed coordinate is subtracted by the location.x
If the button is set at 0/0 ie btn.setBounds(new Rectangle(0,0,80,40));Code:public void mousePressed(MouseEvent e){
location = btn.getLocation(location);
System.out.print(String.valueOf
location.x) +"-"+ String.valueOf
(e.getX()));
}
then you pretty much end up with a negative x value unless the mouse is presssed at x = 0 within the buttons bounds. Right? :confused:
I actually confused myself when trying to explain the code. So im sorry my explanation was a little bit off.:blush: I think this is what it basicly does
The MouseEvent is the location of the mouse as it is being dragged, not the location of the actual component being dragged. So you can't just use code like this(what we were doing before):
x = e.getX();
y = e.getY();
btn.setLocation(x,y);
So the position of the component changes with the change in the mouse position.
I was wrong about the math. At first I was taking it as the top right corner of the frame ended up at the mouse position, but I was wrong:blush: srry bout that!!