I'm simulating multiple Tasks inside a thread - when all of them should report to a GUI. So I have a unique form that has 4 Panels inside which should reply and do different Tasks.. they should each keep pooling a database and reporting stuff to the GUI. In this example, I just made it to write numbers to a textArea.
public class FormMain extends JFrame {
private JButton btnStart;
private JPanel _panelTop, _panelMid, _panelBot;
private PanelFoo panelFooA, panelFooB, panelFooC, panelFooD;
private final List<String> ugsRj = Arrays.asList("AB");
private final List<String> ugsMg = Arrays.asList("CD", "EF");
private final List<String> ugsBA = Arrays.asList("GH", "IJ", "KL");
private final List<String> ugsPE = Arrays.asList("MN", "OP", "RS", "TU");
private void initialize() {
this._panelTop = new JPanel();
this._panelMid = new JPanel();
this._panelBot = new JPanel();
this.btnStart = new JButton("Start");
this._panelBot.add(this.btnStart);
this.panelFooA = new PanelFoo(this.ugsRj);
this.panelFooB = new PanelFoo(this.ugsMg);
this.panelFooC = new PanelFoo(this.ugsBA);
this.panelFooD = new PanelFoo(this.ugsPE);
_panelMid.setLayout(new BoxLayout(_panelMid, BoxLayout.X_AXIS));
this._panelMid.add(this.panelFooA);
this._panelMid.add(this.panelFooB);
this._panelMid.add(this.panelFooC);
this._panelMid.add(this.panelFooD);
}
public FormMain() {
initialize();
getContentPane().setLayout(new BorderLayout());
setSize(800, 516);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(this._panelTop, BorderLayout.NORTH);
getContentPane().add(this._panelMid, BorderLayout.CENTER);
getContentPane().add(this._panelBot, BorderLayout.SOUTH);
this.btnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final AuthenticationUser auth = new AuthenticationUser();
auth.setUser("test");
auth.setPassword("p@ss");
//
final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
final WorkerDoSomething w1 = new WorkerDoSomething(panelFooA);
w1.addPropertyChangeListener(new ProgressListener(panelFooA.getProgressBar()));
final WorkerDoSomething w2 = new WorkerDoSomething(panelFooB);
w2.addPropertyChangeListener(new ProgressListener(panelFooB.getProgressBar()));
final WorkerDoSomething w3 = new WorkerDoSomething(panelFooC);
w3.addPropertyChangeListener(new ProgressListener(panelFooC.getProgressBar()));
final WorkerDoSomething w4 = new WorkerDoSomething(panelFooD);
w4.addPropertyChangeListener(new ProgressListener(panelFooD.getProgressBar()));
w1.execute();
w2.execute();
w3.execute();
w4.execute();
return null;
}
};
worker.execute();
}
});
}
}
public class ProgressListener implements PropertyChangeListener {
private JProgressBar bar;
ProgressListener() {
}
ProgressListener(final JProgressBar b) {
this.bar = b;
this.bar.setValue(0);
}
@Override
public void propertyChange(final PropertyChangeEvent evt) {
// Determine whether the property is progress type
if ("progress".equals(evt.getPropertyName())) {
this.bar.setValue((int) evt.getNewValue());
}
}
}
public class PanelFoo extends JPanel {
/**
*
*/
private static final long serialVersionUID = -1400188281877395934L;
private JLabel label;
private JTextArea textArea;
private JScrollPane scrollPanel;
private JProgressBar progressBar;
public PanelFoo(final List<String> listOfStates) {
setLayout(new FlowLayout());
setSize(180, 400);
final ImageIcon icon = createImageIcon("/images/waiting-list.png", "waiting start");
this.label = new JLabel(listOfStates.get(0), icon, SwingConstants.HORIZONTAL);
add(this.label);
this.textArea = new JTextArea("Numbers: \n");
this.textArea.setWrapStyleWord(true);
this.scrollPanel = new JScrollPane(this.textArea);
this.scrollPanel.setPreferredSize(new Dimension(150, 350));
this.progressBar = new JProgressBar(0, 100);
add(this.scrollPanel);
add(this.progressBar);
setVisible(true);
}
/** Returns an ImageIcon, or null if the path was invalid. */
public ImageIcon createImageIcon(final String path, final String description) {
if (path != null) {
ImageIcon imageIcon = new ImageIcon(getClass().getResource(path));
final Image image = imageIcon.getImage();
final Image newimg = image.getScaledInstance(30, 30, Image.SCALE_SMOOTH);
imageIcon = new ImageIcon(newimg, description);
return imageIcon;
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
public final JLabel getLabel() {
return this.label;
}
public final void setLabel(final JLabel label) {
this.label = label;
}
public final JTextArea getTextArea() {
return this.textArea;
}
public final void setTextArea(final JTextArea textArea) {
this.textArea = textArea;
}
public final JProgressBar getProgressBar() {
return this.progressBar;
}
public final void setProgressBar(final JProgressBar progressBar) {
this.progressBar = progressBar;
}
}
public class WorkerDoSomething extends SwingWorker<Void, Void> {
private JTextArea txtArea;
private JLabel label;
private Random r = new Random();
WorkerDoSomething() {
}
public WorkerDoSomething(final PanelFoo panelFooInstance) {
this.txtArea = panelFooInstance.getTextArea();
this.label = panelFooInstance.getLabel();
}
private Integer randomInt(final int min, final int max) {
final Integer randomNumber = this.r.nextInt((max - min) + 1) + min;
return randomNumber;
}
@Override
protected Void doInBackground() throws Exception {
final Integer randomNumber = randomInt(10000000, 1000000000);
long j;
int progress = 0;
final int onePerCent = randomNumber / 100;
final int onePerMillion = onePerCent / 10;
for (j = 0; j <= randomNumber; j++) {
if (j % onePerCent == 0) {
progress = (int) j / onePerCent;
setProgress(progress);
}
if (j % onePerMillion == 0) {
publish(j);
}
//Thread.sleep(randomInt(1000, 5000));
}
return null;
}
private void publish(final long num) {
this.txtArea.append(num + "\n");
this.txtArea.setCaretPosition(this.txtArea.getDocument().getLength());
}
}
This is the main GUI after all:
and this is the execution:
I just need to wait for a time on each WorkerDoSomething
's task, adding that line (previously comment out): Thread.sleep(randomInt(1000, 5000));
but when I do.. the whole execution freezes, of course..because it uses a single thread to run all the tasks - I suppose.
Is there a solution for this?
Oh...I have to use java 1.8 in the business:
java version "1.8.0_251"
Java(TM) SE Runtime Environment (build 1.8.0_251-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.251-b08, mixed mode)
The whole project it's on my personnal git
--- first edit with debug perspective
The execution is not freezing since Swing uses a thread pool of 10 threads to run the workers.
You can see it work properly if you comment out this part:
if (j % onePerMillion == 0) {
publish(j);
}
PS - Why do you create a new SwingWorker in the actionPerformed method?
Why not simply write like this:
this.btnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final WorkerDoSomething w1 = new WorkerDoSomething(panelFooA);
w1.addPropertyChangeListener(new ProgressListener(panelFooA.getProgressBar()));
final WorkerDoSomething w2 = new WorkerDoSomething(panelFooB);
w2.addPropertyChangeListener(new ProgressListener(panelFooB.getProgressBar()));
final WorkerDoSomething w3 = new WorkerDoSomething(panelFooC);
w3.addPropertyChangeListener(new ProgressListener(panelFooC.getProgressBar()));
final WorkerDoSomething w4 = new WorkerDoSomething(panelFooD);
w4.addPropertyChangeListener(new ProgressListener(panelFooD.getProgressBar()));
w1.execute();
w2.execute();
w3.execute();
w4.execute();
}
});