How to freeze my jframe while program flow is happening in java - java

So I have a little puzzle made in Java, and let's just say there are buttons too on this puzzle which represent the puzzle. There is a solving method where a series of buttons are clicked to find a "solution", and it takes around 1 minute to solve it, so that is 1 minute of just clicking buttons
During this one minute, you notice the buttons being clicked by the computer as it changes color and shape during the program flow, I was wondering if there was a way to freeze the jframe before the solving() method is invoked and then unfreezes into the solution when the method is over?

I am a little confused to exactly what you are asking, but I would suggest using this code to do what I believe you are asking for
private static boolean solveDone = false; //This should go in a the class, not here.
//Create a new thread to handle processes while the JFrame is frozen
SwingUtilities.invokeLater(new Thread(){
public void run(){
//Code to run while the JFrame is frozen should be put here.
main.solveDone = true;
}
});
//Sleep the program until the process is done.
try{
while(!solveDone) {
Thread.sleep(10); //Interval in milliseconds to check if the puzzle is done goes here.
}
solveDone = false;
}catch(InterruptedException e){
e.printStackTrace();
System.exit(-1);
}
//Code to run after solving goes here.
Now, this isn't the cleanest way to do this type of thing, but I believe it should work.
On the other hand, if you know exactly how much time it is going to take, you could do this.
SwingUtilities.invokeLater(new Thread(){
public void run(){
//Code to run while the JFrame is frozen should be put here.
}
});
try{
Thread.sleep(1000); //The time in milliseconds to sleep the JFrame
}catch(InterruptedException e){
e.printStackTrace();
System.exit(-1);
}
//Code to run after solving goes here.

Related

JProgressBar moves instantly and not gradually (java)

I want to make a ProgressBar move gradually using a Jbutton. To achieve this I am using a for loop and the method Thread.sleep. The problem is that insted of moving a tiny bit every second (the progress bar) after pressing the button, the program waits until the loop finishes and then does instantly move the progress up. When I take the loop outside of the button listener it works as I want but I really need it to work when pressing the button. Here is the code:
progressBar.setOrientation(SwingConstants.VERTICAL);
progressBar.setMinimum(0);
progressBar.setMaximum(100);
progressBar.setValue(50);
panel1.setLayout(null);
panel1.add(progressBar);
progressBar.setBounds(40,6,100,100);
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int counter = 5;
for (int i = 0; i < 5; i++) {
progressBar.setValue(progressBar.getValue() + counter);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
});
If anyone can help me I will be very grateful!
Your code runs on the Event Dispatcher Thread (EDT). That thread is responsible for handling events, but also for repainting. Because it's just one thread, the repainting only occurs after your method ends.
There are some ways to solve this. In your case, a javax.swing.Timer would probably be easiest. Instead of running the loop in a single method, the button click starts a timer that runs every second. When it's done the timer can cancel itself. A slightly more difficult alternative is to use a SwingWorker. You could publish data in the doInBackGround method, and override process to perform the updates to the progress bar.
For more information, please read Concurrency in Swing.

I don't understand this java behaviour

I had a question about making a JButton flash colors ,like you would see when an answer was given in millionaire tv show. I got the answer there on how to do it properly but I also managed to "do it" in this way which raised some questions I couldn't answer totally.
As you see in the code bellow I am calling a
JOptionPane.showMessageDialog() after the JButton.setBackground and right before i stall the code using
do {
}while(time+i*100>System.currentTimeMillis());
Ignore the robot.keypress for the time. Lets get to the point. If i didn't use the JOptionPane before the code stalling , the ui would seem frozen and the button wouldn't repaint. But calling the JOptionPane.ShowMessageDialog() gives "time" to the button to repaint. Then the code is stalled normally and I achieve the sequential color repaint. I used the robot.keypress to close the Pane and achieve the effect desired.
My Questions: First, what happens when the JOptionPane is created that allows the button to repaint ? And secondly why the robot works only before the JOptionPane is called? I tried calling after the Pane was called like one would assume it should happen , but it wouldn't work in that case.
Extra: This didn't work in a mac it seems to only work for windows. Not quite sure.
public static void paintbutton(int bnr,boolean corr) {
long time;
try {
Robot robot = new Robot();
for (int i=5;i>1;i--){
b[bnr-1].setBackground(null);
// Simulate a key press
robot.keyPress(KeyEvent.VK_SPACE);
robot.keyRelease(KeyEvent.VK_SPACE);
JOptionPane.showMessageDialog(null,"hi");
time = System.currentTimeMillis();
do {
}while(time+i*100>System.currentTimeMillis());
b[bnr-1].setBackground(i==1?(corr?Color.green:Color.red):Color.yellow);
// Simulate a key press
robot.keyPress(KeyEvent.VK_SPACE);
robot.keyRelease(KeyEvent.VK_SPACE);
JOptionPane.showMessageDialog(null,"hi");
time = System.currentTimeMillis();
do {
}while(time+i*100>System.currentTimeMillis());
}
} catch (AWTException e) {
System.err.println("error");
}
}
To avoid confusion as to the nature of this question!
The code in the state below doesn't work and I know it shouldn't. I am curious on how adding JOptionPane solves that.
public static void paintbutton(int bnr,boolean corr) {
long time;
for (int i=5;i>1;i--){
b[bnr-1].setBackground(null);
time = System.currentTimeMillis();
do {
}while(time+i*100>System.currentTimeMillis());
b[bnr-1].setBackground(i==1?(corr?Color.green:Color.red):Color.yellow);
time = System.currentTimeMillis();
do {
}while(time+i*100>System.currentTimeMillis());
}
}

