stop infinite loop using stop button - java

After starting infinite loop, I am unable to close JFrame.
I want to stop infinite loop using stop button.
I am starting an infinite loop using start button. I want close that loop using stop button.
if(stop.getModel().isPressed()){break;} is not working
actionListener used to identify button click and using break statement to terminate while loop is also not working
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class NewClass1 {
private String arg = "";
public NewClass1()
{
JFrame frame = new JFrame("Datacolor software automate");
JButton stop = new JButton("STOP");
stop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae)
{
arg = (String)ae.getActionCommand();
System.out.println(arg);
}
});
JButton button = new JButton("Start");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
int i = 0;
while (true)
{
try {
System.out.println(i);
i++;
if(arg.equals("STOP"))
{
break;
}
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
}
});
frame.add(button);
frame.add(stop);
frame.setLayout(new FlowLayout());
frame.setSize(300,300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run()
{
new NewClass1();
}
});
}
}
On clicking stop button infinite loop must terminate. I able not able to use any buttons in JFrame after starting infinite loop using start buttton.

You cannot click "Stop" button in the first place, and this is because you run a big task (the while(true) part of your code) in the Event Dispatch Thread which will cause your whole GUI to freeze.
In order to avoid this, and make it work, you will have to use a SwingWorker. A class that allows you to run long/heavy tasks in the background and (optionally) publish them in GUI.
Then, if you want to cancel this SwingWorker, a call to its cancel() method will be enough.
Take a look at the following example:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class NewClass1 {
private String arg = "";
private SwingWorker<Void, Integer> worker;
public NewClass1() {
JFrame frame = new JFrame("Datacolor software automate");
JButton stop = new JButton("STOP");
stop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
worker.cancel(true);
}
});
JButton button = new JButton("Start");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
initializeWorker();
worker.execute();
}
});
frame.add(button);
frame.add(stop);
frame.setLayout(new FlowLayout());
frame.setSize(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void initializeWorker() {
worker = new SwingWorker<Void, Integer>() {
#Override
protected Void doInBackground() throws Exception {
int i = 0;
while (!isCancelled()) {
i++;
publish(i); // give this i to "process" method
}
return null;
}
#Override
protected void process(List<Integer> chunks) {
int i = chunks.get(0);
System.out.println(i);
}
};
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new NewClass1());
}
}

Related

Changing a label text at the start and the end of an ActionListener

