Java (Swing): MouseMoved not working at all - java

This is driving me nuts. It must be an extremely simple problem, but I can't possibly see it.
Basically mouseMoved is NEVER called. Below is the code.
public class MouseMotionThing {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame jFrame = new JFrame();
jFrame.setContentPane(new ContentPane());
jFrame.setSize(400, 400);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
And my panel. This implementation uses a MouseInputListener:
class ContentPane extends JPanel implements MouseInputListener {
int x = 0, y = 0;
public ContentPane() {
setOpaque(true);
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, 0, x, y);
}
#Override
public void mouseDragged(MouseEvent e) {
System.out.println("Mouse Dragged!");
}
#Override
public void mouseMoved(MouseEvent e) {
System.out.println("CALLED MOUSE MOVED");
x = e.getX();
y = e.getY();
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
whereas this alternative implementation uses only a MouseMotionListener:
class ContentPane extends JPanel implements MouseMotionListener {
int x = 0, y = 0;
public ContentPane() {
setOpaque(true);
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, 0, x, y);
}
#Override
public void mouseDragged(MouseEvent e) {
System.out.println("Mouse Dragged!");
}
#Override
public void mouseMoved(MouseEvent e) {
System.out.println("CALLED MOUSE MOVED");
x = e.getX();
y = e.getY();
repaint();
}
}
In none of the above alternative implementations is mouseMoved EVER called. I'm adding the right listeners every single time, but it's simply not working. mouseDragged works fine though. What am I missing?
LE: I tested the code on Ubuntu 12.10 & JDK 7, worked fine. Then when I went back to my W8 machine, it started working. I did absolutely nothing more than restart my laptop. I couldn't reproduce the problem nor track it down, but I will come back if I get it again and manage to find something.

It's not clear where things may have gone awry; it may help to do a full build. For reference, I've re-factored your sscce to use a MouseAdapter and remove a leaking this from the JPanel.
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MouseMotionThing {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame jFrame = new JFrame();
jFrame.add(new MousePanel());
jFrame.pack();
jFrame.setSize(400, 400);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
private static class MousePanel extends JPanel {
Point p = new Point();
public MousePanel() {
setOpaque(true);
addMouseMotionListener(new MouseHandler());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, 0, p.x, p.y);
}
private class MouseHandler extends MouseAdapter {
#Override
public void mouseDragged(MouseEvent e) {
update(e);
}
#Override
public void mouseMoved(MouseEvent e) {
update(e);
}
private void update(MouseEvent e) {
System.out.println(e.paramString());
MousePanel.this.p = e.getPoint();
MousePanel.this.repaint();
}
}
}
}

I happened to come across a similar issue in one of the applications I contribute to. I couldn't find anything else that pointed to the root cause, so I started doing some Java AWT logging as illustrated on Oracle's Logging Overview page.
After analyzing parts of the file, I found that there were 5 mouse buttons being registered to the JVM:
<record>
<date>2015-06-18T15:45:54</date>
<millis>1434656754395</millis>
<sequence>70</sequence>
<logger>sun.awt.windows.WDesktopProperties</logger>
<level>FINE</level>
<class>sun.awt.windows.WDesktopProperties</class>
<method>setIntegerProperty</method>
<thread>1</thread>
<message>awt.mouse.numButtons=5</message>
</record>
I also realized that other mouse events (MOUSE_ENTERED, MOUSE_EXITED, MOUSE_DRAGGED) had a extModifiers value of Button5, which is weird because I was just using a touch pad and no other button is pressed. I'm not sure if this would prevent the MOUSE_MOVED event from being fired - I'm guessing this would take some research into lower level Java.
<record>
<date>2015-06-18T15:45:55</date>
<millis>1434656755026</millis>
<sequence>329</sequence>
<logger>java.awt.event.EventDispatchThread</logger>
<level>FINEST</level>
<class>java.awt.EventDispatchThread</class>
<method>pumpOneEventForFilters</method>
<thread>13</thread>
<message>Dispatching: java.awt.event.MouseEvent[MOUSE_ENTERED,(388,387),absolute(388,387),button=0,extModifiers=Button5,clickCount=0] on frame0</message>
</record>
I did some research on extra mouse buttons and found another Oracle page talking about Desktop Properties. I changed the startup parameters of Java to include -Dsun.awt.enableExtraMouseButtons=false, and voila, my application started working again.
I tested a very simple Java application with listening to MOUSE_MOVED on a variety of Windows JRE's, and they all exhibited the same issue when not setting this parameter.
If extra mouse buttons aren't going to be used in your application, then this may be a workaround for you.

