Say I'm in a Java Swing JFrame. I click my mouse. I want to get the location of the mouse click within the GUI. In java, the line
int mouseX = MouseInfo.getPointerInfo().getLocation.x;
Seems to give the location of the mouse on the entire screen. How would I get it's location relative to the GUI?
From MouseListener methods you can do:
#Override
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
System.out.println(x+","+y);//these co-ords are relative to the component
}
Simply add this to your Component by:
component.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
});
Reference:
How to Write a Mouse Listener
Take a look at Component.getMousePosition.
Returns the position of the mouse pointer in this Component's coordinate space if the Component is directly under the mouse pointer, otherwise returns null. If the Component is not showing on the screen, this method returns null even if the mouse pointer is above the area where the Component would be displayed. If the Component is partially or fully obscured by other Components or native windows, this method returns a non-null value only if the mouse pointer is located above the unobscured part of the Component.
final Point mousePos = component.getMousePosition();
if (mousePos != null) {
final int mouseX = mousePos.x;
final int mouseY = mousePos.y;
...
}
... or, if you use a MouseListener, you may see my original comment...
Try using MouseEvent.getPoint.
The above will return the mouse point relative to the component to which the listener was bound.
public void mouseClicked(final MouseEvent evt) {
final Point pos = evt.getPoint();
final int x = pos.x;
final int y = pos.y;
}
You can add MouseListener to GUI component whose top left pixel should be threated as [0,0] point, and get x and y from MouseEvent
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.add(panel);
panel.addMouseListener(new MouseAdapter() {// provides empty implementation of all
// MouseListener`s methods, allowing us to
// override only those which interests us
#Override //I override only one method for presentation
public void mousePressed(MouseEvent e) {
System.out.println(e.getX() + "," + e.getY());
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
MouseEvent has methods getX() and getY() that return the position relative to the source component.
Related
Say I'm in a Java Swing JFrame. I click my mouse. I want to get the location of the mouse click within the GUI. In java, the line
int mouseX = MouseInfo.getPointerInfo().getLocation.x;
Seems to give the location of the mouse on the entire screen. How would I get it's location relative to the GUI?
From MouseListener methods you can do:
#Override
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
System.out.println(x+","+y);//these co-ords are relative to the component
}
Simply add this to your Component by:
component.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
});
Reference:
How to Write a Mouse Listener
Take a look at Component.getMousePosition.
Returns the position of the mouse pointer in this Component's coordinate space if the Component is directly under the mouse pointer, otherwise returns null. If the Component is not showing on the screen, this method returns null even if the mouse pointer is above the area where the Component would be displayed. If the Component is partially or fully obscured by other Components or native windows, this method returns a non-null value only if the mouse pointer is located above the unobscured part of the Component.
final Point mousePos = component.getMousePosition();
if (mousePos != null) {
final int mouseX = mousePos.x;
final int mouseY = mousePos.y;
...
}
... or, if you use a MouseListener, you may see my original comment...
Try using MouseEvent.getPoint.
The above will return the mouse point relative to the component to which the listener was bound.
public void mouseClicked(final MouseEvent evt) {
final Point pos = evt.getPoint();
final int x = pos.x;
final int y = pos.y;
}
You can add MouseListener to GUI component whose top left pixel should be threated as [0,0] point, and get x and y from MouseEvent
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.add(panel);
panel.addMouseListener(new MouseAdapter() {// provides empty implementation of all
// MouseListener`s methods, allowing us to
// override only those which interests us
#Override //I override only one method for presentation
public void mousePressed(MouseEvent e) {
System.out.println(e.getX() + "," + e.getY());
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
MouseEvent has methods getX() and getY() that return the position relative to the source component.
I am trying to develop a very basic game and it involves mouse. So what i am trying to do is getting coordinates of mouse to write a integer. I searched internet and find this.
mouse_x=MouseInfo.getPointerInfo().getLocation().getX();
mouse_y=MouseInfo.getPointerInfo().getLocation().getY();
It partially worked and gave me coordinates of mouse on desktop. But what i need is coordinates of mouse on frame. So if only i knew the coordinates of frame's starting (0,0) point (not the window's. the white area without toolbars.) I could calculate mouse's coordinates.
Thanks in advance.
Or if thats not possible i could use how to develop it in fullscreen.
And i need to know location of mouse always. It should refresh position when i run it in a never ending while loop.
I just use e.getPoint() which returns the point of the mouse clicked. You could either have your Frame implement MouseListener of you can register a MouseListener to the frame if it is not the main GUI component.
public class MyFrame extends JFrame implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
Point p = e.getPoint();
int x = (int) p.getX();
int y = (int) p.getY();
// do something withe the x and y points
}
}
If you do the above, you also need to override the other MouseListener methods. Though you don't need to implement any action for them
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
If your GUI class didn't extend JFrame, then you can just register the listener to the Frame, in which case you only need to use the MouseAdapter, which allows you to just implement 0 or more action method (i.e. just mouseClicked)
frame.addMouseListener(new MouseAdapter() {
void mouseClicked(MouseEvent e) {
Point p = e.getPoint();
int x = (int) p.getX();
int y = (int) p.getY();
// do somthing withe the x and y points
}
});
Edit for MouseMotionListener
"I want to know location of mouse always not just when clicked."
If you wan't to know the location of the mouse at any given time, you should implement MouseMotionListener and override the mouseDragged and mouseMoved
public class MyFrame extends JFrame implements MouseMotionListener {
....
public void mouseMoved(MouseEvent e){
Point p = e.getPoint();
int x = (int) p.getX();
int y = (int) p.getY();
// do something withe the x and y points
}
public void mouseDragged(MouseEvent e){
}
}
The mouseMoved will fire an event every time the mouse is moved, and the mouseDragged will fire an event whenever the mouse is dragged
You need to add a MouseListener to your JFrame and then you can just get the relative coordinates with MouseEvent.getPoint
frame.addMouseListener(new MouseAdapter() {
void mouseClicked(MouseEvent e) {
System.out.println(e.getPoint());
}
});
If you, for some obscure reason, need the coordinates in a situation when mouse events are not available (in which case, take a look at the other answers), you can use SwingUtilities.convertPointFromScreen() to convert the coordinates from MouseInfo to the coordinate system of a Component.
I have been searching the internet to find examples or how to use java's drag and drop. I have found a few, but all the examples only allow you to drag into a specific location, i.e another list box or text area.
I want to know if there is a way to drag items onto a jpanel or similar container, having the item put anywhere freely on the container.
As long as the target is a supported drop target for the item you are dragging then you can drop it to containers like JPanel.
You control the way the dragged item is displayed at the drop location. If your panel overrides paintComponent() then you can paint the item however you find appropriate.
'is a way to drag items into a jpanel'
You can set a DropTarget to your JPanel.
public class MyDropTarget extends JPanel implements DropTargetListener {
private MyImage image;
private String text;
public MyDropTarget() {
setBackground(new Color(30,60,10));
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, new Color(30,60,10).brighter(), new Color(30,60,10).darker() ) );
DropTarget dt = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true, null);
this.setDropTarget( dt );
}
#Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
if( image != null && image.getImage() != null ) {
g.drawImage( image.getImage(), 0, 0, null );
if(image.isError()){
g.setColor(Color.BLACK);
g.drawString( text, 0, 0 );
}
}
}
public void dragEnter( DropTargetDragEvent dtde ) {
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.RAISED, Color.RED.brighter(), Color.RED.darker() ) );
}
public void dragExit( DropTargetEvent dte ) {
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, UIManager.getColor( "MenuBar.highlight" ), UIManager.getColor( "MenuBar.shadow" ) ) );
}
public void dragOver( DropTargetDragEvent dtde ) {
}
public void drop( DropTargetDropEvent dtde ) {
try {
text = (String) dtde.getTransferable().getTransferData( DataFlavor.stringFlavor );
image = (MyImage)dtde.getTransferable().getTransferData( DataFlavor.imageFlavor );
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, new Color(30,60,10).brighter(), new Color(30,60,10).darker() ) );
dtde.dropComplete( true );
repaint();
} catch( UnsupportedFlavorException e ) {
e.printStackTrace();
} catch( IOException e ) {
e.printStackTrace();
}
this.setDropTarget( null );
}
public void dropActionChanged( DropTargetDragEvent dtde ) {
}
}
I implemented Drag&Drop in this way:
The quite convenient mechanism for the implementation of Drag&Drop has appeared in Java 6, but it does have its disadvantages. For example, you should explicitly specify a Drop Target, what is not very useful when you need to lay down the object near the Drop Target. Also in the standard implementation there is no guarantee of execution order of listeners’ methods. I'll tell you the concept of implementing a more extensible Drag&Drop.
Initially the mouse listeners (Mouse Listener and MouseMotionListener) should be assigned to all Drag Sources. It’s need to implement 3 methods: a method of mouse click on the object, a method of moving the mouse while holding the mouse button on the object (mouseDragged in MouseMotionListener) and the mouse up method.
The listeners assignment looks as follows:
component.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
//block click right mouse button
if (MouseEvent.BUTTON1 == e.getButton()) {
startDrag(e);
}
}
#Override
public void mouseReleased(MouseEvent e) {
//block click right mouse button
if (MouseEvent.BUTTON1 == e.getButton()) {
endDrag(e);
}
}
});
component.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
drag(e);
}
});
Accordingly when you click on the object Drag&Drop starts, when you move the mouse the object should be moved, when you release the mouse the object should change its position and be moved to a new container. If the object will be moved in the frame of one container, then it is possible to implement only mouseDragged () method, in which the coordinates of the dragged object will be changed:
#Override
public void mouseDragged(MouseEvent e) {
Point mouseLocation = e.getLocationOnScreen();
Component draggedComponent = (Component) e.getSource();
SwingUtilities.convertPointFromScreen(mouseLocation,
draggedComponent.getParent());
draggedComponent.setLocation(mouseLocation);
}
But dragged object coordinates can be set relative to the container in which it is located. Accordingly, when the mouse is moved to another container it is necessary to add a component to a new container and to calculate the new coordinates, etc. This method is not very beautiful and extensible, so I suggest using GlassPane to display the dragged object.
The algorithm looks as follows:
Click on the object.
Get a screenshot of the object (see how to make a screenshot).
Hide the original object.
Draw on glassPane a screenshot of the object, based on the
coordinates of the mouse.
When you move the mouse you need to redraw a screenshot according
to the new coordinates.
When you release the mouse you need to place the object on the
container under which the cursor is located.
Display the original object.
With this approach, we have no any dependences on the container on which the cursor should be placed to make Drop and correspondingly the object can be "Dropped" anywhere.
GlassPane with transparency effect:
public class GhostGlassPane extends JPanel {
private final AlphaComposite composite;
private BufferedImage ghostImage = null;
private Point location = new Point(0, 0);
public GhostGlassPane() {
setOpaque(false);
composite = AlphaComposite.getInstance(AlphaComposite.
SRC_OVER, 0.7f);
}
public void paintComponent(Graphics g) {
if (ghostImage == null)
return;
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(composite);
g2.drawImage(ghostImage, (int) (location.getX()),
(int) (location.getY()), null);
}
}
In this response only concept of implementation is given.
This information is taken from my article: Frequently Asked Questions during Java applet development
Say I'm in a Java Swing JFrame. I click my mouse. I want to get the location of the mouse click within the GUI. In java, the line
int mouseX = MouseInfo.getPointerInfo().getLocation.x;
Seems to give the location of the mouse on the entire screen. How would I get it's location relative to the GUI?
From MouseListener methods you can do:
#Override
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
System.out.println(x+","+y);//these co-ords are relative to the component
}
Simply add this to your Component by:
component.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
});
Reference:
How to Write a Mouse Listener
Take a look at Component.getMousePosition.
Returns the position of the mouse pointer in this Component's coordinate space if the Component is directly under the mouse pointer, otherwise returns null. If the Component is not showing on the screen, this method returns null even if the mouse pointer is above the area where the Component would be displayed. If the Component is partially or fully obscured by other Components or native windows, this method returns a non-null value only if the mouse pointer is located above the unobscured part of the Component.
final Point mousePos = component.getMousePosition();
if (mousePos != null) {
final int mouseX = mousePos.x;
final int mouseY = mousePos.y;
...
}
... or, if you use a MouseListener, you may see my original comment...
Try using MouseEvent.getPoint.
The above will return the mouse point relative to the component to which the listener was bound.
public void mouseClicked(final MouseEvent evt) {
final Point pos = evt.getPoint();
final int x = pos.x;
final int y = pos.y;
}
You can add MouseListener to GUI component whose top left pixel should be threated as [0,0] point, and get x and y from MouseEvent
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.add(panel);
panel.addMouseListener(new MouseAdapter() {// provides empty implementation of all
// MouseListener`s methods, allowing us to
// override only those which interests us
#Override //I override only one method for presentation
public void mousePressed(MouseEvent e) {
System.out.println(e.getX() + "," + e.getY());
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
MouseEvent has methods getX() and getY() that return the position relative to the source component.
I've got a problem in Java using a "canvas" class I created, which is an extended JPanel, to draw an animated ring chart. This chart is using a MouseListener to fetch click events.
The problem is that the mouse position does not seem to be accurate, meaning it does not seem to be relative to the "canvas" but instead relative to the window (in the left, upper corner I got about 30px for y coord).
This is my code:
I created a class, that extends JPanel and does have a BufferedImage as member.
public class Canvas extends JPanel {
public BufferedImage buf;
private RingChart _parent;
public Canvas(int width, int height, RingChart parent){
buf = new BufferedImage(width, height, 1);
...
In the paint component method I just draw the buffered image, so I am able to paint on the canvas from 'outside' by painting on the buffered image, which is public.
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(buf, null, 0, 0);
}
Now there's a class RingChart which contains a "canvas":
public class RingChart extends JFrame{
public Canvas c;
...
And I create a Graphics2D from the bufferedImage in the canvas class. This g2d is used for painting:
public RingChart(){
c = new Canvas(1500,980,this);
add(c);
setSize(1500, 1000);
setTitle("Hans");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
g2d = (Graphics2D)c.buf.createGraphics();
...
What I now was trying to achieve, was a mouse listener that listened to mouse events happening on the canvas. So when the user clicks on the canvas I could retrieve the position he clicked on, upon the canvas, through the event variable.
So I created a mouse listener:
class MouseHandler implements MouseListener {
#Override
public void mouseClicked(MouseEvent e){
RingChart r = ((Canvas)e.getSource()).getParent();
r.mouseClick(e);
}
...
...and added this mouse listener to the canvas of the RingChart class (myChart is an instance of RingChart and c is the canvas it contains):
...
MouseHandler mouse = new MouseHandler();
myChart.c.addMouseListener(mouse);
...
But as I mentioned above, the mouse position, that's returned when the click event is called, does not seem to be accurate. I think the mistake must be somehow in the way I created that mouseListener or maybe assigned it to the wrong element or something like that. But I've tried quite a couple of things and it didn't change. Can maybe someone tell me, what I've done wrong?
UPDATE:
The code of the function "mouseClick" that is a member of RingChart and is called in the mouse listener:
public void mouseClick(MouseEvent evt){
//evt = SwingUtilities.convertMouseEvent(this, evt, c);
if(evt.getButton() == MouseEvent.BUTTON1 && animation == null){
for(Element e : elements){
if(e.getShape() != null && e.getShape().contains(evt.getPoint())){
//do some stuff
}
}
}
}
Again, the hierarchy of my classes:
RingChart --contains a--> Canvas --got a--> MouseListener.
The shapes in this function are shapes that have been painted on the canvas c. Now I want to check, if the user has clicked on one of them. So as I thought, the shapes should be in canvas-coordinates and the event position should be in canvas-coordinates and everything should fit together. But it doesn't.
Now user MadProgrammer told me, to use the ConvertMouseEvent function. But I currently don't see which exact way I should use this sensibly.
UPDATE:
I found a solution: All I had to do is adding the canvas not directly to the JFrame but to the ContentPane of the JFrame instead:
So instead:
public RingChart(){
c = new Canvas(1500,980,this);
add(c);
...
I do:
public RingChart(){
c = new Canvas(1500,980,this);
getContentPane().add(c);
...
Then I give the MouseListener to the ContentPane.
getContentPane().addMouseListener(new MouseHandler());
getContentPane().addMouseMotionListener(new MouseMoveHandler());
I don't know, if this is an elegant solution, but it works.
The mouse event is automatically converted to be relative to the component that it occurred in that is, point 0x0 is always the top left corner of the component.
By using RingChart r = ((Canvas)e.getSource()).getParent(), you've effectively changed the reference, which now means the location is no longer valid.
You need to convert the location so that its coordinates are in the context of the parent component. Take a look at SwingUtilities.convertMouseEvent(Component, MouseEvent, Component)
UPDATE with PICTURES
Lets take this example...
The blue box has a relative position of 50px x 50px to the red box. If you click in the blue box, lets say at 25x25, the mouse coordinates will be relative to the blue box (0x0 will be the top left of the blue box).
If you then pass this event to the red box and try and use the coordinates from it, you will find that the coordinates will now be half way between the top left of the red box and the blue box, because the coordinates are context sensitive.
In order to get it to work, you need to translate the mouse events location from the blue box to the red box, which would make it 75x75
Now, I don't know what you're doing when you pass the mouse event to the RingChart so I'm only guessing that this is the issue you're facing.
UPDATED with Click Code
Okay, lets say, you have a Canvas at 100x100. You click on that Canvas at 50x50. You then pass that value back up the chain.
public void mouseClick(MouseEvent evt){
//evt = SwingUtilities.convertMouseEvent(this, evt, c);
if(evt.getButton() == MouseEvent.BUTTON1 && animation == null){
for(Element e : elements){
// Here, we are asking the shape if it contains the point 50x50...
// Not 150x150 which would be the relative position of the click
// in the context to the RingChart, which is where all your objects
// are laid out.
// So even the original Canvas you clicked on will return
// false because it's position + size (100x100x width x height)
// does not contain the specified point of 50x50...
if(e.getShape() != null && e.getShape().contains(evt.getPoint())){
//do some stuff
}
}
}
}
UPDATED
I think you have your references around the wrong way...
public static MouseEvent convertMouseEvent(Component source,
MouseEvent sourceEvent,
Component destination)
I think it should read something like
evt = SwingUtilities.convertMouseEvent(evt.getComponent(), evt, this);
UPDATE with Code Example
Okay, so, I put this little example together...
public class TestMouseClickPoint extends JFrame {
private ContentPane content;
public TestMouseClickPoint() throws HeadlessException {
setSize(600, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setLayout(new BorderLayout());
content = new ContentPane();
add(content);
}
protected void updateClickPoint(MouseEvent evt) {
content.updateClickPoint(evt);
}
protected class ContentPane extends JPanel {
private Point relativePoint;
private Point absolutePoint;
public ContentPane() {
setPreferredSize(new Dimension(600, 600));
setLayout(null); // For testing purpose only...
MousePane mousePane = new MousePane();
mousePane.setBounds(100, 100, 400, 400);
add(mousePane);
}
protected void updateClickPoint(MouseEvent evt) {
absolutePoint = new Point(evt.getPoint());
evt = SwingUtilities.convertMouseEvent(evt.getComponent(), evt, this);
relativePoint = new Point(evt.getPoint());
System.out.println(absolutePoint);
System.out.println(relativePoint);
repaint();
}
protected void paintCross(Graphics2D g2d, Point p) {
g2d.drawLine(p.x - 5, p.y - 5, p.x + 5, p.y + 5);
g2d.drawLine(p.x - 5, p.y + 5, p.x + 5, p.y - 5);
}
/*
* This is not recommended, but I want to paint ontop of everything...
*/
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
if (relativePoint != null) {
g2d.setColor(Color.BLACK);
paintCross(g2d, relativePoint);
}
if (absolutePoint != null) {
g2d.setColor(Color.RED);
paintCross(g2d, absolutePoint);
}
}
}
protected class MousePane extends JPanel {
private Point clickPoint;
public MousePane() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
clickPoint = e.getPoint();
TestMouseClickPoint.this.updateClickPoint(e);
repaint();
}
});
setBorder(new LineBorder(Color.RED));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE);
if (clickPoint != null) {
g2d.drawLine(clickPoint.x, clickPoint.y - 5, clickPoint.x, clickPoint.y + 5);
g2d.drawLine(clickPoint.x - 5, clickPoint.y, clickPoint.x + 5, clickPoint.y);
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
new TestMouseClickPoint().setVisible(true);
}
}
Basically, it will paint three points. The point that the mouse was clicked (relative to the source of the event), the unconverted point in the parent container and the converted point with the parent container.
The next thing you need to do is determine the mouse location is actually been converted, failing that. I'd probably need to see a working example of your code to determine what it is you're actually doing.