Second loop is getting executed first - java

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)

Related

JavaFX - Create Loop of Logic that Pauses for User-Prompt Windows

As part of my efforts to familiarize myself with the MVC model, I am attempting to write a program that loops through a set of code calculations while occasionally pausing to prompt the user for input with custom windows created in JavaFX, using that input to continue the calculations until a certain result is reached to break the loop. The idea is that for each window, the user selects an option, the window closes, and then the logic continues until the next user input is needed. Then the next window opens and the process continues. Based on what the user inputs, the choices included in the next window can change. For my starting example, the window has four buttons with the numbers 1-4 and prompts the user to choose a number. I boiled down my code to something really basic:
public class LogicLoop()
{
public static AtomicInteger CHOICE; //Global variable to act as the user's current choice, as there is only ever one choice made at a time
public static boolean loopDone = false;
public static void main(String [] args)
{
new Start().startLoop(); //Calls the class that extends Application to call the launch() command. Since launch() can only be called once, it needs to be outside the loop
logicLoop();
}
public void logicLoop()
{
while(!loopDone)
{
Chooser chooser = new Chooser();
chooser.show();
int choice = CHOICE.get();
CHOICE = null;
doSomething(choice);
}
public doSomething(int choice)
{
//Set some other variables to modify how the next window will look
//Potentially set loopDone to true;
}
}
}
And then my Chooser class:
public class Chooser()
{
public int show()
{
Stage newStage = new Stage();
createWindow(newStage); //method that sets up window based on global variables and calls show() on newStage. Each button in the window will close the stage. The CHOICE value will also be set based on the user's input
}
}
The window created by createWindow() has buttons with the following handle() method:
public void handle(ActionEvent event) {
CHOICE = new AtomicInteger(btn.getValue()); //I made my own Button class that has a value variable and a getter() for it
Stage stage = (Stage) btn.getScene().getWindow();
stage.close();
}
The issue I'm facing is that when my code goes to execute, the logic doesn't wait for the user's input before continuing right past the show() method. So what happens is the code starts the loop, and immediately brings up the first window. At the same time, a NullPointerException is thrown because my logic is already trying to call CHOICE.get() before the user even has time to input any value. So after choosing a button and closing the first window, nothing else happens.
So far I've tried making use of the showAndWait() method in my createWindow() method, but it doesn't appear to make any difference. I've tried calling the wait() command after chooser.show(), but it just adds a delay and then I see the same results. Based on information I've been able to find on Stack Overflow, I've seen a lot of recommendation to use the Platform.runLater() method, but I can't see how it would be effective here. If the GUI runs later, the logic will still just stampede ahead without it. I need the logic loop to pause until the window closes, which seems to be what showAndWait() is designed to do. What confuses me the most is a statement I came across while researching an answer that said that implementing a basic MVC framework does not require multithreading and that it is not advisable for a beginner to make use of it. At this stage, I'm not certain how that's possible.
What am I missing here?

String Switches Back Previous Value

So, this is really annoying, and an incredible magic show at the same time. So I have a global string called setAnagram. I'm making a GUI with Eclipse, and so what I'm trying to do, is have the user click a button, it start another thread, and on that thread it gets the value of a text field. The way I did this was to set setAnagram to the value of the text field.
However, that didn't actually work, and setAnagram had a blank value (""). So then I thought okay well what if I set the variable to null. Well then I get a NullPointerException.
I thought well, what if the variable actually doesn't change, and it starts the thread before it can change the variable? Well I made it so you press the button once and it changes it, then you press it again, and then it starts the thread. Here's where the weird stuff comes in. I print out the value of setAnagram on the first button click after it has been changed. However, when I start the thread on the next button click, it's back to the what it was initialized as ("test"). Here's the code for the button click:
decodeAnagramButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (buttonPresses == 0) {
setAnagram = chosenAnagram.getText(); // chosenAnagram is the text field
buttonPresses++;
decodeAnagramButton.setText("Click again");
System.out.println(setAnagram); // These two lines output the same thing
System.out.println(chosenAnagram.getText());
}
else {
titleText.setText("Decoding anagram...");
decodeAnagramButton.setVisible(false);
MainWindow thread = new MainWindow();
thread.start();
}
}
});
And then to minimize, I won't add the thread code because it's kinda long, just know that all it does with setAnagram is get the value. Any ideas on why this is changing unexpectedly?
MainWindow thread = new MainWindow();
thread.start();
So... you create a new instance of MainWindow (which is apparently a thread?!?). That means that new instance of MainWindow also has its own setAnagram member variable, right?
Try adding thread.setAnagram = this.setAnagram; between these two lines of code.
(Also, something about your design smells fishy, why is your main window a thread?)

