How to share data with two(2) SwingWorker class in Java - java

I have two SwingWorker class: FileLineCounterThread and FileDivisionThread
I will execute the two threads. When the lines counting thread finishes, it will pass the result to File Division thread.
I do not have an idea on how to pass the result to started thread.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
public class ExecutorAndSwingWorker2 {
private JFrame frame = new JFrame();
private JButton button1;
private JButton button2;
private JButton button3;
private JButton button4;
private JPanel buttonPanel = new JPanel();
private Executor executor = Executors.newCachedThreadPool();
private javax.swing.Timer timer1;
private javax.swing.Timer timer2;
private javax.swing.Timer timer3;
private javax.swing.Timer timer4;
private Random random = new Random();
public ExecutorAndSwingWorker2() {
button1 = new JButton(" Executor + SwingWorker Thread No.1 ");
button1.setFocusable(false);
button2 = new JButton(" Executor + SwingWorker Thread No.2 ");
button3 = new JButton(" Executor + SwingWorker Thread No.3 ");
button4 = new JButton(" Executor + SwingWorker Thread No.4 ");
buttonPanel = new JPanel();
buttonPanel.setBorder(new EmptyBorder(15, 15, 15, 15));
buttonPanel.setLayout(new GridLayout(2, 2, 20, 20));
buttonPanel.add(button1);
buttonPanel.add(button2);
buttonPanel.add(button3);
buttonPanel.add(button4);
frame.setTitle("Shaking Button Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(buttonPanel);
frame.setPreferredSize(new Dimension(700, 170));
frame.setLocation(150, 100);
frame.pack();
frame.setVisible(true);
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton1")); // non on EDT
}
private void startButton1() {
System.out.println("Starting long Thread == startButton1()");
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
}
}
private void startButton2() {
System.out.println("Starting long Thread == startButton2()");
try {
Thread.sleep(17500);
} catch (InterruptedException ex) {
}
}
private void startButton3() {
System.out.println("Starting long Thread == startButton3()");
try {
Thread.sleep(12500);
} catch (InterruptedException ex) {
}
}
private void startButton4() {
System.out.println("Starting long Thread == startButton4()");
try {
Thread.sleep(20000);
} catch (InterruptedException ex) {
}
}
private void colorAction1() {
timer1 = new Timer(1000, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
random = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
button1.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)));
button1.validate();
button1.repaint();
}
});
}
});
timer1.setDelay(500);
timer1.setRepeats(true);
timer1.start();
}
private void colorAction2() {
timer2 = new Timer(1200, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
random = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
button2.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)));
button2.validate();
button2.repaint();
}
});
}
});
timer2.setDelay(500);
timer2.setRepeats(true);
timer2.start();
}
private void colorAction3() {
timer3 = new Timer(1400, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
random = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
button3.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)));
button3.validate();
button3.repaint();
}
});
}
});
timer3.setDelay(500);
timer3.setRepeats(true);
timer3.start();
}
private void colorAction4() {
timer4 = new Timer(1600, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
random = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
button4.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)));
button4.validate();
button4.repaint();
}
});
}
});
timer4.setDelay(500);
timer4.setRepeats(true);
timer4.start();
}
private void endButton1() {
timer1.stop();
button1.setBackground(null);
System.out.println("Long Thread Ends == startButton1()");
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton3")); // non on EDT
}
private void endButton2() {
timer2.stop();
button2.setBackground(null);
System.out.println("Long Thread Ends == startButton2()");
}
private void endButton3() {
timer3.stop();
button3.setBackground(null);
System.out.println("Long Thread Ends == startButton3()");
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton2")); // non on EDT
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton4")); // non on EDT
}
private void endButton4() {
timer4.stop();
button4.setBackground(null);
System.out.println("Long Thread Ends == startButton4()");
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton1")); // non on EDT
}
private class MyTask extends SwingWorker<Void, Integer> {
private String str;
private String namePr;
private JDialog dialog = new JDialog();
MyTask(String str) {
this.str = str;
addPropertyChangeListener(new SwingWorkerCompletionWaiter(dialog, str, namePr));
}
#Override
protected Void doInBackground() throws Exception {
if (str.equals("startButton1")) {
colorAction1();
startButton1();
} else if (str.equals("startButton2")) {
colorAction2();
startButton2();
} else if (str.equals("startButton3")) {
colorAction3();
startButton3();
} else if (str.equals("startButton4")) {
colorAction4();
startButton4();
}
return null;
}
#Override
protected void process(List<Integer> progress) {
System.out.println(str + " " + progress.get(progress.size() - 1));
}
#Override
protected void done() {
if (str.equals("startButton1")) {
endButton1();
} else if (str.equals("startButton2")) {
endButton2();
} else if (str.equals("startButton3")) {
endButton3();
} else if (str.equals("startButton4")) {
endButton4();
}
}
}
private class SwingWorkerCompletionWaiter implements PropertyChangeListener {
private JDialog dialog;
private String str;
private String namePr;
SwingWorkerCompletionWaiter(JDialog dialog, String str, String namePr) {
this.dialog = dialog;
this.str = str;
this.namePr = namePr;
}
#Override
public void propertyChange(PropertyChangeEvent event) {
if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) {
System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue());
} else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) {
System.out.println("Thread Status with Mame :" + str + ", SwingWorker Status is " + event.getNewValue());
} else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) {
System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue());
} else {
System.out.println("Thread Status with Name :" + str + ", Something wrong happends ");
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ExecutorAndSwingWorker2 executorAndSwingWorker = new ExecutorAndSwingWorker2();
}
});
}
}