I have a process to be performed in an ActionListener call. This process can take some time. So I have to inform that is processing during the time of the execution in a label.
My problem is that Swing doesn't repaint the label during the thread of ActionListener, so I can't show the "Processing" message.
What is the best way to solve that?
package test;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MyTestPane extends JPanel{
/**
*
*/
private static final long serialVersionUID = 340444475514103360L;
private JLabel myLabel;
private JButton myButton;
public MyTestPane() {
initComponents();
}
private void initComponents() {
myLabel = new JLabel("Ready");
myButton = new JButton("Start");
myButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
myActionListenter();
}
});
add(myLabel);
add(myButton);
}
private void myActionListenter(){
myLabel.setText("Starting count ...");
try{
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
myLabel.setText("Finishing count ...");
}
public static final void main(String argv[]) {
JFrame frame = new JFrame();
frame.add(new MyTestPane());
frame.pack();
frame.setVisible(true);
}
}
When you want to do something heavy (in terms of time required to be finished), like Thread.sleep, you can't simply do it in the same thread the GUI runs. When your heavy task starts on the same thread as the GUI, the GUI thread is busy calculating your heavy task and therefore it cannot receive any events. That's why the whole GUI freezes. Because it is busy.
Now in order to solve that read concurrency in Swing.
To sum it up for you, all Swing applications must run on their single-per-application thread. This thread is called the Event Dispatch Thread. Because all GUI events (mouse pointers moving, buttons clicked, windows resizing, etc) happen there.
So, when you want to do something heavy, you do it in another thread and since they are invisible to the user(GUI) they are called background threads. Swing has its own API to create background threads. They are called SwingWorkers. You can find how to use one in the doc.
Here is an example of doing something heavy (Thread.sleep) and at the same time publishing the progress (I don't know if you are interested in that). Also, I try to keep things some sort of abstract, in order to keep the concerns separated.
I suggest you to run it and have some experiments with it.
public class WorkerExample {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
MyPanel myPanel = new MyPanel();
myPanel.setPreferredSize(new Dimension(400, 300));
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(myPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
private static class MyPanel extends JPanel implements ProgressableView {
private JLabel countLabel;
private JProgressBar progressBar;
public MyPanel() {
super(new FlowLayout());
countLabel = new JLabel("Progress: 0");
add(countLabel);
progressBar = new JProgressBar();
progressBar.setVisible(false);
add(progressBar);
JButton startHeavyTaskButton = new JButton("Start Heavy Task");
startHeavyTaskButton.addActionListener(e -> {
startHeavyTaskButton.setEnabled(false);
startHeavyTaskButton.setText("Please wait..");
progressBar.setValue(0);
progressBar.setVisible(true);
Runnable restoreButtonAvailability = () -> {
startHeavyTaskButton.setEnabled(true);
startHeavyTaskButton.setText("Start Heavy Task");
};
new DoSomethingHeavyAndShowProgressWorker(this, restoreButtonAvailability).execute();
});
add(startHeavyTaskButton);
}
#Override
public void setProgress(int progress) {
if (progress >= 99) {
countLabel.setText("Finished!!");
progressBar.setVisible(false);
} else {
progressBar.setValue(progress);
countLabel.setText("Progress: " + progress);
}
}
}
private static interface ProgressableView {
void setProgress(int progress);
}
private static class DoSomethingHeavyAndShowProgressWorker extends SwingWorker<Void, Integer> {
private ProgressableView view;
private Runnable onDone;
public DoSomethingHeavyAndShowProgressWorker(ProgressableView view, Runnable onDone) {
this.view = view;
this.onDone = onDone;
}
#Override
protected Void doInBackground() throws Exception {
for (int i = 0; i < 100; i++) {
Thread.sleep(200);
publish((i + 1)); // Publish will call process() method in the GUI thread
}
return null;
}
#Override
protected void process(List<Integer> chunks) {
if (chunks.isEmpty())
return;
int progress = chunks.get(chunks.size() - 1);
view.setProgress(progress);
}
#Override
protected void done() {
try {
get(); // To catch exceptions happend in background
if (onDone != null)
onDone.run();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
Here is a preview:
I put the counter code in a separate thread so it would run separately from the Event Dispatch Thread that all Swing components must be created and executed.
Here's the complete runnable code.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TimerTestPanel extends JPanel {
private static final long serialVersionUID = 340444475514103360L;
private JLabel myLabel;
private JButton myButton;
public TimerTestPanel() {
initComponents();
}
private void initComponents() {
myLabel = new JLabel("Ready");
myButton = new JButton("Start");
myButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
myActionListenter();
}
});
add(myLabel);
add(myButton);
}
private void myActionListenter() {
myLabel.setText("Starting count ...");
new Thread(new Counter()).start();
}
public static final void main(String argv[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TimerTestPanel());
frame.pack();
frame.setVisible(true);
}
});
}
public class Counter implements Runnable {
#Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
myLabel.setText("Finishing count ...");
}
});
}
}
}
I think I can use an invokeLater to perform the process, so the ActionListener can change the label without waiting de long process to be finished, but I don't if it is the best solution.
package test;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MyTestPane extends JPanel{
/**
*
*/
private static final long serialVersionUID = 340444475514103360L;
private JLabel myLabel;
private JButton myButton;
public MyTestPane() {
initComponents();
}
private void initComponents() {
myLabel = new JLabel("Ready");
myButton = new JButton("Start");
myButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
myActionListenter();
}
});
add(myLabel);
add(myButton);
}
private void myActionListenter(){
myLabel.setText("Starting count ...");
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try{
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
myLabel.setText("Finishing count ...");
}
});
}
public static final void main(String argv[]) {
JFrame frame = new JFrame();
frame.add(new MyTestPane());
frame.pack();
frame.setVisible(true);
}
}

Java swing Loader image not displaying properly? [duplicate]