Well, it seemed that I had those problems when I used my A4TECH G10-770F mouse on Windows 8. If I turned it off, things went back to normal. I didn't look into it in greater detail though - I already had another mouse and used that one instead.

Related

Drawing lines on canvas using Mouse without Swing in java

My Quesition is similar to this question
Drawing lines with mouse on canvas : Java awt
My problem is that When the windows is minimized and maximized , the drawn lines are gone everytime
But my working is quite different because i used only awt components and without swing.
import java.awt.*;
import java.awt.event.*;
class Drawing extends WindowAdapter implements MouseMotionListener, MouseListener, ComponentListener {
Frame f;
Canvas c;
int X=400,Y=400;
int px=-1,py=-1;
int x,y;
public Drawing() {
f=new Frame("Drawing - Canvas");
f.addWindowListener(this);
f.addComponentListener(this);
f.setSize(X,Y);
c=new Canvas();
f.add(c);
c.addMouseMotionListener(this);
c.addMouseListener(this);
f.setVisible(true);
}
public void componentResized(ComponentEvent e) {}
public void componentHidden(ComponentEvent e) {}
public void componentMoved(ComponentEvent e) {}
public void componentShown(ComponentEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseDragged(MouseEvent e) {
int x,y;
x=e.getX();
y=e.getY();
Graphics g=c.getGraphics();
if(px!=-1) {
g.drawLine(px,py,x,y);
}
else {
g.drawLine(x,y,x,y);
}
px=x;
py=y;
}
public void mouseReleased(MouseEvent e) {
this.X=400; this.Y=400;
this.px=-1; this.py=-1;
}
public void windowClosing(WindowEvent e) {
f.dispose();
}
public static void main(String[] args) {
Drawing c=new Drawing();
}
}
Can someone help me out on these problems ?
getGraphics is NEVER the write way to perform custom paint.
Start by having a read through Painting in AWT and Swing and Performing Custom Painting for a better understanding how painting works and how you should work with it.
The simple answer is, you need to maintain a model of what has been painted, so that on each paint pass you can re-draw it.
For example Resize the panel without revalidation, Draw trail of circles with mouseDragged, Why is my line not drawing?

How to set up mouse and keyboard input

Hi I'm trying to program a game using java. This is my first time using java, I am used to C#. In C# I would call Mouse.getLocation() and create a rect using the mouses location. Then by using if(Mouse.Left().toString() == "Pressed") I would then check if the mouse rect intersected with any other objects and act accordingly.
I've noticed in java you aren't provided with methods like these. So I was wondering, is the best way to approach mouse input simply to add listeners on all my clickable objects? I understand listeners and have a good idea how to use them but I was just wanting to check if there are more efficient ways to handle input or ways geared more towards what I'm most conformable with.
let your frame implement the MouseListener interface
implement all abstract methods, but in your case it is probably the mouseClicked event
identify if the button clicked is a left click, using the SwingUtilities class
if it is a left click, then set the x and y, which is the location of your click relative to the frame, not the screen.
public class MouseListeningObject extends JFrame implements MouseListener {
int x, y;
public MouseListeningObject () {
addMouseListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
if(SwingUtilities.isLeftMouseButton(e)){
x = e.getX();
y = e.getY();
}
}
#Override
public void mousePressed(MouseEvent e) {
// Some codes here
}
#Override
public void mouseReleased(MouseEvent e) {
// Some codes here
}
#Override
public void mouseEntered(MouseEvent e) {
// Some codes here
}
#Override
public void mouseExited(MouseEvent e) {
// Some codes here
}
}
You want your frame to implement MouseListener then add it in the constructor.
class MyFrame extends JFrame implements MouseListener {
MyFrame() {
addMouseListener(this);
}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
}

I am trying to develop a game using java applet, the motion of a ball halts whole of my game?

This is just the begining of the game, where there are two squares, one can be controlled by arrow keys and other by mouse, they can fire balls on each other and simultaneously can be saved, the one getting maximum hits will win...
In this code when I fire from the second square there is a long line which goes towards the second player and whole of the game has to halt..
package raship;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.io.IOException;
public class raship extends Applet implements KeyListener, MouseMotionListener, MouseListener, Runnable
{
int width,flag1=0,flag2=0,height,x1,y1,x2,y2,calc1,calc2x,calc2y;
Thread t=null;
public void init()
{
//Toolkit toolkit=Toolkit.getDefaultToolkit();
t=new Thread();
width=getSize().width;
height=getSize().height;
x1=0;y1=height/2;
x2=width-10;y2=height/2;
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
setBackground(Color.gray);
repaint();
}
public void keyPressed(KeyEvent e)
{
int c=e.getKeyCode();
System.out.println(c);
if(c==KeyEvent.VK_LEFT)
{
System.out.println("yeah it's on");
x1-=10;
}
else if(c==KeyEvent.VK_UP)
y1-=10;
else if(c==KeyEvent.VK_RIGHT)
x1+=10;
else if(c==KeyEvent.VK_DOWN)
y1+=10;
if(x1>=0 && y1>=0 && y1<=height-20 && x1<=3*width/4)
repaint();
}
public void keyReleased(KeyEvent arg0) {
}
public void keyTyped(KeyEvent arg0) {
}
public void mouseDragged(MouseEvent e) {
}
public void mouseMoved(MouseEvent e)
{
x2=e.getX();
y2=e.getY();
if(x2>=5*width/8 && x2<=width-20)
repaint();
}
public void mouseClicked(MouseEvent e)
{
flag2=1;
calc2x=x2;
calc2y=y2;
System.out.println(calc2x);
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
public void mousePressed(MouseEvent arg0) {
}
public void mouseReleased(MouseEvent arg0) {
}
public void paint(Graphics g)
{
width=getSize().width;
height=getSize().height;
g.setColor(Color.green);
g.fillRect(x1, y1, 20, 20);
g.setColor(Color.red);
g.fillRect(x2, y2, 20, 20);
if(flag2==1)
{
g.setColor(Color.yellow);
while(true)
{
calc2x-=1;
System.out.println(calc2x);
g.fillOval(calc2x,calc2y,10,10);
try {
Thread.sleep(4);
} catch (InterruptedException e) {e.printStackTrace();}
if(calc2x<10)
{
flag2=0;
break;
}
}
}
}
#SuppressWarnings("static-access")
public void run()
{
if(flag2==1)
while(true)
{
{
repaint();
System.out.println("calc2x="+calc2x);
if(calc2x<10)
{
flag2=0;
}
try
{
t.sleep(4);
} catch (InterruptedException e) {e.printStackTrace();}
calc2x-=1;
}
}
}
}
NEVER have Thread.sleep(...) in a paint method. EVER. This puts all your drawing to sleep. In fact simply calling Thread.sleep(...) in your GUI thread will be enough to put the GUI to sleep, but its worse still in a paint method, since that method must be called over and over, and needs to be blazing fast and over in the blink of an eye or less.
Instead:
Create a Swing JApplet, not an AWT Applet
Override the paintComponent method of a JPanel to do your drawing
Use a Swing Timer to do your game loop.
Edit
You state in comment:
#HovercraftFullOfEels if you can write the syntax of swing timer and swing applet it would be of great help....
You appear to be wanting me to write tutorials for you. I wish I had all the time to do that, but alas, I don't, and I feel that it would be much more efficient for both you and me for you to check out the decent tutorials with sample code that are already in existence just waiting for you to learn from. For example, please check out the following links:
The Java Tutorials, The Really Big Index
Java Applets
Using Swing Components
How to make Java Applets
How to Use Swing Timers

MouseMotionListener in child component disables MouseListener in parent component

I need help to understand the event propagation in Swing. I know that each event is handled by only one component. Thus, when I have a panel outside with some child panel inside and I add mouseListeners to both of them, the one of inside will be called. That's nice and that's the expected behavior.
But I don't understand the behavior in the following situation:
inside registers a MouseMotionListener and outside registers a MouseListener. I expect inside to consume all MouseMotionEvents and outside to receive the MouseEvents, because there is no listener for normal MouseEvents on inside. But that's not the case, inside somehow consumes all MouseEvents not only the MouseMotionEvents.
The following code illustrates the problem:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class EventTest {
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
JComponent inside = new JPanel();
inside.setBackground(Color.red);
inside.setPreferredSize(new Dimension(200,200));
MouseMotionListener mm = new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent arg0) {
System.err.println("dragged");
}
#Override
public void mouseMoved(MouseEvent arg0) {
System.err.println("moved");
}
};
// next line disables handling of mouse clicked events in outside
inside.addMouseMotionListener(mm);
JComponent outside = new JPanel();
outside.add(inside);
outside.setPreferredSize(new Dimension(300,300));
outside.addMouseListener( new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
System.err.println("clicked");
}
});
JFrame frame = new JFrame();
frame.add(outside);
frame.pack();
frame.setVisible(true);
}
});
}
}
I could work around the problem by registering a listeners on inside for all events the parent component might be interested in and then calling dispatchEvent to forward the event to the parent.
a) can someone point me to some docs, where this behavior is described? The javadocs of MouseEvent made me think that my expectations were right. So, I need a different description to understand it.
b) is there a better solution than the one sketched above?
Thanks,
Kathrin
Edit: It is still unclear, why Swing behaves this way. But as it looks, the only way to get the stuff working is to manually forward the events, I will do it.
a) By design, Java mouse events "bubble up" only if there in no mouse listener on the child component.
b) You can forward events to another component, as shown here and below.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class EventTest {
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JComponent outside = new JPanel();
JComponent inside = new JPanel();
inside.setBackground(Color.red);
inside.setPreferredSize(new Dimension(200, 200));
inside.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
System.err.println("dragged");
}
#Override
public void mouseMoved(MouseEvent e) {
System.err.println("moved inside");
outside.dispatchEvent(e);
}
});
outside.add(inside);
outside.setPreferredSize(new Dimension(300, 300));
outside.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent arg0) {
System.err.println("moved outside");
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(outside);
frame.pack();
frame.setVisible(true);
}
});
}
}
Very similar to trashgod's answer - you can use a MouseAdapter as your motion listener, and override it to forward any events you want to be handled by the parent. This should only add a minimal amount to your code.
MouseAdapter mm = new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent arg0) {
System.err.println("dragged");
}
#Override
public void mouseMoved(MouseEvent arg0) {
System.err.println("moved");
}
#Override
public void mouseClicked(MouseEvent e) {
outside.dispatchEvent(e);
}
};
// For forwarding events
inside.addMouseListener(mm);
// For consuming events you care about
inside.addMouseMotionListener(mm);
I too couldn't find any way around using the dispatchEvent(e) method. I think you're stuck with that route.
This worked out for me:
Ellipse2D mCircle = new Ellipse2D.Double(x,y,size,size);
void PassMouseEvent(MouseEvent e) {
getParent().dispatchEvent(e);
}
public void mousePressed(MouseEvent arg0) {
if(mCircle.contains(arg0.getX(), arg0.getY())) {
// Do stuff if we click on this object
} else {
// Pass to the underlying object to deal with the mouse event
PassMouseEvent(arg0);
}
}