SwingWorker.execute() is buggy and will only execute tasks serially. Use ExecutorService.execute() for concurrency:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RunnableFuture;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
public class MyFrame extends JFrame implements ActionListener {
/**
* Test Driver
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame frame = new MyFrame("Swing Concurrency Test");
frame.setVisible(true);
}
});
}
/**
* Thread Executor
* (must be explicitly shutdown, see WindowAdapter below)
*/
private final ExecutorService exec = Executors.newFixedThreadPool(2);
/**
* Button action
*/
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
textArea.append("\nStarting both tasks...\n");
// start both tasks, pass a reference to outer task
FileLineCounterThread counterTask = new FileLineCounterThread();
exec.execute(counterTask);
FileDivisionThread divisionTask = new FileDivisionThread(counterTask);
exec.execute(divisionTask);
}
/**
* Counter task
*/
private class FileLineCounterThread extends SwingWorker<Long, String> {
private String template = "[FileLineCounterThread] %s\n";
#Override
protected Long doInBackground() throws Exception {
// do some work
publish("started...");
Thread.sleep(10000);
// return the result
return 42L;
}
#Override
protected void process(List<String> chunks) {
for (String chunk : chunks) {
textArea.append(String.format(template, chunk));
}
}
#Override
protected void done() {
try {
textArea.append(String.format(
template, "complete. Counted: " + get()));
}
catch (Exception e) {
// catch any exceptions thrown during execution
e.printStackTrace();
}
}
}
/**
* File Division task
*/
private class FileDivisionThread extends SwingWorker<String, String> {
private RunnableFuture<Long> counterTask;
private String template = " [FileDivisionThread] %s\n";
public FileDivisionThread(RunnableFuture<Long> counterTask) {
this.counterTask = counterTask;
}
#Override
protected String doInBackground() throws Exception {
// do some initial work
publish("started...");
Thread.sleep(2000);
// wait for other task to complete and get result
publish("Waiting for line counter to finish...");
long numLines = counterTask.get();
publish("Line count received: " + numLines);
// do the rest of the work and return result
Thread.sleep(5000);
return "complete.";
}
#Override
protected void process(List<String> chunks) {
for (String chunk : chunks) {
textArea.append(String.format(template, chunk));
}
}
#Override
protected void done() {
try {
textArea.append(String.format(template, get()));
button.setEnabled(true);
}
catch (Exception e) {
// catch any exceptions thrown during execution
e.printStackTrace();
}
}
}
/////////////////////////
//// GUI Boilerplate ////
/////////////////////////
private JScrollPane scroller = new JScrollPane();
private JTextArea textArea = new JTextArea();
private JButton button = new JButton("Start");
public MyFrame(String windowTitle) {
super(windowTitle);
initComponents();
}
private void initComponents() {
addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
exec.shutdownNow();
System.exit(0);
}
});
button = new JButton("Start");
button.addActionListener(this);
textArea = new JTextArea();
textArea.setColumns(35);
textArea.setRows(15);
scroller.setViewportView(textArea);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.insets = new Insets(10, 0, 0, 0);
getContentPane().add(button, gridBagConstraints);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new Insets(10, 10, 10, 10);
getContentPane().add(scroller, gridBagConstraints);
pack();
}
}

PipedReader/Writer for character data & PipedInput/OutputStream for binary data
in java.io.
Regards,
Stéphane

