MouseListener called multiple times - java

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.

Related

I want to get coordinates of x and y using mouse adapter and insert into an array. But only two values are getting updated every time in whole array

I want to enter the X and Y coordinates of mouse adapter to array . But whenever I insert them into array using for loop, the whole array is getting filled with same value. How can I insert X and Y coordinates to the array every time the JPanel is clicked?
Code:
addMouseListener(new MouseAdapter () {
public void mouseClicked(MouseEvent e) {
setBackground(Color.RED);
int k[]=new int[18];
int l[]=new int[18];
for(int i=0;i<=17;i++) {
k[i]=e.getX();
l[i]=e.getY();
}
}
});
It's not clear from the OP where the data is meant to be going. Assuming it's being used elsewhere then -
// NOTE: perhaps use CopyOnWriteArrayList or synchronize all
// use of clicks for MT safety..
final List<Point> clicks = new ArrayList<Point>();
X.addMouseListener(new MouseAdapter () {
public void mouseClicked(MouseEvent e) {
setBackground(Color.RED);
clicks.add(e.getPoint());
}
});
Each time the mouse is clicked another point is added to the clicks array.
HT to #AndrewThompson

JLabel graphic changes at wrong time

I have a slot machine program with some graphics, and the graphic is supposed to change when you pull the lever and for some reason it changes the graphic after it goes through all of the other code first. Have a look:
Declare images:
static ImageIcon jImage = new ImageIcon("C:\\Users\\Harry\\Desktop\\jackpotLeverNotPulled.png");
static ImageIcon jackpot1 = new ImageIcon("C:\\Users\\Harry\\Desktop\\jackpotimage1.png");
static ImageIcon jackpotPulled = new ImageIcon("C:\\Users\\Harry\\Desktop\\jackpotLeverPulled.png");
Now I add to panel:
static JLabel jlb = new JLabel(jImage);
Now I want the image to change when a certain area is clicked on my panel but the main jackpot code runs first and then the image changes:
public void mousePressed(MouseEvent e) {
// Returns the X coordinate of where the mouse was click on the panel
System.out.println("X Coordinate: " + e.getX() );
// Returns the Y coordinate of where the mouse was click on the panel
System.out.println("Y Coordinate: " + e.getY() );
System.out.println();
Scanner ansr = new Scanner(System.in);
String yesno;
int random = (int)(Math.random() * 21 );
int percentCheck = (int)(Math.random() * 10 );
if (e.getX ()>975 && e.getX ()<1159 && e.getY ()>82 && e.getY ()<218){
jlb.setIcon(jackpotPulled);
if (cashMoneyz<1) {
System.out.println("Insufficient funds");
image1.setIcon(jackpot1);
} else {
System.out.println("One dollar has been removed from you slot machine balance");
cashMoneyz--;
try {
System.out.println("Spinning...");
Thread.sleep(1000);
System.out.println("Spinning...");
Thread.sleep(1000);
System.out.println("SPINNINGGGGG...OMG SOOO INTENSE");
Thread.sleep(1000);
} catch (InterruptedException ie)
{
}
}
System.out.println("You have this much money (in dollars) left in your slot machine balance: " + cashMoneyz);
System.out.println("");
System.out.println("----------------------------------------------------------------------------------");
}
It does the if statements and try catches and only changes the graphic to jackpotPulled at the end of everything.
Thanks in advance :)
There are basically 2 problems in your code:
1)
A call to label.setImage() won't update immediately, as this is true for everything in AWT and Swing. Any time a repaint request is fired, it is simply added to a repaint queue, that will wait patiently for all other tasks done in the EDT (Event Dispatching Thread) to finish. But since you do other things in the mousePressed(), they will run first. A simple solution for this would be to do the computing in mouseReleased(). But a bigger problem exists.
2)
What you are currently doing is "starving" the EDT - a bad programming practice - as all screen related invocations must be executed immediately. Sleeping the EDT won't allow any repaints to take place while running. This is true for any long running tasks as well.
Its solution is to run the non-painting calls in a different thread:
private volatile boolean isComputing = false;
public void mousePressed(MouseEvent evt) {
if(isComputing)
return;
isComputing = true;
// .
// .
// .
// change icon here, or any
// other swing related change.
// .
// .
// run game
new Thread(){
public void run(){
// all non-swing computations
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// change back icons,
// and some other swing updates
}
}
isComputing = false;
}
}.start();
}
An event handler (mousePressed) souldn't take a long time to complete, there should be no sleeps in it. As long as it runs (or sleeps), nothing else can happen. The runtime is waiting for the handler to return and displays the image after that. I would move most of the code to a function called by a timer, and use a state variable to keep track of how intensely the wheels are spinning.