This question already has answers here:
Java swing GUI freezes
(5 answers)
Closed 5 years ago.
I have tried the below code .
Functionality-
Click on Button
It will call a method which will take some time to process.
Need to display Loader image so that user can see that processing is going on.
I tried below but if the loaderLabel1.setVisible(true); before method call doesnot show image and if we comment loaderLabel1.setVisible(false); then it shows loader image after method is finished.
Will actionPerformed method not apply the visibility to Label unless it completes? If yes is there any alternative for this problem?
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TestLoader extends JPanel{
static ImageIcon loading1 = new ImageIcon("D:\\WORKSPACE\\STUDY\\images\\ajax-loader.gif");
static JLabel loaderLabel1 = new JLabel(loading1, JLabel.CENTER);
public TestLoader(){
super(new GridLayout(0, 1));
System.out.println("---------TEST ------");
JPanel submitPanel = new JPanel();
submitPanel.add(clearMessageButton);
this.add(submitPanel);
JPanel LOADER_PANEL = new JPanel();
loaderLabel1.setVisible(false);
LOADER_PANEL.add(loaderLabel1);
this.add(LOADER_PANEL);
}
JButton clearMessageButton = new JButton(new AbstractAction("Test Result") {
#Override
public void actionPerformed(ActionEvent arg0) {
loaderLabel1.setVisible(true);
TestMethod();
loaderLabel1.setVisible(false);
}});
public void TestMethod(){
System.out.println(" =========START TestMethod =========");
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" =========complete TestMethod =========");
}
/**
* #param args
*/
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TestLoader pf = new TestLoader();
pf.display();
}
});
}
private void display() {
JFrame frame = new JFrame("TEST LOADER");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
There is the class SwingWorker that allows you to perform Tasks in a different thread; here's an example of how your code could be changed to use a SwingWorker:
JButton clearMessageButton = new JButton(new AbstractAction("Test Result") {
#Override
public void actionPerformed(ActionEvent arg0) {
SwingWorker worker = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
loaderLabel1.setVisible(true);
TestMethod();
return true;
}
public void TestMethod() {
System.out.println(" =========START TestMethod =========");
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" =========complete TestMethod =========");
}
protected void done() {
loaderLabel1.setVisible(false);
};
};
worker.execute();
}
});
Note the methods doInBackground() that does the work in the other thread and done() that is called after doInBackground() is finished.

Update a JPopupMenu menu items while it is open

In my UI i have a JPopMenu with values as ,
for e.g A,B,C
The scenario is,
I opened the JPopupMenu and kept it open.
At back end with a timer running , it updates the content B to some other alphabet at frequent interval.
3.I want the JPopupMenu to get updated while it is kept open.
In current behavior if i close and open JPopupMenu the updated value shows up.
I tried repaint()but it doesn't do anything.
What is the best way to do this?? Am new to swings please help.
Menu items can change their content at run time just fine. Without seeing your code it's hard to tell what you're doing wrong, but here's a working example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
public class PopupTest {
private static final String[] messages = {
"You are today's 1000th user!",
"You have won an internet!",
"Claim your prize!"
};
private PopupTest() {
JFrame frame = new JFrame("You have won");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel("Check your prize!");
frame.setLocationByPlatform(true);
frame.add(lbl);
frame.pack();
final JPopupMenu menu = new JPopupMenu();
final JMenuItem item = new JMenuItem(messages[0]);
menu.add(item);
menu.add(new JMenuItem("Another item that does not work"));
final Timer timer = new Timer(1000, new ActionListener() {
int count;
#Override
public void actionPerformed(ActionEvent e) {
count++;
count %= messages.length;
item.setText(messages[count]);
}
});
menu.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
timer.stop();
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
timer.stop();
}
});
lbl.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
#Override
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
menu.show(e.getComponent(), e.getX(), e.getY());
timer.start();
}
}
});
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new PopupTest();
}
});
}
}
Try to use .revalidate() with .repaint() it might help.
The docs suggest that the revalidate method is called every time something like size changes and manually calling it with repaint seems to solve problems like these.

Using SwingWorker to update the progress of a thread from another class