How to stop an infinit loop in java desktop application to move the mouse

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.

JFrame white and unresponsive with a while loop

I am having troubles with programming a game called "Coup" and to explain what the problem is, i need to briefly explain what the game is about. Coup is a card game where players try to eliminate each other and be the last player left. To do this, players can choose a number of actions but they can also lie to other players. In this game, other players can call "bullshit" or block another players action. Because of this, i need to make Response windows which will let other players respond with a challenge, a block or do nothing. The result of the action is then dependent on the responses. For example, a player tries to get foreign aid. I can decide to block his action or to let him continue. There are consequences if i block but that isnt the problem here.
The real problem is this: I want to give all my players a chance to give a response (Block or do nothing) via a JFrame and I use a while loop to wait for all players responses. However, this while loop doesnt do anything except keep the method from progressing since the result depends on players reactions. With the while loop, the JFrame I constructed appears white and doesnt contain the two buttons i made. At this point i can even press the close button and it wont respond due to the while loop I made which is dependent on my responseless window. Is there anyway to fix this?
if (turnCount == players[currentPlayerNum].getPlayerNum()){
for(int i=0; i<players.length;i++){
//If it is not the players turn and they have one or two lives, make response window
if (players[i].getPlayerNum() != turnCount){
if (players[i].getLives() != 0){
//foreignAidBlock constructs the response window
players[i].foreignAidBlock(turnCount);
}
else{
//Not applicable since out of game/not in game
players[i].setResponse("NA");
}
}
else{
//Not applicable since out of game/not in game
players[i].setResponse("NA");
}
}
//Idea: PAUSE TILL RESPONSES COME IN
while(players[0].getResponse() != null || players[1].getResponse() != null || players[2].getResponse() != null || players[3].getResponse() != null)
{
System.out.println(players[0].getResponse());
System.out.println(players[1].getResponse());
System.out.println(players[2].getResponse());
System.out.println(players[3].getResponse());
}
The result i get from running this part of the code is:
"NA
null
NA
NA"
continuously. I use a null to represent a player that hasnt answered yet. At the end of the method, I reset all of my players abilities back to null.
All my response window will do is change the response of the player from null to "B" or "N". But without access to the buttons I cannot do this. Does anybody have any tips on how to use something to "pause" my thread besides using a while loop?
As Abdul Fatir mentioned, it is because the UI thread is being blocked.
I would however not reccomend directly messing with threads. There is a SwingWorker class exactly for this scenario and it is reccommended you use this.
For more info check this blog article - Swing Worker Example
You can also find some useful info in the following SO question - How do I use SwingWorker in Java
Here is quick use example from the official javadoc:
Say we want to find the "Meaning of Life" and display the result in a JLabel.
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
return findTheMeaningOfLife();
}
#Override
protected void done() {
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
(new MeaningOfLifeFinder()).execute();
The while loop is blocking your UI Thread. Perform your while loop checks in a different Thread.
Thread t = new Thread(new Runnable(){...});
t.start();
This way your UI won't be blocked and controls will remain responsive.

if statement only executes if I print to terminal before [duplicate]

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.

Categories

Resources