Pause game and add flashing text Java

I have this loop
while (true) {
game.update();
view.repaint();
Thread.sleep(DELAY);
}
In the game.update various components of the game have their position changed and those updates are reflected when the repaint() method is called on the view. The view extends JComponent and loops through the game objects and calls their print methods.
What I want to do is have a boolean called nextLevel in the game and if it's true Flash text on the screen for the player to notify them that they're going onto the next level. Maybe flash 4-5 times. Then continue the game.
Is this possible? I have been playing around with Thead.Sleep() but this only seems to pause the displaying and in the background the game is still going on.
Any ideas on how to do this?
Maybe you want to avoid threading by using a Timer object.
an example like that could be
int flashTimer = 0;
if(nextLevel) {
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
//flash something method here
flashTimer++;
}
});
timer.start();
}
and then check your flashTimer if it reaches the number you want then just stop the timer by timer.stop();
Just an idea which seems to me a bit simpler. the 1000 value is milliseconds which is passed and executes the code inside the actionPerformed method every 1 sec.
Hope it helped

Quirky trouble updating an image for a Jlabel

I'm having some trouble with an assignment I'm working on.
Part of it is to "animate" the rolling of a pair of die. I have 6 JPEGS, one of each of the sides. Instead of rolling, I want it to cycle through the images. I'm trying to use setIcon over and over in a loop, and use Thread.sleep() for a delay. This, among other things, all happens when the user hits a button (the event). Instead of displaying the images, it waits the correct amount of time and displays only the last image. Here's the function I'm calling to perform the loop:
private void aniRoll(){
for(int i = 0; i < 10; i++){
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face1.jpg")));
try{
Thread.sleep(1000); // Sleep for 1 sec
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face2.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face3.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face4.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face5.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face6.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
}
}
die1Disp is the name of my JLabel, aniRoll() is the function I'm calling to perform the loop (made private because I don't want anything outside of my GUI class to call it), and the faceX.jpg are my images.
What I can't understand is no matter where I put the Thread.sleep() it delays the program first, and then only displays the last image. For example:
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face1.jpg")));
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face2.jpg")));
//bunch of extra code
try{
Thread.sleep(10000); // Sleep for 10 sec
}
catch(InterruptedException e){}
This will wait for 10 seconds and then display only the second image. It doesn't blip the first quickly, display the second, then wait, it waits and only displays the second image. This quirk really has me baffled, and I'm not sure how to correct it. I'm using NetBeans IDE 7.01 as my editor and for the basic layout and code generation I'm using a Component Palette.
--Thanks
First you must make the changes on the gui thread. See
SwingUtils.invokeLater.
Also Thread.sleep isn't going to cut it, you should be using a javax.swing.Timer to specify when to switch icons.
There's a single UI thread managing events and repainting (updating the screen). You put it to sleep. Doing so means that nothing else was going to happen (in regard to the UI) until it wakes up.
In your actionPerformed method, start a new Thread that will do the repainting. That should fix it.

jSlider code causes the application to hang

This jSlider code causes the application to hang.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
for(int i=0;i<100;i++)
{
jSlider1.setValue(i);
Thread.sleep(3000);
}
} catch (InterruptedException ex) {
Logger.getLogger(AsdView.class.getName()).log(Level.SEVERE, null, ex);
}
}
thank you guys i am updating the answer
Timer time = new Timer(100, new ActionListener() {
int percent = 0;
#Override
public void actionPerformed(ActionEvent e) {
percent++;
if (percent>100)
percent = 0;
jSlider1.setValue((int)(100*(percent/600.0)));
}
});
time.start();
I am guessing you are trying to do some kind of smooth scroll.
That code freezes because the event thread that handles the window painting, sizing, etc..., is being frozen by you executing Thread.sleep(3000), 100 times.
I would recommend that you use a Swing timer that changes the scroll bar little by little.
i don't know why you put the sleep for 3 secs and that too in for loop of 100
3*100 = 5 mins so it will hang upto 5 mins
remove Thread.sleep(3000);
it will work fine and won't hang
When you say your application 'hangs', that generally means that you have some sort of deadlock that prevents your threads from making progress. Is that what you're observing in your program? The way it's currently written, the current thread of execution will take at least 300 seconds to complete. Is this work being done on the main thread of execution? If so, you may want to consider creating a new Thread to do this work.

Categories

Resources