Java - Mouse out of window

How do I know if the mouse if out of the window I made and from which side it exited. I'm making a classic pong game and when I move my mouse out too fast, the 'thing' stays some pixels in. I'd like it to move to the edge of the window where it exited.
private class MouseMotion extends MouseAdapter{
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
int x = e.getX();
p1.move(x);
}
}
and the move function
public void move(int x) {
if (x < 0 ) {
this.x = 0;
}else if(x+width > Main.screenSize.width - 1){
this.x = Main.screenSize.width - width - 1;
} else {
this.x = x;
}
}
I just need to know a way to know if the mouse is out of the window.
Check for MouseListener.mouseExited(MouseEvent).
You might want to take a look this:
Point mouse = MouseInfo.getPointerInfo().getLocation();
This tells you were the pointer is on the screen. No matter if your application has the focus or not. No matter if the pointer in on top of your window or not.
You can use MouseExited() and then get the coordinate from the event generated, using event.getPoint().
Try putting this somewhere where it will get run and getting rid of the MouseMotion class. 'c' is the JComponent that p1 is getting drawn to, I don't know what you called that object in your code. 'running' is some boolean that is set to true. When this code is run, p1 will move according to the mouse until 'running' is set to false.
new Thread(()->{
while(running) {
p1.move(MouseInfo.getPointerInfo().getLocation().getX()-c.getLocationOnScreen());
}
}).start();

Jobjects on top of existing object

so I would like to know if it's possible to put things like buttons, text boxes, words, progress bars, ect, ect, on top of an already existing, in this example, JLabel.
Here is the image of the undercoated frame I made, followed by the snippet of code that is associated with this undercoated frame.
(I dont have 10 reputation, so here is a link to a photo)
http://prntscr.com/15516f
Map.setTitle("Map");
Map.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Map.setUndecorated(true);
Map.setBackground(new Color(0,0,0,0));
Map.setLayout(new FlowLayout());
JLabel Background = new JLabel(new ImageIcon(getClass().getResource("Map.png")));
Background.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
initialClick = e.getPoint();
getComponentAt(initialClick);
}
});
Background.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
// get location of Window
int thisX = Map.getLocation().x;
int thisY = Map.getLocation().y;
// Determine how much the mouse moved since the initial click
int xMoved = (thisX + e.getX()) - (thisX + initialClick.x);
int yMoved = (thisY + e.getY()) - (thisY + initialClick.y);
// Move window to this position
int X = thisX + xMoved;
int Y = thisY + yMoved;
Map.setLocation(X, Y);
}
});
Map.add(Background);
Map.setSize(507,512);
Map.setLocation(0, 100);
Map.setResizable(false);
Map.setVisible(false);
on a side note, and I KNOW this is FlowLayout(), but when I try to add something else, it'll just put itself above, or below my map.
I'd just like to know if I could put things on top of this Map.
Maybe I should put the image in in another way besides the JLabel?
Look into JLayeredPane and similar strategies. See How to Use Layered Panes for more details.

JavaFX - Drawing a line between two nodes

