Java: when trying to pause the program, the entire program freezes - java

I have a program here with buttons. one is a pause button and the other is a resume button. when i click on the pause button the program stops, but when i attempt to click the resume button nothing happens, i can't even click the button or even X out the window. And the click effects on the buttons also dont work. So i'm assuming the program just froze for some reason
public void createButtons() {
fastForwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
synchronized(this) {
this.notify();
}
}
});
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
synchronized(this) {
try {
this.wait();
} catch (InterruptedException e3) {
e3.printStackTrace();
}
}
}
});
}
public static void main(String args[]) {
new Sim().start();
}
Any ideas would be much appreciated, thanks
Update:
The purpose of this program is to have a simulation of a game and i have these 2 buttons were u can pause the game and then resume the game. but all in all, i really just want to pause the whole program and resume it

Went for a small hack, i just placed a while loop in the place i wish to pause and added a isPaused state that will be true or false depending on the button pressed. The while loop will be an infinite loop till someone clicks resume, which will update the state to false and the thing will resume itself. Worked out fine in the end

Related

Starting "asyncExec" in Mouse Down Event results in blocking behavior

Having a "next" Button, when I press keyboard enter key with the button selected, the widgetSelected event of the button is being repeatedly called once and once and doing a super fast next. It's exactly the behaviour I want, but only happens with keyboard enter key.
I want to have that behaviour with mouse click when holding the click. When trying to do the same with the mouse click, the behaviour is not the same, it only makes one event call, and when the click is end (UP). How to simulate the same behaviour with the mouse click?
I tried it doing this, but it blocks the UI (can't understand why) and mouseUp is never being called, it blocks forever in the while:
button.addMouseListener(new MouseAdapter() {
boolean mouseDown;
#Override
public void mouseDown(MouseEvent e) {
System.out.println("mouseDown");
mouseDown = true;
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
while (mouseDown) {
System.out.println("Doing next in mouseDown");
next(composite, label_1);
synchronized(this){
try {
wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
}
#Override
public void mouseUp(MouseEvent e) {
System.out.println("mouseUp");
mouseDown = false;
}
});
The Runnable you give to asyncExec runs in the UI thread. You must never do any sort of wait in the UI thread as that will block the UI until it completes.
So you cannot run a loop like this as it just blocks the UI. Since the loop never returns to the main SWT readAndDispatch loop no UI actions are done.
Instead use the timerExec method of Display to schedule a Runnable to run after a given interval. This runnable should do one step of the action and use timerExec to schedule the next step later.
I remember there was another question a few days ago regarding a long mouse click behaviour but I can't find it anymore. I put this code based on greg-449 solution to use timerExec method, after my failed attempts to use asyncExec in the UI thread. :)
button.addMouseListener(new MouseAdapter() {
boolean mouseDown;
#Override
public void mouseDown(MouseEvent e) {
mouseDown = true;
Display.getCurrent().timerExec(1000, () -> {
if (mouseDown) {
button.notifyListeners(SWT.Selection, new Event());
button.notifyListeners(SWT.MouseDown, new Event());
}
});
}
#Override
public void mouseUp(MouseEvent e) {
mouseDown = false;
}
});
button.addSelectionListener(SelectionListener.widgetSelectedAdapter(
e -> System.out.println("Do next")));

java Swing: How to pass value by pressing one button while other button is already pressed

I am working on a project with Java swing and Matlab. I have a GUI with 2 buttons "Run" and "Pause". I am using one more java program (Matlabjavaprog.java) where I am running a loop as follows:
int pause = 0;
for (int i=0; i<10; i++) {
if (pause == 20000) {
try {
Thread.sleep(pause);
System.out.println("Now delayed for 20s!");
} catch (InterruptedException ie) {}
} else {
proxy.setVariable("n", i);
proxy.eval("n=n+1");
proxy.feval("myfun");
}
}
When I pressed "Run" button, the else part executes. But I want to press "Pause" button in between this loop where value of pause (20000) will be passed to java program from GUI, and the execution should be delayed by 20000ms. However, I am not able to press "Pause" button until "Run" is executing the loop.
"Run" button:
JButton btnNewButton = new JButton("Run");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pauseButton.setEnabled(true);
prog1.main(args); // a java program that calls another program Matlabjavaprog.java (which calls an instance of Matlab)
}
});
"Pause" button:
pauseButton = new JButton("Pause");
pauseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int p =20000;
Matlabjavaprog.getpause(p); // a function in Matlabjavaprog java program that passes pause value from GUI to this program
}
});
Actually "Run" creates a TCP connection with MATLAB and within it it runs several instances of data set. The whole process cannot be put in thread as it will not allow to reconnect as it has already a connection. It seems that once I pressed "Run", I cannot press "Pause" until run is complete. Is there any way to execute "Pause" button that could delay the loop as per user need? Currently, I am not able to sent pause value to the running program, i.e., Matlabjavaprog.java. Any help will be appreciable!
How about putting the execution in another thread by implementing Runnable and using an AtomicBoolean
e.g.
AtomicBoolean isPaused = new AtomicBoolean(false);
new Thread(new Runnable(){
public void run(){
while(true){
if(isPaused.get()){
Thread.sleep(20000);
isPaused.set(false);
}
proxy.setVariable("n", i);
proxy.eval("n=n+1");
proxy.feval("myfun");
}
}
}).start()
Then in your pause button, call a setter that calls isPause.set(true) and that should make it clickable. It's a start anyway - I like using atomics for signaling between threads for simplicity.

