I'm working through the Stanford CS106A lectures and have hit a snag in the breakout project.
After I addMouseListeners(), I cannot detect mouseMoved calls.
However if I rename mouseMoved() to mouseDragged() or mouseClicked() or mousePressed() etc, it all updates correctly. Only the moved method does not work.
No errors or alerts, just doesn't detect the mouse being moved.
Any idea why that would happen?
public void run() {
/* Add a listener for the mouse */
addMouseListeners();
label = new GLabel("Mouse x & y");
add(label, 50, 50);
/* Load the method to create the brick pattern */
createBricks();
}
/** Detect a mouse move and update something */
public void mouseMoved(MouseEvent e){
label.setLabel("Mouse: " + e.getX() + " , " + e.getY());
paddle.setLocation(e.getX(), getHeight()-PADDLE_Y_OFFSET);
}
You need to use addMouseMotionListeners();. addMouseListeners is only for the functions that you were using.
Related
Is there a way to track the value to the position of the mouse while the drag event is still running and if the value is so and so then execute some code code?
Edit: Since this confuses people. I am looking for a way to get real time data of the position of the mouse while dragging. By real time I mean finding the position of the mouse while dragging not on drag beginning or end.
You can use setOnMouseDragged();:
source.setOnMouseDragged(m->{
System.out.println("MouseScreenX:"+m.getScreenX()+", MouseScreenY:"+m.getScreenY());
System.out.println("MouseSceneX:"+m.getSceneX()+", MouseSceneY:"+m.getSceneY());
//Execute some code here(maybe it has to run in a different Thread)
//....code
//....
});
In case you are not comfortable with lambda expressions:
source.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("MouseScreenX:" + event.getScreenX() + ", MouseScreenY:" + event.getScreenY());
System.out.println("MouseSceneX:" + event.getSceneX() + ", MouseSceneY:" + event.getSceneY());
// Execute some code here(maybe it has to run in a different
// Thread)
// ...code
// ....
}
});
To execute some code while being in the drag process:
setOnMouseDragged(new EventHandler<TouchEvent>() {
#Override
public void handle(MouseEventevent) {
//your code here
}
});
what exactly do you mean with "and if the value is so and so then execute some code code?"?
I am developing a Java application where when a button in the GUI is pressed, the user can click anywhere on the screen to record the x and y coordinates where they clicked.This is done by putting an undecorated, partly transparent JFrame over the entire screen that listens for a mouse click, records the x/y coords, then closes itself upon being clicked.
Transparent JFrame class (note: extends JFrame)
setUndecorated(true);
setOpacity((float) 0.75);
W = Toolkit.getDefaultToolkit().getScreenSize().width;
H = Toolkit.getDefaultToolkit().getScreenSize().height;
setSize(W,H);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
X = e.getX();
Y = e.getY();
System.out.println(X + ":" + Y);
closed = true;
dispose();
}
});
}
public void start() {
java.awt.EventQueue.invokeLater(() -> {
this.setVisible(true);
});
}
public boolean closed = false;
public int X = -1;
public int Y = -1;
method from button press (note: extends JFrame)
setVisible(false);
click_frame.start();
while(!click_frame.closed) {
}
setVisible(true);
System.out.println(click_frame.X + "," + click_frame.Y);
The problem I am having is that the while loop hangs the entire application not just the main GUI. I want to use wait() and notifyAll() because I am trying to intentionally hang the main GUI until click_frame.X and click_frame.Y have values.
When I tried other methods without the while loop, the "click_frame JFrame class" ran alongside the main GUI, instead of blocking it, which is not what I want to happen.
My question is how can I make the main GUI use wait()/notifyAll() so it will stop while the second JFrame records the input.
Swing is a single threaded framework, this means that any long running or blocking process which is executed within the context of the Event Dispatching Thread, will prevent the framework from responding to new events
My question is how can I make the main GUI use wait()/notifyAll() so it will stop while the second JFrame records the input.
Don't. Swing, like most UI frameworks is event driven, this means, something happens (at some point in time) and you respond to it.
Instead, simply make use of a MouseListener and monitor the mouseClicked event. When it occurs, you can use the MouseEvent#getLocationOnScreen method to determine where on the screen the user clicked.
When clicked, this should then report back to the caller (via some kind of observer pattern) the results of the call.
Of course, you could cheat and simply use a modal JDialog, which will block (safely) at the point the dialog is made visible, until it is dismissed (closed)
I hava a Java swing application that use a 'pan-able' JComponent to display large data. When the user move the mouse wheel, I listen to these events, and update the content of the JComponent from the scrolled amount.
I would like to have a different behavior depending on whether the user is
using a classical mouse
using a touchpad, as the ones that can be found on modern Mac laptops.
How could I detect that the user is using the mouse wheel vs the trackpad to generate the scroll event? I am relying in java 1.6 swing, si I cannot go to javaFX.
Story behind the question:
I just wanted to add a cool inertia feel to the scrolling event when the user use the mouse wheel. But of course, on MacOSX, the trackpad has its own inertia stuff builtin. So I wanted to decide whether I should generate the inertial movement or not.
Java Swing is an old technology, it supports the traditional mouse wheel rotation events.
When you use the old wheel mouse, or wheel track-pad, it will read the rotation of the hardware wheel.
When you use a modern laser mouse, the mouse movement will be translated to rotation motion.
When you use a touch track-pad like the one in modern Mac laptops, the scroll gesture will be translated into rotation motion, single & double touch as left and right click (based on OS mouse-pad configuration).
You can use libraries to check the input devices in detail, in case your mouse or track-pad is connected to your computer through USB, you can try J-USB library.
As for internal hardware, you first have to identify the type of OS, and based on that you can get information on system and hardware in Java.
Finally, if your application interacts with a user, I suggest asking the user what type of mouse they're using, and store that in configuration file or something.
For MacOS you can get all the touchpad events in Java, I'd been searching myself for a while and just answered my own question. Leaving this here in case anyone else starts down the same rabbit hole
What replaces GestureUtilities in Java 9
Try this code
MetaDown is used for Right Click
AltDown is used for Mouse wheel
.
public class Exp extends JFrame {
private String string;
private JLabel l;
public Exp() {
super("Title");
l = new JLabel("Status");
add(l, BorderLayout.SOUTH);
addMouseListener(new MouseClass());
}
private class MouseClass extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
string = String.format("Clicked %d Times", e.getClickCount());
if(e.isMetaDown())
string += " With Right Mouse Button";
else if(e.isAltDown())
string += " With Centre Mouse Button";
else
string += " With Left Mouse Button";
l.setText(string);
}
}
}
Also try this:
you can determine which of the Mouse buttons is pressed,by these three methods from SwingUtilities:
isLeftMouseButton
isMiddleMouseButton
isRightMouseButton
The Mouse Wheel Listener API
Although MouseWheelListener has only one method, it has the corresponding adapter class — MouseAdapter. This capability enables an application to have only one adapter class instance for the component to manage all types of events from the mouse pointer.
mouseWheelMoved(MouseWheelEvent) //Called when the mouse wheel is rotated.
The following code snippet is related to the mouse-wheel event handling:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.*;
public class MouseWheelEventDemo extends JPanel
implements MouseWheelListener {
JTextArea textArea;
JScrollPane scrollPane;
static final String NEWLINE = System.getProperty("line.separator");
public static void main(String[] args) {
/* Use an appropriate Look and Feel */
try {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use of bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("MouseWheelEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new MouseWheelEventDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public MouseWheelEventDemo() {
super(new BorderLayout());
textArea = new JTextArea();
textArea.setEditable(false);
scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(400, 250));
add(scrollPane, BorderLayout.CENTER);
textArea.append("This text area displays information "
+ "about its mouse wheel events."
+ NEWLINE);
//Register for mouse-wheel events on the text area.
textArea.addMouseWheelListener(this);
setPreferredSize(new Dimension(450, 350));
setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}
//Append to the text area and make sure the new text is visible.
void eventOutput(String eventDescription, MouseWheelEvent e) {
textArea.append(e.getComponent().getClass().getName()
+ ": "
+ eventDescription);
textArea.setCaretPosition(textArea.getDocument().getLength());
}
public void mouseWheelMoved(MouseWheelEvent e) {
String message;
int notches = e.getWheelRotation();
if (notches < 0) {
message = "Mouse wheel moved UP "
+ -notches + " notch(es)" + NEWLINE;
} else {
message = "Mouse wheel moved DOWN "
+ notches + " notch(es)" + NEWLINE;
}
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
message += " Scroll type: WHEEL_UNIT_SCROLL" + NEWLINE;
message += " Scroll amount: " + e.getScrollAmount()
+ " unit increments per notch" + NEWLINE;
message += " Units to scroll: " + e.getUnitsToScroll()
+ " unit increments" + NEWLINE;
message += " Vertical unit increment: "
+ scrollPane.getVerticalScrollBar().getUnitIncrement(1)
+ " pixels" + NEWLINE;
} else { //scroll type == MouseWheelEvent.WHEEL_BLOCK_SCROLL
message += " Scroll type: WHEEL_BLOCK_SCROLL" + NEWLINE;
message += " Vertical block increment: "
+ scrollPane.getVerticalScrollBar().getBlockIncrement(1)
+ " pixels" + NEWLINE;
}
eventOutput(message, e);
}
}
The output from MouseWheelEventDemo for a system that uses unit increments for its mouse wheel might look as follows:
javax.swing.JTextArea: Mouse wheel moved UP 1 notch(es)
Scroll type: WHEEL_UNIT_SCROLL
Scroll amount: 3 unit increments per notch
Units to scroll: -3 unit increments
Vertical unit increment: 16 pixels
I want my app to detect mouse clicks anywhere on the screen without having to have the app focused. I want it to detect mouse events universally even if its minimized. So far I've only been able to detect mouse events within a swing gui.
Autohotkey can detect mouse clicks and get the mouse's position at any time, how can I do this with java?
It is possible with a little trick. Should be 100% cross-platform (tested on Linux & Windows). Basically, you create a small JWindow, make it "alwaysOnTop" and move it around with the mouse using a timer.
Then, you can record the click, dismiss the window and forward the click to the actual receiver using the Robot class.
Short left and right clicks work completely fine in my tests.
You could also simulate dragging and click-and-hold, just forwarding that seems harder.
I have code for this, but it is in my Java extension (JavaX). JavaX does translate into Java source code, so you can check out the example here.
The code in JavaX:
static int windowSize = 11; // odd should look nice. Set to 1 for an invisible window
static int clickDelay = 0; // Delay in ms between closing window and forwarding click. 0 seems to work fine.
static int trackingSpeed = 10; // How often to move the window (ms)
p {
final new JWindow window;
window.setSize(windowSize, windowSize);
window.setVisible(true);
window.setAlwaysOnTop(true);
JPanel panel = singleColorPanel(Color.red);
window.setContentPane(panel);
revalidate(window);
final new Robot robot;
panel.addMouseListener(new MouseAdapter {
// public void mousePressed(final MouseEvent e) {}
public void mouseReleased(final MouseEvent e) {
print("release! " + e);
window.setVisible(false);
int b = e.getButton();
final int mod =
b == 1 ? InputEvent.BUTTON1_DOWN_MASK
: b == 2 ? InputEvent.BUTTON2_DOWN_MASK
: InputEvent.BUTTON3_DOWN_MASK;
swingLater(clickDelay, r {
print("clicking " + mod);
robot.mousePress(mod);
robot.mouseRelease(mod);
});
}
});
swingEvery(window, trackingSpeed, r {
Point p = getMouseLocation();
window.setLocation(p.x-windowSize/2, p.y-windowSize/2);
//print("moving");
});
}
I am using this code to get the X and Y coordinates of an image placed as icon of a jLable.
This method to get the coordinates was suggested by an answer to this question.
private void lblMapMouseClicked(java.awt.event.MouseEvent evt) {
lblMap.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
double X = e.getX();
double Y = e.getY();
System.out.println("X: " + X + "Y: " + Y );
}
});
}
When I run this public void mouseClicked(MouseEvent e) { } gets called multiple times.
Exactly the amount of times I click on the image.
Eg: If I'm clicking on it for the 3rd time ,
X and Y values from the System.out.println line , gets printed 3 times.
And it increases as the number of times I click increases.
Can any of you explain why this happens? And how can I fix it? :)
The problem is that you are adding a new listener again and again when click happens, here.
private void lblMapMouseClicked(MouseEvent evt)
{
lblMap.addMouseListener(new MouseAdapter()
{
...
Instead, change your code to this.
private void lblMapMouseClicked(MouseEvent e)
{
double X = e.getX();
double Y = e.getY();
System.out.println("X: " + X + "Y: " + Y);
}
And it should fix the problem.
Hope this helps.
it looks for me that every time image is clicked new mouse listener is added.. do also
System.out.println(this)
to check from which instance of mouse listener it is actually printed
The problem with above code was you are creating new Mouse event with every click on the image.
// Create a Mouse pressed Event
mouseLis = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
actionMenthod(e);
}
};
Here am attaching the my event to lblMap.
lblMap.addMouseListener(mouseLis);
After this event happens you have to remove this event from the lblmap.
lblMap.removeMouseListener(mouseLis);
After when I click again only one event will be there then it prints only once.