I am busying writing a simple application using JavaFX2. The goal is just to plot 2 nodes (the nodes are movable by dragging them) and then have a function to draw lines between these nodes.
I finished the functions to add and move nodes (at the moment I am just using Ellipse shapes but I am going to replace it later with my own node class) but now I am struggling with the connecting lines. The actions to add a node or a line is from a dropdown menu and I have the following code on the line function:
private void drawLine(MenuItem line) {
final BooleanProperty lineActive = new SimpleBooleanProperty(false);
final BooleanProperty clickOne = new SimpleBooleanProperty(false);
final BooleanProperty clickTwo = new SimpleBooleanProperty(false);
line.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
lineActive.set(true);
}
});
nodeGroup.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(final MouseEvent t1) {
clickOne.set(true);
if (lineActive.get()) {
if (clickOne.get()) {
//get x and y of first node
x1 = ((Ellipse) t1.getTarget()).getCenterX();
y1 = ((Ellipse) t1.getTarget()).getCenterY();
clickOne.set(false);
clickTwo.set(true);
}
if (clickTwo.get()) {
nodeGroup.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(MouseEvent t2) {
//get x and y of second node
x2 = ((Ellipse) t2.getTarget()).getCenterX();
y2 = ((Ellipse) t2.getTarget()).getCenterY();
//draw line between nodes
final Line line = new Line();
line.setStartX(x1);
line.setStartY(y1);
line.setEndX(x2);
line.setEndY(y2);
canvas.getChildren().add(line);
clickTwo.set(false);
lineActive.set(false);
}
});
}
}
}
});
}
I just have the booleans to check for the first and second click to get the center of each node.
My first question is when I click on the line function and add a line between 2 nodes, it doesn't seem to end the function, and any other nodes I click on gets a line to it. How can I prevent it from executing more than once.
And my second question is how can I "connect" the line to the nodes that if the node moves, the line stays in the center of the node?
Thanks.
I think there is a couple of things which could make this simpler...
Do not use booleans when you have more than two states (no click, click one, click two) use an enum instead. Then you only need one variable to look after.
Only ever set one mouse listener on the nodeGroup and check which state you're in and have the appropriate code there instead of separate mouse listeners.
I imagine that the program is setting the listener for the second click and not resetting it to the listener for the first click when it completes.
Since i am new to Stack Overflow , I tried something on your problem
First add line between two labels
final Line line = new Line();
#Override
public void initialize(URL arg0, ResourceBundle arg1)
{
// TODO Auto-generated method stub
line.setStartX(lblDragTest.getLayoutX());
line.setStartY(lblDragTest.getLayoutY());
line.setEndX(lblNew.getLayoutX());
line.setEndY(lblNew.getLayoutY());
rootAnchorPane.getChildren().add(line);
}
And then add this methods...
// This code handles label move
//set lblDragMousePressed method to Mouse Pressed event for lblDrag
#FXML
public void lblDragMousePressed(MouseEvent m)
{
System.out.println("Mouse is pressed");
prevLblCordX= (int) lblDragTest.getLayoutX();
prevLblCordY= (int) lblDragTest.getLayoutY();
prevMouseCordX= (int) m.getX();
prevMouseCordY= (int) m.getY();
}
//set this method on mouse released event for lblDrag
#FXML
public void lblDragMouseReleased(MouseEvent m)
{
System.out.println("Label Dragged");
}
// set this method on Mouse Drag event for lblDrag
#FXML
public void lblDragMouseDragged(MouseEvent m)
{
diffX= (int) (m.getX()- prevMouseCordX);
diffY= (int) (m.getY()-prevMouseCordY );
int x = (int) (diffX+lblDragTest.getLayoutX()-rootAnchorPane.getLayoutX());
int y = (int) (diffY+lblDragTest.getLayoutY()-rootAnchorPane.getLayoutY());
if (y > 0 && x > 0 && y < rootAnchorPane.getHeight() && x < rootAnchorPane.getWidth())
{
lblDragTest.setLayoutX(x);
lblDragTest.setLayoutY(y);
}
line.setStartX(lblDragTest.getLayoutX());
line.setStartY(lblDragTest.getLayoutY());
line.setEndX(lblNew.getLayoutX());
line.setEndY(lblNew.getLayoutY());
// rootAnchorPane.getChildren().add(line);
}

Categories

Resources