Thread.sleep and hiding buttons

The problem that I have in my code is that when it runs the button.setVisible(true); it won't set the button to visible until all the other if statements are passed through which really confuses me.
I'm trying to make simon says, and what this try-catch does is that it makes the button in the sequence order blink so that the user can know which button it is that follows.
I'm new to programming so any tips and advises are welcome.
Thank you for taking a look!
try {
inputOrder.clear();
// System.out.println("THIS IS INPUT" + inputOrder);
Sequence.add(randomNumber());
int f = 0;
for (; f < Sequence.size(); f++) {
//Thread.sleep(2000);
if (Sequence.get(f) == 1) {
try {`
btnNewButton.setVisible(false);
Thread.sleep(1000);
} catch (InterruptedException e1) {
}
Thread.sleep(1000);
System.out.println("it ran here");
btnNewButton.setVisible(true);
}
if (Sequence.get(f) == 2) {
try {
btnBlue.setVisible(false);
Thread.sleep(1000);
} catch (InterruptedException e1) {
}Thread.sleep(1000);
System.out.println("it ran here");
btnBlue.setVisible(true);
}
if (Sequence.get(f) == 3) {
try {
btnYellow.setVisible(false);
Thread.sleep(1000);
} catch (InterruptedException e1) {
}Thread.sleep(1000);
System.out.println("it ran here");
btnYellow.setVisible(true);
}
if (Sequence.get(f) == 4) {
try {
btnGreen.setVisible(false);
Thread.sleep(1000);
} catch (InterruptedException e1) {
}
Thread.sleep(1000);
System.out.println("it ran here");
btnGreen.setVisible(true);
}
System.out.println(Sequence);
// Order.add(getColor(Sequence.get(f)));
System.out.println(Order);
text.setText(String.valueOf(Order.size()));
}
btnNextRound.setVisible(false);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Looks like this happens because you are doing this operation in the UI thread, and it does not have time to execute EventQueue since you force to sleep the UI thread, due to this thread gets chance to actually do the paint once it finish all the sleep calls.
In order to get desired output, I think you should move the sleep logic into a separate thread or to a SwingWorker. If you moved the logic to a separate thread you need to use the EventQueue.InvokeLater to enable buttons.
The way that the Java Swing GUI works is that everything happens one after another. Only when the entire method you posted is finished will the next GUI events (such as the repainting events that need to occur to show that the button's not visible anymore). Doing a Thread.sleep just makes your method take longer to finish. The result is that your UI is frozen because no other events (such as mouse, keyboard, or repainting events) are able to run until after all of your sleep calls.
To perform animation in Java, you should use the javax.swing.Timer class rather than using Thread.sleep. Below I've posted a quick example of a timer that, when started, will cause a button to flash. This doesn't completely solve your problem (you're also looping, but you really need another timer to actually schedule when the buttons will flash so that they don't all happen at once).
import javax.swing.Timer
/**
* Timer that causes a button to flash (become invisible for 1 second, and then become visible again).
*/
public class ButtonFlashTimer extends Timer {
private final JButton buttonToFlash;
public ButtonFlashTimer(JButton button) {
super(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// This method is called every 1000 ms (until we tell
// it to stop). This allows us to perform the next "step"
// in the animation.
boolean isVisible = buttonToFlash.isVisible();
if (isVisible) {
buttonToFlash.setVisible(false);
} else {
buttonToFlash.setVisible(true);
// Once we've flashed, stop the timer (don't keep flashing).
stop();
}
}
});
buttonToFlash = button;
// Become invisible immediately; the 1000 ms will be the time between the first
// call to the actionPerformed (which will set it as invisible) and the second
// call (which makes it visible again).
setInitialDelay(0);
setRepeats(true);
}
}

Why is my button not clickable? (Java)

I have a java swing gui program and when I click a toggle button a timer begins but I want to be able to click the same button and the timer stops and right now it won't let me click on it again.
This is in my timer class
public void runningClock(){
isPaused = false;
while(!isPaused){
incrementTime();
System.out.println("Timer Current Time " + getTime());
time.setText(""+ getTime());
try{Thread.sleep(1000);} catch(Exception e){}
}
}
public void pausedClock(){
isPaused=true;
System.out.println("Timer Current Time " + getTime());
time.setText(""+ getTime());
try{Thread.sleep(1000);} catch(Exception e){}
}
and this is in my main class
private void btnRunActionPerformed(java.awt.event.ActionEvent evt) {
if(btnRun.getText().equals("Run")){
System.out.println("Run Button Clicked");
btnRun.setText("Pause");
test.runningClock();
}
else if(btnRun.getText().equals("Pause")){
System.out.println("Pause Button Clicked");
btnRun.setText("Run");
test.pausedClock();
}
}
You're freezing the Swing event thread with your Thread.sleep(...) and while (something) loops. Solution: don't do that -- don't call code on the event thread that occupies the event thread and prevents it from doing its necessary tasks. Instead change the state of your program. And for your clock, use a Swing Timer. For example, please look at my answer and code here.
You are doing this in your program, try{Thread.sleep(1000);} catch(Exception e){}. As this statement is applied on the main thread itself, so the application itself hangs or you can say freezes. What you can do is apply a separate thread for the timer.
new Thread(new Runnable(){
public void run(){
//Do Stuff
}
}).start();

I have a issue with java threads and KeyEvents?

I need a bit of help with my program here. I have a blocking function waiting in my main thread for the user to click "Enter". Then, when the user hits enter, the keypressed event should fire, which will unblock the blocking function. However, when the program hits the blocking function, it simply freezes up and doesn't register the key pressed event.
So, my question is, is a event a runnable, which is added to a thread whenever the user clicks enter? If so, my code should have worked, right? If this is not the case, and each event is not a separate thread, could anyone enlighten me on how I should fix my problem here?
my blocking function:
public String getInput() {
synchronized(waitObject) {
try {
System.out.println("waiting");
waitObject.wait(); // throws exception, cba to add it here
} catch (Exception ex) {
ex.printStackTrace();
}
}
return(myString);
}
my keylistener code:
public void keyPressed(KeyEvent e) {
System.out.println("key pressed");
char c = e.getKeyChar();
if (c == e.VK_ENTER) {
System.out.println("Enter pressed");
synchronized(waitObject) {
waitObject.notifyAll();
}
}
}
and the function getting the input:
private String getCommand() {
System.out.println("getting command");
CommandField command = new CommandField((JFrame)(this));
command.setPreferredSize(new Dimension(getWidth(), 30));
m_panel.add(command, BorderLayout.NORTH);
validate();
command.requestFocus();
System.out.println(command.getInput());
return null;
}
And this function is called from another keylistener:
public class Listener implements KeyListener {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_F2) {
System.out.println(getCommand());
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
OK, getCommand() is called on the event thread which then calls getInput() on the same thread, which then calls Object#wait() on the event thread, so yes you are tying up the event thread and effectively freezing your program.
None of this is needed, and a much easier fix is possible if you code using the concepts of event-driven programming. You don't want to call wait() in a Swing GUI and in your situation don't need to call it, but rather you want to change how your program responds to input based on its state. If you tell us more on the exact behavior you're trying to elicit, we can probably help you find a much better solution.
Edit
Consider using a JOptionPane or a modal JDialog for displaying a "blocking" window that stops the main program until the dialog has been dealt with.
Starting with ImageApp, I added the following key binding in the constructor. It will show() the popup menu when pressing the Enter key. You can change the arbitrary location to suit your usage.
this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "showPopup");
this.getActionMap().put("showPopup", new AbstractAction("showPopup") {
#Override
public void actionPerformed(ActionEvent e) {
popup.show(ImageApp.this, 42, 42);
}
});
Addendum: To bring up a modal input dialog, so something like this:
this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "dialog");
this.getActionMap().put("dialog", new AbstractAction("dialog") {
#Override
public void actionPerformed(ActionEvent e) {
String value = JOptionPane.showInputDialog("What?");
System.out.println(value);
}
});

Categories

Resources