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
Advertisement
Answer
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(); } });