How to "do something" on Swing component resizing?

I've a class which extends JPanel. I overwrote protected void paintComponent(Graphics g).
There is a variable which has to be recalculated when the panel's dimensions change. How do I do that in a proper way?
Like Adam Paynter suggested, you can also add an inner class to your code, like this:
class ResizeListener extends ComponentAdapter {
public void componentResized(ComponentEvent e) {
// Recalculate the variable you mentioned
}
}
The code you have entered between the innermost brackets will be executed everytime the component get resized.
Then you add this listener to your component with
myJPanel.addComponentListener(new ResizeListener());
You can get your component by using e.getComponent(). This way you can call any method of your component from inside the inner class like
e.getComponent().getWeight();
I suppose you could override the various setSize and resize methods and perform the calculation there. However, you may not find all the places where the size can be changed. You may want to have your class implement ComponentListener and simply listen to itself for resize events.
Warning: I am not a Swing expert.
Warning: I have not compiled this code.
public class MyJPanel extends JPanel implements ComponentListener {
public MyJPanel() {
this.addComponentListener(this);
}
public void paintComponent(Graphics g) {
// Paint, paint, paint...
}
public void componentResized(ComponentEvent e) {
// Perform calculation here
}
public void componentHidden(ComponentEvent e) {}
public void componentMoved(ComponentEvent e) {}
public void componentShown(ComponentEvent e) {}
}
If I understand the question correctly then you should read the section from the Swing tutorial on How to Write a Component Listener which shows you how to listen for a change in a components size.
If the calculation isn't time consuming, I would just re-calculate the value each time in paintComponent().
Otherwise, you can save a value that is the size of the component and check it against the new size in paintComponent. If the size changed, then recalculate, otherwise don't.
private Dimension size;
protected void paintComponent(Graphics g){
if (!size.equals(getSize())){
size = getSize();
// recalculate value
}
}
Or, you can do the calculation on a resize event.
//in the constructor add the line
addComponentListener(resizeListener);
private ComponentListener resizeListener = new ComponentAdapter(){
public void componentResized(ActionEvent e){
// recalculate value
}
};
The simplest way is to implement a ComponentListener:
myjpanel.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
//recalculate variable
}
});
Here, I have used a ComponentAdapter because I only intend on overriding componentResized().
Here's what I use (where CoordinatePlane is a JPanel):
I'm not an expert
public CoordinatePlane() {
setBackground(Color.WHITE);
this.addComponentListener(new ComponentAdapter(){
public void componentResized(ComponentEvent e) {
//YOUR CODE HERE
}
});
}
It resizes automatically if it's
inside a BorderLayout panel and
put there as BorderLayout.CENTER component.
If it doesn't work, you probably have forgotten one of these two.
This simple example is drawing a red circle in the resized frame....
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.*;
import java.awt.geom.*;
public class RedCircle extends JFrame implements ComponentListener {
int getWidth;
int getHeight;
public RedCircle() {
super("Red Circle");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addComponentListener(this);
pack();
setVisible(true);
}
public void componentResized(ComponentEvent e) {
getWidth = e.getComponent().getWidth();
getHeight = e.getComponent().getHeight();
Panel pane = new Panel(getWidth,getHeight);
add(pane);
}
public static void main(String[] args) {
RedCircle rc = new RedCircle();
}
public void componentMoved(ComponentEvent e) {
}
public void componentShown(ComponentEvent e) {
}
public void componentHidden(ComponentEvent e) {
}
}
class Panel extends JPanel {
int panelWidth;
int panelHeight;
public Panel(Integer getWidth,Integer getHeight) {
panelWidth = getWidth;
panelHeight = getHeight;
}
public void paintComponent(Graphics comp) {
super.paintComponent(comp);
Graphics2D comp2D = (Graphics2D) comp;
int realWidth = panelWidth - 17;
int realHeight = panelHeight - 40;
float Height = (realHeight);
float Width = (realWidth);
// draw the Red Circle
comp2D.setColor(Color.red);
Ellipse2D.Float redCircle = new Ellipse2D.Float(0F, 0F, Width, Height);
comp2D.fill(redCircle);
}
}

Categories