Value is updated by the end, but not during the process. I guess the reason is that the publish method locates outside the loop.
As to invoke PropertyChangeListener, can it be achieved by defining the class without extends SwingWorker<Void, Void> ?
To address the question in another way, I have two threads locate in two different classes. Is it possible to build communication between the two using SwingWorker?
Class Application
import javax.swing.JFrame;
public class Application {
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
JFrame frame = new Progress();
frame.setSize(200, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
Class Progress
import java.awt.BorderLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
#SuppressWarnings("serial")
public class Progress extends JFrame{
private JProgressBar progressbar;
public Progress(){
JButton button = new JButton("Run");
progressbar = new JProgressBar(0, 100);
progressbar.setValue(0);
progressbar.setStringPainted(true);
JPanel panel = new JPanel();
panel.add(button);
panel.add(progressbar);
add(panel, BorderLayout.PAGE_START);
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
start();
}
});
}
private void start(){
progressbar.setValue(0);
SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>(){
#Override
protected Void doInBackground() throws Exception {
Simulation sim = new Simulation();
publish(sim.getCount());
return null;
}
#Override
protected void process(List<Integer> chunks) {
Integer progress = chunks.get(chunks.size()-1);
progressbar.setValue(progress);
progressbar.repaint();
progressbar.update(progressbar.getGraphics());
}
#Override
protected void done() {
Toolkit.getDefaultToolkit().beep();
}
};
worker.execute();
}
}
Class Simulation
public class Simulation {
private int count;
public Simulation(){
for(int i=0; i<100; i++){
count++;
System.out.println(count);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getCount(){
return count;
}
}
How can I update the value during the process?
You need to implement PropertyChangeListener on your SwingWorker and listen to the Progress property changes and then from overridden propertChange() method update your JProgressBar.
Here is what you are looking.
Hope this helps.

JProgressBar not updating

I have made a very simple code to show it here, i have a button that should show a JDialog to check the progress status, i am using the invoke late to go through EDT and my loop isn't in the run method, so why isn't my bar updating ?
here is the code
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class JBarEx extends JFrame {
private JTextField progStatus = new JTextField("Undefined");
private JButton dialogBtn = new JButton("Show Progression dialog");
final JDialog dlg = new JDialog((JFrame) null, "prog Title", false);
final JProgressBar dpb = new JProgressBar(0, 100);
public JBarEx() {
JPanel pan = new JPanel();
dialogBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
showProgress();
}
});
progStatus.setEditable(false);
pan.add(progStatus);
pan.add(dialogBtn);
setContentPane(pan);
this.setSize(200, 100);
setVisible(true);
}
public void showProgress() {
dlg.add(BorderLayout.CENTER, dpb);
dlg.add(BorderLayout.NORTH, new JLabel("prog message"));
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.setSize(300, 75);
dlg.setLocationRelativeTo(null);
dlg.setVisible(true);
for (int i = 0; i < 100; i++) {
final int ii = i;
try {
Thread.sleep(25);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
updateBar(ii);
}
});
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void updateBar(int newValue) {
dpb.setValue(newValue);
}
public static void main(String[] args) {
JBarEx jbx = new JBarEx();
}
}
Your showProgress method is being executed within the context of the Event Dispatching Thread. The EDT is responsible for, amongst other things, processing paint requests. This means that so long as your for-loop is executing, the EDT can not process any new paint requests (or handle the invokeLater events either) as it is blocking the EDT.
While there are any number of possible ways to solve the problem, based on your code example, the simplest would be to use a SwingWorker.
It has the capacity to allow your to execute the long running task the a background thread (freeing up the EDT), but also allows you means for publishing updates (if required) so that they can be processed in the EDT and also provides handy progress notification.
For example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class SwingWorkerProgress {
public static void main(String[] args) {
new SwingWorkerProgress();
}
public SwingWorkerProgress() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JProgressBar pbProgress;
private JButton start;
public TestPane() {
setBorder(new EmptyBorder(10, 10, 10, 10));
pbProgress = new JProgressBar();
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 0;
gbc.gridy = 0;
add(pbProgress, gbc);
start = new JButton("Start");
gbc.gridy++;
add(start, gbc);
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
start.setEnabled(false);
ProgressWorker pw = new ProgressWorker();
pw.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if (name.equals("progress")) {
int progress = (int) evt.getNewValue();
pbProgress.setValue(progress);
repaint();
} else if (name.equals("state")) {
SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
switch (state) {
case DONE:
start.setEnabled(true);
break;
}
}
}
});
pw.execute();
}
});
}
}
public class ProgressWorker extends SwingWorker<Object, Object> {
#Override
protected Object doInBackground() throws Exception {
for (int i = 0; i < 100; i++) {
setProgress(i);
try {
Thread.sleep(25);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
}
Check out Concurrency in Swing for more details
Even if you fix the loop as others have pointed out, you'd still block the event dispatch thread. The for loop is run in showProgress() which is called from an event listener. The updates are pushed to the event queue, but that does not get processed until the loop has completed.
Use a Swing Timer instead. Something like this:
Timer timer = new Timer(25, new ActionListener() {
private int position;
#Override
public void actionPerformed(ActionEvent e) {
position++;
if (position < lastPosition) {
updateBar(position);
} else {
((Timer) e.getSource).stop();
}
}
});
timer.start();
where lastPosition would be the state where you want the progress bar to stop.
Unrelated to that bug, but a bug still, you should not create swing components outside the event dispatch thread. It's best to do it right from the start:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JBarEx jbx = new JBarEx();
}
});
}
for (int i = 0; i < 0; i++) {
You will never enter this code so will never call the updateBar(..) method
i needs to be greater than 0 in this case. If it is 1 then updateBar will be called once, if 2 then updateBar will be called twice etc
Also rather than doing
Thread.sleep(25);
take a look at java executors as these will help with your scheduling and remove the need for the sleep

Categories

Resources