never hands up, never surrender its possible with Executor and SwingWorker
1/ bug for Executor and SwingWorker
2/ hold and check number of thread started by Executor and live SwingWorkers threads with intentions to avoid caught above mentioned bug
3/ check maximum numbers for Executor or restict that to final munber
EDIT changed by OP's requirements
import java.beans.*;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.swing.JDialog;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class ExecutorAndSwingWorker1 {
private static Executor executor = Executors.newCachedThreadPool();
private static void startButton1() {
System.out.println("Starting long Tread == startButton1()");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
private static void startButton2() {
System.out.println("Starting long Tread == startButton2()");
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
}
}
private static void startButton3() {
System.out.println("Starting long Tread == startButton3()");
try {
Thread.sleep(1500);
} catch (InterruptedException ex) {
}
}
private static void startButton4() {
System.out.println("Starting long Tread == startButton4()");
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
}
}
private static void endButton1() {
System.out.println("Long Tread Ends == startButton1()");
executor.execute(new ExecutorAndSwingWorker1.MyTask("startButton3")); // non on EDT
}
private static void endButton2() {
System.out.println("Long Tread Ends == startButton2()");
executor.execute(new ExecutorAndSwingWorker1.MyTask("startButton4")); // non on EDT
}
private static void endButton3() {
System.out.println("Long Tread Ends == startButton3()");
}
private static void endButton4() {
System.out.println("Long Tread Ends == startButton3()");
}
private static class MyTask extends SwingWorker<Void, Integer> {
private String str;
private String namePr;
private JDialog dialog = new JDialog();
MyTask(String str) {
this.str = str;
addPropertyChangeListener(new SwingWorkerCompletionWaiter(dialog, str, namePr));
}
#Override
protected Void doInBackground() throws Exception {
if (str.equals("startButton1")) {
startButton1();
} else if (str.equals("startButton2")) {
startButton2();
} else if (str.equals("startButton3")) {
startButton3();
} else if (str.equals("startButton4")) {
startButton4();
}
return null;
}
#Override
protected void process(List<Integer> progress) {
System.out.println(str + " " + progress.get(progress.size() - 1));
}
#Override
protected void done() {
if (str.equals("startButton1")) {
endButton1();
} else if (str.equals("startButton2")) {
endButton2();
} else if (str.equals("startButton3")) {
endButton3();
} else if (str.equals("startButton4")) {
endButton4();
}
}
}
private static class SwingWorkerCompletionWaiter implements PropertyChangeListener {
private JDialog dialog;
private String str;
private String namePr;
SwingWorkerCompletionWaiter(JDialog dialog, String str, String namePr) {
this.dialog = dialog;
this.str = str;
this.namePr = namePr;
}
#Override
public void propertyChange(PropertyChangeEvent event) {
if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) {
System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue());
} else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) {
System.out.println("Thread Status with Mame :" + str + ", SwingWorker Status is " + event.getNewValue());
} else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) {
System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue());
} else {
System.out.println("Thread Status with Name :" + str + ", Something wrong happends ");
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
executor.execute(new ExecutorAndSwingWorker1.MyTask("startButton1")); // non on EDT
executor.execute(new ExecutorAndSwingWorker1.MyTask("startButton2")); // non on EDT
}
});
}
private ExecutorAndSwingWorker1() {
}
}

