This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
I am using the javax.swing packages to construct a gui, and have a while loop running forever with an if statement inside, to see if a button has been pressed. For some reason unbeknownst to me, this code only works if I print to the console inside the while loop.
Here is the algorithm structure:
while(true){
System.out.println(" ");
if (startOver && playPressed) {//set to true on JButton press
//do stuff
}
}
Possibly this is some sort of threading issue? Has anyone ever encountered such a problem before? Is there a method of waiting for a JButton to be pressed that doesn't involve an infinite while loop?
Thanks in advance!
Swing is event-based. You're not supposed to have infinite loops waiting for a button to be pressed. The loop is implemented by Swing internally. What you're supposed to do is to add an action listener to the event, which will be called by the button when it's clicked:
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("The button has been clicked!");
// do stuff
}
}
This is fundamental stuff when dealing with Swing. You should read the swing tutorial.
Any infinite loop in the swing event dispatch thread will freeze the GUI forever.
The only way I was able to overcome this problem without an infinite loop was by creating a new thread for the "//do stuff" portion of the algorithm.
very strange, and I still don't understand why I had to print to console to make it work within the while loop.
Related
Right now, the object moves a certain increment each time I manually click a button, but its actually suppose to move on its own across the screen on its own once the button is clicked. I tried calling timer.start(); various times in my code. As well as, setting up an 'if' statement in the actionPerformed method that checks for a button being pressed and then calls timer.start() as a result. But, it didn't get the object to move on its own.
Can anyone lead me in the right direction? Am I not writing the code right? Or is does this problem have something to do with java swing timer.
PS. I am new to java,
And this is part of my code :
public void actionPerformed(ActionEvent e){
if (e.getSource() == rightBtn) {
objXpos += objMoveIncrement;
direction.equals("Right");
}
if (e.getSource() == leftBtn) {
direction.equals("Left");
objXpos -= objMoveIncrement;
}
repaint();
}
}
**edit
the timer is suppose to start once a button is clicked, and the timer is what allows the object to move across the screen
this problem have something to do with java swing timer.
No.
Am I not writing the code right?
That would be the problem.
the timer is suppose to start once a button is clicked
And how does the Timer stop? What happens if you click "right" and then "down"?
Without knowing the exact requirements it is hard to give an exact solution.
So I would suggest that one solution is to just start the Timer when your program starts.
Then in the ActionListener for each button, you change the direction.
Then when the ActionListner for the Timer is invoked, you simply move the object based on the current direction and then repaint the object.
Generally you would use Key Bindings for something like this. So when you press a key you start the Timer and when you release the key you stop the Timer. Check out the Motion With Key Bindings example from Motion Using the Keyboard for a working example of this approach.
I'm trying to create a desktop program to move the mouse until I press for example the letter "q" in java.
I've created a window (JFrame), when I press a buttom the mouse start to move.
My doubt is related to this part:
while (true) {
for (int j = 1500; j <1600; j++) {
robot.mouseMove(j, 0);
robot.delay(100);
}
}
How can I stop this infinit loop by pressing a letter?
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_Q) {
System.exit(0);
}
}
why this is not working?
(I need to press a letter because the mouse, while the program works, is unusable)
Thanks in advance.
First, you might have to let go of the event handler.
If this while(true) is ran on the awt event queue, you are hogging the whole GUI and no wonder it is not responsive; no other event can be fired until you return from the mouse event.
Can you give more code? This is not enough to explain the behavior.
You would probably need to launch a thread to perform this work.
UPDATE:
instead of calling synchronously your JavaRobot(); method, you will need to run it in a thread. Ugly hacked version for testing:
(new Thread(() -> JavaRobot())).start();
The cleaner version would likely save thread in a variable so you can interrupt it with another button. You can also go nuts with the executor services apis if you prefer not handling threads yourself yet still run tasks in threads.
tf is a JTextField.
Expected flow of execution:
The control is not supposed to move out of the first loop until something is entered in the JTextField named tf .
Second while loop should only run after the control moves out of the first one.
while(true)
{
if((!tf.getText().equals("")))
{
p.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
String name=tf.getText();
System.out.println("Hello "+name+",\nWelcome to Guess the number Game");
}
});
break;
}
else if (tf.getText().equals(""))
{
p.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
p.setSelected(false);
}
});
continue;
}
} //while end
while(true)
{ st="game on";
System.out.println(st);
if(!st.equals(""))
{
gamer3 game1=new gamer3();
Thread nt =new Thread(game1);
nt.start();
break;
}
Problems:
Second while loop is getting executed first. game on got printed.
As soon as I enter something into tf ,the code inside second while loop gets executed. Why is the control moving to second while loop as soon as I enter something into tf? Second while loop is not even dependent on tf.
I don't even need to press enter after entering something into tf. How is the entered value being recognized before pressing enter ?
Main issue:
Why is the second loop getting executed first?
According to the general flow of control, the control has to remain in the first loop until it encounters a break statement. Why is this not being followed here?
The control moves back to the previous loop when I press the start button.
Control never enters the else if in first while loop.
Note:
Second while loop gets executed only after I enter something into tf. And as soon as I press the Start Button first while loop gets executed.
Without a runnable example, it's difficult to ascertain what an out-of-context snippet of code might or might not do
I "suspect" you have an uncontrolled thread which is inspect the state of the field which is triggering actions which you aren't prepared for - Swing is not thread safe and you should not be monitoring or modify the state from outside the context of the EDT, remember, Swing (like most GUIs) is event driven.
Normally you would use either a DocumentListener to get real time feedback or an ActionListener so you can be notified when the user presses the Enter button (or presses another button on the UI)
This question already has answers here:
Waiting for multiple SwingWorkers
(2 answers)
Closed 8 years ago.
I need to perform a method after the clicking of a JButton in a Java Project.
I'm making a client-server game and after the click of a button I need that the client/server start to wait untill the opponent perform a click. The problem is that at the end of the action listener code I start a loop end untill the opponent don't perform another click the jbutton stays clicked..
public void actionPerformed(ActionEvent e) {
JButton o = (JButton)e.getSource();
String name = o.getName().substring(3);
Click(Integer.parseInt(name));
if(isServer)
ListenServer();
else
ListeClient();
}
ListenServer() and ListenClient() are two loop function... How can I call this methods AFTER the click??? Thanks and sorry for the bad english
You can use threads and synchronization. See https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html for examples.
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
I am trying to have my program break out of a while loop when a button on the gui is pressed.
I have a thread which launches the GUI thread and the waits until an apply button is pressed.
Here is the code:
public void run() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
// Wait until apply button clicked and set team
while(true) {
applyClicked = gui.getApplyClicked();
if (applyClicked == true) {
teamYellow = gui.getTeam();
break;
}
}
However even when I click apply and the applyClicked becomes true within the GUI it does not execute that if statement.
However if I add a print line underneath the while true it works ok.
I also debugged it running line by line and the variables set correctly and it works.
Why doesn't this work when I don't have a println? Is it something to do with threads?
Thanks
You're executing a busy-wait loop, which will I guess take all of your cpu power.
You should instead add an actionListener on your apply-button and do your stuff in the actionPerformed method.
This may not be the answer you are looking for exactly, but just in case, define applyClicked outside the loop and declare the loop as while(!applyClicked) so that the break is not needed, because if applyClicked is true, the loop will exit on its own. If that still doesn't work, run the new code with the debugger. This may or may not work, it's just a suggestion.