how to set the value of jprogressbar to zero after reached the 100%?
i used the following code but didn't do exactly what i want:
private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Thread runner = new Thread(){
#Override
public void run(){
counter = pb_MINIMUM;
while(counter <= pb_MAXIMUM){
Runnable runme = new Runnable(){
public void run(){
jProgressBar1.setValue(counter);
}
};
SwingUtilities.invokeLater(runme);
counter++;
try{
Thread.sleep(100);
}catch(Exception e){
}
}
}
};
runner.start();
if(jProgressBar1.getMaximum()==pb_MAXIMUM){
jProgressBar1.setValue(0);
}
}
thanks for any help i could get here...
Your call of setValue(0) occurs directly after you started the thread (which does all the work and increases value of progress bar). At this time no work was done yet and the method does not wait for your thread to complete. Instead you may just include the code right after your while loop (same as you do inside but with value of zero).
Related
I'm new in java. I'm trying to understand thraeads and timers in java. It was big problem for me to undate ProgressBar from another thread. I read many posts and found answers. So can you say is this the best way to resolw my task. So, what I want is to run second thread and when it's done, stop progress bar and change text on the button. So I creat Frame with button and progress bar in Test class:
After I realize action listener for Button to run second thread:
public class Test extends javax.swing.JFrame {
RunBg thread = new RunBg();
....
// declaration for button, progressbar and main() method
....
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
// needed to check is the thread running at first time else creat new object and rund hread again cause thread can be executed once
if(thread == null){
thread = new RunBg();
}
if (jProgressBar1.isIndeterminate()) {
jProgressBar1.setIndeterminate(false);
jButton1.setText("Run!");
thread.suspend();
} else {
jButton1.setText("Working...");
jProgressBar1.setIndeterminate(true);
// let us know is the second thread running or nope so we can know resume it or pause
if (thread.isAlive()) {
thread.resume();
} else {
thread.start();
}
timer.start();
}
}
/*
Then I creat timer to know is my thread still alive else change Progress bar and button
*/
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(!thread.isAlive()){
thread.stop();
jProgressBar1.setIndeterminate(false);
jButton1.setText("Запустить!");
timer.stop();
// thread.interrupt();
thread = null;
}
}
});
...
// end of class
}
And my second class for another thread named RunBG:
public class RunBg extends Thread{
int i = 0;
public void run(){
while(i<20000){
System.out.println(">>>"+i);
i++;
}
System.out.println("<<<Finished>>>");
}
}
Everythig works fine , but I have question. Is there a better way to realize my task or maybe I made some mistakes. Also I thik that my code will help another beginners who looking for help to understand how it's work.
In my onTouchEvent method (in a class that extends Activity), I have some imageViews that change one by one, which is done by waiting a little before executing the next change.
//in the onTouchEvent method
//ivList is an arrayList of imageViews
ivList.get(0).setImageResource(R.drawable.drawable1);
synchronized (this) {
try {
wait(500);
} catch (InterruptedException e) {
}
}
ivList.get(1).setImageResource(R.drawable.drawable2);
However, when this is executed, the changes only take place once onTouchEvent is concluded, so the result is a minor delay and then both imageViews change at once, as opposed to one imageView changing, a minor delay, and then the second one changes. Can someone explain how to fix this?
The problem is you should not use wait() because it will block the main thread
ivList.get(0).setImageResource(R.drawable.drawable1); // this is doing in main thread
synchronized (this) {
try {
wait(500); // this blocks the main thread
} catch (InterruptedException e) {
}
}
ivList.get(1).setImageResource(R.drawable.drawable2); // this is also doing in main thread
try following
Runnable r = new Runnable() {
#Override
public void run() {
ivList.get(1).setImageResource(R.drawable.drawable2);
}
};
ivList.get(0).setImageResource(R.drawable.drawable1);
// no synchronized is needed
new Handler().postDelayed(r,500); // call to change the image after 500s
of cause your Runnable and Handler can create else where so that you do not need to create them every time the onTouchEvent is trigeered
okay , if you are going to make it work for 10 images.
// these are local variables
//create a contant int array for the 10 images
int[] imgs = {R.drawable.drawable1 , R.drawable.drawable2 ,....,R.drawable.drawable10};
int count = 0; // counting which image should show
// local variable ends
// initialize
Handler handler = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
if (count < 9){
count++;
ivList.get(count).setImageResource(imgs[count]);
handler().postDelayed(r,500);
}
}
};
// in your touch event
ivList.get(0).setImageResource(R.drawable.drawable1);
// no synchronized is needed
handler().postDelayed(r,500); // call to change the image after 500s
I am having an issue with a piece of my code in Java, it seems to be creating an endless loop.
public void progress(){
x = 3;
timer = new Timer(800, new ActionListener() {
public void actionPerformed(ActionEvent evt){
System.out.println(x);
x--;
if(x < 1){
UI();
timer.stop();
}
}
});
timer.start();
}
The method UI asks for input via SavitchIn, and it doesn't seem to run the line. I print before I ask for input in the UI method, and the print works just fine. When I remove this timer from my code, and keep the UI method the same, it works fine. Prints and then takes input. I've added a timer.stop() in UI method as well, and I am positive the timer is stopped, however after running the program I am forced to Reset the Virtual Machine the next time around otherwise it wont run. Any help is appreciated!
Your UI() method likely should be called on a background thread as it is likely tying up the Swing event thread (this we have to guess since you don't show it). So create a SwingWorker or a background thread and do this call in there. For more on this, please read Concurrency in Swing.
e.g.,
public void progress() {
x = 3;
timer = new Timer(800, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println(x);
x--;
if (x < 1) {
new Thread(new Runnable() {
public void run() {
UI();
}
}).start();
timer.stop();
}
}
});
timer.start();
}
In Java, let's say I have a GUI with 2 buttons, Go and Pause.
When I press Go, "Hello" gets printed out over and over again. When I press Pause, "Hello" no longer gets printed to the screen.
Example: User presses Go button. "Hello" gets printed out for 1 minute until the user presses "Pause."
What is the proper way to express this approach in Java? Is it equivalent to my commented pseudocode within the goButton source?
public void actionPerformed(ActionEvent e) {
if(e.getSource() == goButton)
{
// while user has not pressed the pause button
printHello();
}
else if(e.getSource() == pauseButton)
{
pause();
}
}
Thanks
In order to get this to work, in reasonable fashion, you will need a Thread. This is executed in the background until such time as you decide to cancel/pause it.
This is an EXTREMELY basic example. Normally I'd wrap the task and the GUI up in appropriate classes rather then accessing static references, but it gives a basic idea
public class TestHello {
private static HelloTask task;
public static void main(String[] args) {
Thread thread = new Thread((task = new HelloTask()));
thread.setDaemon(true);
thread.start();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
JButton goButton = new JButton("Go");
JButton stopButton = new JButton("Stop");
goButton.setActionCommand("Go");
stopButton.setActionCommand("Stop");
ActionHandler handler = new ActionHandler();
goButton.addActionListener(handler);
stopButton.addActionListener(handler);
frame.add(goButton);
frame.add(stopButton);
frame.setVisible(true);
}
public static class ActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Go")) {
task.start();
} else if (e.getActionCommand().equals("Stop")) {
task.pause();
}
}
}
public static class HelloTask implements Runnable {
private static final Object WAIT_LOCK = new Object();
private boolean dump = false;
public void start() {
synchronized (WAIT_LOCK) {
dump = true;
WAIT_LOCK.notify();
}
}
public void pause() {
synchronized (WAIT_LOCK) {
dump = false;
WAIT_LOCK.notify();
}
}
#Override
public void run() {
while (true) {
while (dump) {
System.out.println("Hello");
}
try {
synchronized (WAIT_LOCK) {
WAIT_LOCK.wait();
}
} catch (Exception e) {
}
}
}
}
}
Some further read:
Java Concurrency
Concurrency in Swing
Caveats
NEVER try and modify the GUI from any thread other then the Event Dispatching Thread.
To have responsive UI you would usually have to run printHello() in separate thread. Then as you do processing in this thread, for example, after every print statement, you check some flag boolean isPaused; and stop execution if it is true. When pause button is clicked you set the value of this flag to true.
You need to implement your loop in a separate thread. Otherwise the GUI will become irresponsive and the user might not be able to click the Pause button at all.
With this threaded approach, you also need a flag which indicates whether or not to print out the message. The printing loop can simply stop executing the thread when the flag is set to no longer print.
what about htis:
boolean flag=true;
public void actionPerformed(ActionEvent e) {
if(e.getSource() == goButton)
{
while(true)
{
printHello();
}
}
else if(e.getSource() == pauseButton)
{
pause();
}
}
You can do this in a few ways the simplest being:
You have a boolean flag, keepPrinting and you set it to true when you push the Go button, false when you push the Pause. Next you have a thread somewhere executing a while loop which will print nothing when keepPrinting is false.
The threading here is really important, without it you're going to have your GUI freeze once the user pushes a button as the program prints hello and happily ignores anything else.
Pseudo Code
//GUI
public ThreadedPrinter greeter;
void ButtonGoPushed(args){
greeter.keepPrinting = true;
}
void ButtonPausePushed(args){
greeter.keepPrinting = false;
}
//ThreadedPrinter
boolean keepPrinting
void run(){
while(true){
if(keepPrinting){
print("Hello");
}
sleep(5); //Make sure that this thread yields if the system doesn't do it automatically
}
The good news about java concurrency versus say C++ is that this will just work, you don't have to worry about the boolean being crazy and inconsistent because in java variable sets are atomic. If you want to do more than just set the variable, make a synchronized method that sets the variable and does anything else you want.
Basically to keep UI responsive such task need to be performed in other thread.
There can be various ways in which you can implement this mechanism in java.
I have used simple mechanism of Runnalbe and volatile flag which ensure that thread exists when you call cancelPrint() method
public void actionPerformed(ActionEvent e) {
if(e.getSource() == goButton)
{
//start the thread here
}
else if(e.getSource() == pauseButton)
{
//call cancel here
}
}
public class HelloPrinter implements Runnable {
volatile boolean cancel = false;
#Override
public void run() {
while (!cancel) {
printHello();
}
}
public void cancelPrint() {
cancel = true;
}
}
I assume you want to do more than just printouts. Take a look at Swing Worker.
It allows you to pretty easily write your GUI-related code that gets executed in the AWT Event Thread and your long-executing code in other thread(s) and pass values back and forth. This will help prevent any GUI lockup issues you might experience.
private class MultipleGensListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
for(int i = 0; i < 25; i++)
{
game.runSimulationOneGen();
changeGrid();
}
}
}
//this is the loop. The changeGrid method displays a game grid on a GUI but
// only the 25th iteration is visible on screen. I would like each one to be
// visible for about a half a second before the loop continues.
// I have seen some questions answered on here that are very close to what I'm asking,
// but I just don't really understand how to apply it to my program..
// thanks for any help.
If the code performed by the simulation is quick and does not consume too much CPU and time, then consider using a Swing Timer to do your looping and delay. Otherwise, you'll need to use a background thread such as can be done with a SwingWorker object.
For e.g. if using both Swing Timer and SwingWorker:
private class MultipleGensListener implements ActionListener {
protected static final int MAX_INDEX = 25;
public void actionPerformed(ActionEvent e) {
int timerDelay = 500; // ms delay
new Timer(timerDelay, new ActionListener() {
int index = 0;
public void actionPerformed(ActionEvent e) {
if (index < MAX_INDEX) { // loop only MAX_INDEX times
index++;
// create the SwingWorker and execute it
new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
game.runSimulationOneGen(); // this is done in background thread.
return null;
}
#Override
protected void done() {
changeGrid(); // this is called on EDT after background thread done.
}
}.execute(); // execute the SwingWorker
} else {
((Timer) e.getSource()).stop(); // stop the timer
}
}
}).start(); // start the Swing timer
}
}
NEVER BLOCK THE GUI EVENT THREAD
you can use a timer for that and have it only fire 25 times
final Timer t = new Timer(500,null);
t.addActionListener(new ActionListener(){
int i=0;
public void actionPerformed(ActionEvent e){
game.runSimulationOneGen();//run 1 iteration per tick
changeGrid();
if(i>25){t.stop();}
i++;
}
});
t.setRepeats(true);
t.start();
btw the reason only the last iteration is shown is that gui updates (redraws) are done in a separate event, but to let another event trigger you need to return from the listener method which you didn't
the Timer I showed is a more elaborate iteration which lets other events run in between iterations allowing the gui to show the changes
check my post that shows both methods java.swing.Timer#setDelay(int)
and
correct usage of Thread.sleep(int)
java wait cursor display problem