I am not sure this is a solution you should use, and it undermines the simplicity and safety you get from using SwingWorker, but I'll mention it for completeness.
Put two fields where both threads can see them: one boolean, called hasValue, initialized to false, and one int (or long) called countValue. Both must be declared as volatile. When the counter thread is done, put the count in countValue. Then set hasValue to true. The division thread can then check `hasValue' periodically and grab the count when it is available.
If the division is providing values that will be more accurate once it gets the count, this will do. More likely, it is doing some work, then waiting for the count. In this case, set up a third field called countMonitor, defined as final Object. When it finishes the initial work, have it check hasValue. If it's true, grab the value and continue. If it's false, call the wait method on countMonitor and continue when notified. The counter thread, when done, should always call the notifyAll method on countMonitor after putting values in hasValue and countValue.
I've left out a bit here. The javadoc for Object will tell you about needed synchronization and checked exceptions. Your design is straightforward enough that you won't be troubled with the usual supernatural horror stories multi-threading generates. I hope. But you might want to do a bit of research if you go this route. (If you repeat the whole process in the same session, you will definitely want to do a lot of research.)

Related

Java Threading: make GUI wait before showing each message when receiving multiple messages instantly

I would like to implement a frame where you can press a button to make a call, and then either the respondent, the manager or the director would respond to the call, and it would output on the screen who answered the call.
If an employee is not available, I would like to show on the console. So for example if respondent and manager are not available, I would like the output to look like this:
Respondent busy. Forwarding to manager.
Manager busy. Forwarding to Director.
Director answered the call.
With my implementations these messages are shown, but they are all showed instantly. I would like to set some waiting time between the messages, like:
shows message: "Manager is busy. Forwarding to director"
waits 2 seconds
shows message: "Director answered the call"
CallHandler.java:
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class CallHandler implements Runnable{
private ArrayList<Employee> employees = new ArrayList<>();
private MyFrame view;
public CallHandler(){
employees.add(new Respondent());
employees.add(new Manager());
employees.add(new Director());
view = new MyFrame(this);
}
public void dispatchCall() throws InterruptedException {
boolean dialing = true;
while(dialing) {
for (Employee employee : getAvailableEmployees()) {
Status status = employee.call();
if (status == Status.ANSWERED) {
(new Thread(employee)).start();
sendMessage(employee.getClass().getName() + " has answered the call.");
dialing = false;
break;
}
sendMessage(employee.getClass().getName() + " is busy. You will be redirected to the next available employee.");
}
if (dialing)
sendMessage("No one is available at the moment. Please wait...");
}
}
private void sendMessage(String msg) throws InterruptedException {
view.addMessage(msg);
}
private ArrayList<Employee> getAvailableEmployees(){
return employees.stream().filter(Employee::isFree).collect(Collectors.toCollection(ArrayList::new));
}
public static void main(String args[]){
CallHandler handler = new CallHandler();
}
#Override
public void run() {
try{
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException e) {
System.out.println("Call got interrupted");
}
}
}
MyFrame.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
public class MyFrame extends JFrame implements Runnable {
private static final int WIDTH = 800;
private static final int HEIGHT = 500;
private static final int PANEL_WIDTH = 600;
private static final int PANEL_HEIGHT = 290;
private final JPanel panel = new JPanel();
private final ArrayList<JLabel> labels = new ArrayList<>();
private int rowIndex = 0;
private static final int ROWS = 17;
private CallHandler handler = null;
private Timer timer;
MyFrame(CallHandler callHandler) {
handler = callHandler;
this.setLayout(null);
setVisible(true);
setSize(WIDTH, HEIGHT);
add(panel);
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.setBackground(Color.GREEN);
panel.setBounds(100, 50, PANEL_WIDTH, PANEL_HEIGHT);
JButton btn = new JButton("Make call");
btn.setBounds(350, 370, 100, 80);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
handler.dispatchCall();
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
});
this.add(btn);
initiateRows();
}
public void addMessage(String msg) throws InterruptedException {
if (rowIndex < ROWS) {
getLabel(rowIndex).setText(msg);
rowIndex++;
} else {
System.out.println("removing first component");
removeComponent(0);
addRow(msg);
}
panel.updateUI();
// Thread.sleep(1000);
}
private void initiateRows() {
for (int i = 0; i < ROWS; i++) {
addRow("");
}
}
private void addRow(String msg) {
JLabel label = new JLabel(msg);
label.setAlignmentX(Component.CENTER_ALIGNMENT);
labels.add(label);
panel.add(label);
}
private JLabel getLabel(int i) {
return (JLabel) panel.getComponent(i);
}
private void removeComponent(int i) {
panel.remove(i);
}
public static void main(String args[]) {
MyFrame f = new MyFrame(new CallHandler());
}
#Override
public void run() {
try{
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException e) {
System.out.println("Call got interrupted");
}
}
}

Multi-threading with GUI in Java

I'm working on a GUI for a program that is computationally intensive and takes some period of time to complete calculations. I want to display and update the processing time on the GUI, both for reference and as an indication to the user that the program is running. I've created a worker to deal with the processing time on a separate thread as follows:
public class Worker extends SwingWorker<String, String>{
JLabel label;
boolean run;
public Worker(JLabel label)
{
this.label = label;
this.run = true;
}
#Override
protected String doInBackground() throws Exception {
//This is what's called in the .execute method
long startTime = System.nanoTime();
while(run)
{
//This sends the results to the .process method
publish(String.valueOf(System.nanoTime() - startTime));
Thread.sleep(100);
}
return null;
}
public void stop()
{
run = false;
}
#Override
protected void process(List<String> item) {
double seconds = Long.parseLong(item.get(item.size()-1))/1000000000.0;
String secs = String.format("%.2f", seconds);
//This updates the UI
label.setText("Processing Time: " + secs + " secs");
label.repaint();
}
}
I pass a JLabel to the Worker which it displays the processing time on. The following code creates the Worker and executes a runnable that carries out the main calculations.
Worker worker = new Worker(jLabelProcessTime);
worker.execute();
//Check for results truncation
boolean truncate = !jCheckBoxTruncate.isSelected();
long startTime = System.nanoTime();
String[] args = {fileName};
//run solution and draw graph
SpeciesSelection specSel = new SpeciesSelection(args, truncate);
Thread t = new Thread(specSel);
t.start();
t.join();
ArrayList<Double> result = specSel.getResult();
drawGraph(result);
worker.stop();
My problem is that the processing time does not update on the GUI until after the calculations have finished. I think I'm pretty close because without 't.join();' the timer updates fine, but the processing never completes. I'd really appreciate some help to figure out what's wrong.
Your code is not working as you think it is...
I created MVCE for you...
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.JLabel;
import javax.swing.SwingWorker;
public class SwingWorkerTest extends JFrame {
public SwingWorkerTest() {
this.setLayout(new FlowLayout());
JButton button = new JButton("run");
JLabel label = new JLabel("time: -");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Worker worker = new Worker(label);
worker.execute();
//Check for results truncation
// boolean truncate = !jCheckBoxTruncate.isSelected();
// long startTime = System.nanoTime();
// String[] args = {fileName};
//run solution and draw graph
// SpeciesSelection specSel = new SpeciesSelection(args, truncate);
// Thread t = new Thread(specSel);
// t.start();
// t.join();
// ArrayList<Double> result = specSel.getResult();
// drawGraph(result);
worker.stop();
System.out.println("button's actionPerformed finished");
}
});
this.getContentPane().add(button);
this.getContentPane().add(label);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
new SwingWorkerTest();
}
}
class Worker extends SwingWorker<String, String>{
JLabel label;
boolean run;
public Worker(JLabel label)
{
this.label = label;
this.run = true;
}
#Override
protected String doInBackground() throws Exception {
System.out.println("doInBackground..., run=" + run);
//This is what's called in the .execute method
long startTime = System.nanoTime();
// while(run)
// {
System.out.println("running...");
//This sends the results to the .process method
publish(String.valueOf(System.nanoTime() - startTime));
Thread.sleep(100);
// }
System.out.println("worker finished...");
return null;
}
public void stop()
{
// System.out.println("stop");
// run = false;
}
#Override
protected void process(List<String> item) {
System.out.println("processed");
double seconds = Long.parseLong(item.get(item.size()-1))/1000000000.0;
String secs = String.format("%.2f", seconds);
//This updates the UI
System.out.println("updating");
label.setText("Processing Time: " + secs + " secs");
// label.repaint();
}
}
In short I found, that Worker.stop() is called before doInBackground as a result, your run is false and so publish is never called.
The "fixed" code above prints (after start I resized and I clicked on run button):
button's actionPerformed finished
doInBackground..., run=true
running...
processed
updating
worker finished...
and it shows:
new approach with a timer
import java.awt.GridLayout;
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.SwingWorker;
import javax.swing.SwingWorker.StateValue;
import javax.swing.Timer;
public class SwingWorkerTestNew extends JFrame {
int progress = 0;
public SwingWorkerTestNew() {
GridLayout layout = new GridLayout(2, 1);
JButton button = new JButton("run");
JLabel label = new JLabel("progress: -");
WorkerNew worker = new WorkerNew(label);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
worker.execute();
System.out.println("button's actionPerformed finished");
}
});
this.getContentPane().setLayout(layout);
this.getContentPane().add(button);
this.getContentPane().add(label);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (worker.getState() == StateValue.STARTED) {
++progress;
label.setText(Integer.toString(progress));
}
if (worker.getState() == StateValue.DONE) {
label.setText("done");
}
}
});
timer.start();
}
public static void main(String[] args) {
new SwingWorkerTestNew();
}
}
class WorkerNew extends SwingWorker<String, String> {
JLabel label;
public WorkerNew(JLabel label) {
this.label = label;
}
#Override
protected String doInBackground() throws Exception {
System.out.println("background");
Thread.sleep(2000);
System.out.println("done");
return null;
}
}
I was going about this in a far too complicated manner. No SwingWorker was required. I solved it as follows:
//Check for results truncation
boolean truncate = !jCheckBoxTruncate.isSelected();
String[] args = {fileName};
//run solution and draw graph
SpeciesSelection specSel = new SpeciesSelection(args, truncate);
Thread t = new Thread(specSel);
t.start();
long startTime = System.nanoTime();
new Thread()
{
public void run() {
while(!specSel.isFinished())
{
double seconds = (System.nanoTime() - startTime)/1000000000.0;
String secs = String.format("%.2f", seconds);
jLabelProcessTime.setText("Processing Time: " + secs + " secs");
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(SpecSelGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
ArrayList<Double> result = specSel.getResult();
drawGraph(result);
}
}.start();

How can create timer with JLabel?

I want to display in my JPanel a JLabel with timer in this mode, for example:
03:50 sec
03:49 sec
....
....
00:00 sec
So I have build this code:
#SuppressWarnings("serial")
class TimeRefreshRace extends JLabel implements Runnable {
private boolean isAlive = false;
public void start() {
Thread t = new Thread(this);
isAlive = true;
t.start();
}
public void run() {
int timeInSecond = 185
int minutes = timeInSecond/60;
while (isAlive) {
try {
//TODO
} catch (InterruptedException e) {
log.logStackTrace(e);
}
}
}
}//fine autoclass
And with this code, I can start the JLabel
TimeRefreshRace arLabel = new TimeRefreshRace ();
arLabel.start();
So I have the time in secondo for example 180 second, how can I create the timer?
Here is an example, how to build a countdown label. You can use this pattern to create your component.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class TimerTest {
public static void main(String[] args) {
final JFrame frm = new JFrame("Countdown");
final JLabel countdownLabel = new JLabel("03:00");
final Timer t = new Timer(1000, new ActionListener() {
int time = 180;
#Override
public void actionPerformed(ActionEvent e) {
time--;
countdownLabel.setText(format(time / 60) + ":" + format(time % 60));
if (time == 0) {
final Timer timer = (Timer) e.getSource();
timer.stop();
}
}
});
frm.add(countdownLabel);
t.start();
frm.pack();
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setVisible(true);
}
private static String format(int i) {
String result = String.valueOf(i);
if (result.length() == 1) {
result = "0" + result;
}
return result;
}
}
You could within your try block call the Event Dispatcher Thread (EDT) and update your UI:
try {
SwingUtils.invokeLater(new Runnable() {
#Override
public void run() {
this.setText(minutes + " left");
}
}
//You could optionally block your thread to update your label every second.
}
Optionally, you could use a Timer instead of an actual thread, so your TimerRefreshRace will have its own timer which periodically fires an event. You would then use the same code within your try-catch block to update the UI.

create new thread inside actionPerformed and Event Dispatch Thread (EDT) issue

As stated from Sun that actionPerformed() from ActionListener is executed in EDT automatically so I've decided to create new thread inside actionPerformed() method and the problem is this thread is not running inside EDT. Can someone explain this? Thanks
If you create a new thread from EDT that thread is different than the EDT. Isn't that clear?
You are supposed to update controls via the EDT.
You can create your own background threads for heavy tasks but the update of the controls should be only via the EDT.
There are constructs for you to use to facilitate your code e.g. pass a Runnable to be called by EDT via SwingUtilities invoke Runnable. You should study about Concurrency in Swing
1) AWT or Swing GUI invoked and created EDT, this event is done by (maybe there are another) methods pack() and setVisible(true)
2) if all events waiting in EDT are done and EDT is empty then if (EventQueue.isDispatchThread()) { returns false, but EDT thread is there until current JVM instance exist
3) as mentioned for invoke EDT queue you can use invokeLater or invokeAndWait, notice invokeAndWait you can use only if isDispatchThread returns false, otherwise returns exceptions
4) by calling Thread.sleep(int) from Swing Listener or its method can freeze and lock EDT, causing lost some event from event queue,
two codes example for testing isDispatchThread() and how to alive EDT from Java Objects
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class IsThereEDT {
private ScheduledExecutorService scheduler;
private AccurateScheduledRunnable periodic;
private ScheduledFuture<?> periodicMonitor;
private int taskPeriod = 30;
private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
private Date dateRun;
private JFrame frame1 = new JFrame("Frame 1");
public IsThereEDT() {
scheduler = Executors.newSingleThreadScheduledExecutor();
periodic = new AccurateScheduledRunnable() {
private final int ALLOWED_TARDINESS = 200;
private int countRun = 0;
private int countCalled = 0;
private int maxCalled = 10;
#Override
public void run() {
countCalled++;
if (countCalled < maxCalled) {
if (countCalled % 3 == 0) {
/*if (EventQueue.isDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//some stuff
}
});
} else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
//some stuff
}
});
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
}*/
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println("Push a new event to EDT");
frame1.repaint();
isThereReallyEDT();
}
});
} else {
if (this.getExecutionTime() < ALLOWED_TARDINESS) {
countRun++;
isThereReallyEDT(); // non on EDT
}
}
} else {
System.out.println("Terminating this madness");
System.exit(0);
}
}
};
periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
periodic.setThreadMonitor(periodicMonitor);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
isThereReallyEDT();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.getContentPane().add(new JLabel("Hello in frame 1"));
frame1.pack();
frame1.setLocation(100, 100);
frame1.setVisible(true);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame2 = new JFrame("Frame 2");
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.getContentPane().add(new JLabel("Hello in frame 2"));
frame2.pack();
frame2.setLocation(200, 200);
frame2.setVisible(true);
isThereReallyEDT();
}
});
}
private void isThereReallyEDT() {
dateRun = new java.util.Date();
System.out.println(" Time at : " + sdf.format(dateRun));
if (EventQueue.isDispatchThread()) {
System.out.println("EventQueue.isDispatchThread");
} else {
System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
}
if (SwingUtilities.isEventDispatchThread()) {
System.out.println("SwingUtilities.isEventDispatchThread");
} else {
System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
}
System.out.println();
}
public static void main(String[] args) {
IsThereEDT isdt = new IsThereEDT();
}
}
abstract class AccurateScheduledRunnable implements Runnable {
private ScheduledFuture<?> thisThreadsMonitor;
public void setThreadMonitor(ScheduledFuture<?> monitor) {
this.thisThreadsMonitor = monitor;
}
protected long getExecutionTime() {
long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
return delay;
}
}
and simpler code
.
.
import java.awt.EventQueue;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class IsThereEDT {
private ScheduledExecutorService scheduler;
private AccurateScheduledRunnable periodic;
private ScheduledFuture<?> periodicMonitor;
private int taskPeriod = 30;
private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
private Date dateRun;
private JFrame frame1 = new JFrame("Frame 1");
public IsThereEDT() {
scheduler = Executors.newSingleThreadScheduledExecutor();
periodic = new AccurateScheduledRunnable() {
private final int ALLOWED_TARDINESS = 200;
private int countRun = 0;
private int countCalled = 0;
private int maxCalled = 10;
#Override
public void run() {
countCalled++;
if (countCalled < maxCalled) {
if (countCalled % 3 == 0) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println("Push a new event to EDT");
frame1.repaint();
isThereReallyEDT();
}
});
} else {
if (this.getExecutionTime() < ALLOWED_TARDINESS) {
countRun++;
isThereReallyEDT(); // non on EDT
}
}
} else {
System.out.println("Terminating this madness");
System.exit(0);
}
}
};
periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
periodic.setThreadMonitor(periodicMonitor);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
isThereReallyEDT();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.getContentPane().add(new JLabel("Hello in frame 1"));
frame1.pack();
frame1.setLocation(100, 100);
frame1.setVisible(true);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame2 = new JFrame("Frame 2");
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.getContentPane().add(new JLabel("Hello in frame 2"));
frame2.pack();
frame2.setLocation(200, 200);
frame2.setVisible(true);
isThereReallyEDT();
}
});
}
private void isThereReallyEDT() {
dateRun = new java.util.Date();
System.out.println(" Time at : " + sdf.format(dateRun));
if (EventQueue.isDispatchThread()) {
System.out.println("EventQueue.isDispatchThread");
} else {
System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
}
if (SwingUtilities.isEventDispatchThread()) {
System.out.println("SwingUtilities.isEventDispatchThread");
} else {
System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
}
System.out.println();
}
public static void main(String[] args) {
IsThereEDT isdt = new IsThereEDT();
}
}
abstract class AccurateScheduledRunnable implements Runnable {
private ScheduledFuture<?> thisThreadsMonitor;
public void setThreadMonitor(ScheduledFuture<?> monitor) {
this.thisThreadsMonitor = monitor;
}
protected long getExecutionTime() {
long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
return delay;
}
}

how can i solve this error

This is the complete code :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Thread;
class jProgressBar {
JProgressBar pb;
JButton start;
int i;
jProgressBar() {
buildGUI();
hookUpEvents();
}
public void buildGUI() {
JFrame fr=new JFrame("Progress Bar");
JPanel p=new JPanel();
p.setLayout(new FlowLayout(FlowLayout.CENTER));
JPanel barPanel=new JPanel();
barPanel.setLayout(new GridLayout(2,0,50,50));
pb=new JProgressBar(0,10);
start=new JButton("Start Demo");
fr.add(p);
barPanel.add(start);
barPanel.add(pb);
p.add(barPanel);
fr.setSize(500,500);
fr.setVisible(true);
}
public void hookUpEvents() {
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
try {
Runnable r=new Runnable() {
public void run() {
action(ae); // LINE 39
}
};
Thread th=new Thread(r);
th.start();
} catch(Exception exc) {
System.out.println(exc);
}
}
});
}
public void action(ActionEvent ae) {
start.setVisible(false);
try {
Runnable rp=new Runnable() {
public void run() {
i++;
pb.setValue(i);
try {
Thread.sleep(2000);
} catch(Exception exc) {
System.out.println(exc);
}
if(i==5) {
pb.setString("Half Done!");
}
else if(i==10) {
pb.setString("Completed!");
}
}
};
Thread th=new Thread(rp);
th.start();
} catch(Exception exc) {
System.out.println(exc);
}
}
public static void main(String args[]) {
new jProgressBar();
}
}
This is the error produced on cmd:
d:\UnderTest>javac jProgressBar.java
jProgressBar.java:39: local variable ae is accessed from within inner class; needs to be declared fina
l
action(ae);
^
1 error
What is this error and how can I solve this error?
Declare the variable ae as final:
public void actionPerformed(final ActionEvent ae) {
This means that it cannot be assigned a new value, which should be fine according to your current code.
a very nice example for SwingWorker
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class SwingWorkerExample extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private final JButton startButton, stopButton;
private JScrollPane scrollPane = new JScrollPane();
private JList listBox = null;
private DefaultListModel listModel = new DefaultListModel();
private final JProgressBar progressBar;
private mySwingWorker swingWorker;
public SwingWorkerExample() {
super("SwingWorkerExample");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridLayout(2, 2));
startButton = makeButton("Start");
stopButton = makeButton("Stop");
stopButton.setEnabled(false);
progressBar = makeProgressBar(0, 99);
listBox = new JList(listModel);
scrollPane.setViewportView(listBox);
getContentPane().add(scrollPane);
//Display the window.
pack();
setVisible(true);
}
//Class SwingWorker<T,V> T - the result type returned by this SwingWorker's doInBackground
//and get methods V - the type used for carrying out intermediate results by this SwingWorker's
//publish and process methods
private class mySwingWorker extends javax.swing.SwingWorker<ArrayList<Integer>, Integer> {
//The first template argument, in this case, ArrayList<Integer>, is what s returned by doInBackground(),
//and by get(). The second template argument, in this case, Integer, is what is published with the
//publish method. It is also the data type which is stored by the java.util.List that is the parameter
//for the process method, which recieves the information published by the publish method.
#Override
protected ArrayList<Integer> doInBackground() {
//Returns items of the type given as the first template argument to the SwingWorker class.
if (javax.swing.SwingUtilities.isEventDispatchThread()) {
System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() returned true.");
}
Integer tmpValue = new Integer(1);
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) { //find every 100th prime, just to make it slower
tmpValue = FindNextPrime(tmpValue.intValue());
//isCancelled() returns true if the cancel() method is invoked on this class. That is the proper way
//to stop this thread. See the actionPerformed method.
if (isCancelled()) {
System.out.println("SwingWorker - isCancelled");
return list;
}
}
//Successive calls to publish are coalesced into a java.util.List, which is what is received by process,
//which in this case, isused to update the JProgressBar. Thus, the values passed to publish range from
//1 to 100.
publish(new Integer(i));
list.add(tmpValue);
}
return list;
}//Note, always use java.util.List here, or it will use the wrong list.
#Override
protected void process(java.util.List<Integer> progressList) {
//This method is processing a java.util.List of items given as successive arguments to the publish method.
//Note that these calls are coalesced into a java.util.List. This list holds items of the type given as the
//second template parameter type to SwingWorker. Note that the get method below has nothing to do with the
//SwingWorker get method; it is the List's get method. This would be a good place to update a progress bar.
if (!javax.swing.SwingUtilities.isEventDispatchThread()) {
System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() + returned false.");
}
Integer percentComplete = progressList.get(progressList.size() - 1);
progressBar.setValue(percentComplete.intValue());
}
#Override
protected void done() {
System.out.println("doInBackground is complete");
if (!javax.swing.SwingUtilities.isEventDispatchThread()) {
System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() + returned false.");
}
try {
//Here, the SwingWorker's get method returns an item of the same type as specified as the first type parameter
//given to the SwingWorker class.
ArrayList<Integer> results = get();
for (Integer i : results) {
listModel.addElement(i.toString());
}
} catch (Exception e) {
System.out.println("Caught an exception: " + e);
}
startButton();
}
boolean IsPrime(int num) { //Checks whether a number is prime
int i;
for (i = 2; i <= num / 2; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
protected Integer FindNextPrime(int num) { //Returns next prime number from passed arg.
do {
if (num % 2 == 0) {
num++;
} else {
num += 2;
}
} while (!IsPrime(num));
return new Integer(num);
}
}
private JButton makeButton(String caption) {
JButton b = new JButton(caption);
b.setActionCommand(caption);
b.addActionListener(this);
getContentPane().add(b);
return b;
}
private JProgressBar makeProgressBar(int min, int max) {
JProgressBar progressBar1 = new JProgressBar();
progressBar1.setMinimum(min);
progressBar1.setMaximum(max);
progressBar1.setStringPainted(true);
progressBar1.setBorderPainted(true);
getContentPane().add(progressBar1);
return progressBar1;
}
private void startButton() {
startButton.setEnabled(true);
stopButton.setEnabled(false);
System.out.println("SwingWorker - Done");
}
#Override
public void actionPerformed(ActionEvent e) {
if ("Start" == null ? e.getActionCommand() == null : "Start".equals(e.getActionCommand())) {
startButton.setEnabled(false);
stopButton.setEnabled(true);
// Note that it creates a new instance of the SwingWorker-derived class. Never reuse an old one.
(swingWorker = new mySwingWorker()).execute(); // new instance
} else if ("Stop" == null ? e.getActionCommand() == null : "Stop".equals(e.getActionCommand())) {
startButton.setEnabled(true);
stopButton.setEnabled(false);
swingWorker.cancel(true); // causes isCancelled to return true in doInBackground
swingWorker = null;
}
}
public static void main(String[] args) {
// Notice that it kicks it off on the event-dispatching thread, not the main thread.
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SwingWorkerExample swingWorkerExample = new SwingWorkerExample();
}
});
}
}
There are some counterproductive issues present.
Swing is single-thread based, and all actions must be done on the EDT. For that reason, your JProgressBar doesn't update correctly. See also Concurrency in Swing.
Don't use Thread.sleep(int) in Swing, and certainly not in an action listener.
By using Runnable, it is possible to update JProgressBar; but as mentioned, the method must be run from invokeLater().
For that, SwingWorker would be better, as shown below and here.
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class TestProgressBar {
private static void createAndShowUI() {
JFrame frame = new JFrame("TestProgressBar");
frame.getContentPane().add(new TestPBGui().getMainPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowUI();
}
});
}
private TestProgressBar() {
}
}
class TestPBGui {
private JPanel mainPanel = new JPanel();
public TestPBGui() {
JButton yourAttempt = new JButton("Your attempt to show Progress Bar");
JButton myAttempt = new JButton("My attempt to show Progress Bar");
yourAttempt.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
yourAttemptActionPerformed();
}
});
myAttempt.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myAttemptActionPerformed();
}
});
mainPanel.add(yourAttempt);
mainPanel.add(myAttempt);
}
private void yourAttemptActionPerformed() {
Window thisWin = SwingUtilities.getWindowAncestor(mainPanel);
JDialog progressDialog = new JDialog(thisWin, "Uploading...");
JPanel contentPane = new JPanel();
contentPane.setPreferredSize(new Dimension(300, 100));
JProgressBar bar = new JProgressBar(0, 100);
bar.setIndeterminate(true);
contentPane.add(bar);
progressDialog.setContentPane(contentPane);
progressDialog.pack();
progressDialog.setLocationRelativeTo(null);
Task task = new Task("Your attempt");
task.execute();
progressDialog.setVisible(true);
while (!task.isDone()) {
}
progressDialog.dispose();
}
private void myAttemptActionPerformed() {
Window thisWin = SwingUtilities.getWindowAncestor(mainPanel);
final JDialog progressDialog = new JDialog(thisWin, "Uploading...");
JPanel contentPane = new JPanel();
contentPane.setPreferredSize(new Dimension(300, 100));
final JProgressBar bar = new JProgressBar(0, 100);
bar.setIndeterminate(true);
contentPane.add(bar);
progressDialog.setContentPane(contentPane);
progressDialog.pack();
progressDialog.setLocationRelativeTo(null);
final Task task = new Task("My attempt");
task.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equalsIgnoreCase("progress")) {
int progress = task.getProgress();
if (progress == 0) {
bar.setIndeterminate(true);
} else {
bar.setIndeterminate(false);
bar.setValue(progress);
progressDialog.dispose();
}
}
}
});
task.execute();
progressDialog.setVisible(true);
}
public JPanel getMainPanel() {
return mainPanel;
}
}
class Task extends SwingWorker<Void, Void> {
private static final long SLEEP_TIME = 4000;
private String text;
public Task(String text) {
this.text = text;
}
#Override
public Void doInBackground() {
setProgress(0);
try {
Thread.sleep(SLEEP_TIME);// imitate a long-running task
} catch (InterruptedException e) {
}
setProgress(100);
return null;
}
#Override
public void done() {
System.out.println(text + " is done");
Toolkit.getDefaultToolkit().beep();
}
}

Categories