Quantcast
Channel: Notify PropertyChangeListener faster - Stack Overflow
Viewing all articles
Browse latest Browse all 2

Answer by Hovercraft Full Of Eels for Notify PropertyChangeListener faster

$
0
0

Your problem is here:

read.execute();
return read.get();

get() is a blocking call, and so calling it from the event thread immediately after executing your worker will block the event thread and your GUI.

Instead, it should be called from a call-back method such as the done() method or from the property change listener after the worker has changed its state property to SwingWorker.StateValue.DONE.


For example

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import javax.swing.*;

@SuppressWarnings("serial")
public class TestSwingWorkerGui extends JPanel {
    private JProgressBar progressBar = new JProgressBar(0, 100);
    private Action myAction = new MyAction("Do It!");

    public TestSwingWorkerGui() {
        progressBar.setStringPainted(true); 
        add(progressBar);
        add(new JButton(myAction));
    }

    private class MyAction extends AbstractAction {
        public MyAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            myAction.setEnabled(false);
            Task read = new Task(30) {
                @Override
                public String doInBackground() throws Exception {
                    int counter = getCounter();
                    int max = getMax();
                    while (counter < max) {
                        counter = getCounter();
                        step();
                        TimeUnit.MILLISECONDS.sleep(200);
                    }
                    return "Worker is Done";
                }
            };
            read.addPropertyChangeListener(new MyPropListener());
            read.execute();
        }
    }

    private class MyPropListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            String name = evt.getPropertyName();
            if ("progress".equals(name)) {
                progressBar.setIndeterminate(false);
                progressBar.setValue((Integer) evt.getNewValue());
            } else if ("state".equals(name)) {
                if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
                    myAction.setEnabled(true);
                    @SuppressWarnings("unchecked")
                    SwingWorker<String, Void> worker = (SwingWorker<String, Void>) evt.getSource();
                    try {
                        String text = worker.get();
                        System.out.println("worker returns: " + text);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private static void createAndShowGui() {
        TestSwingWorkerGui mainPanel = new TestSwingWorkerGui();

        JFrame frame = new JFrame("GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

class Task extends SwingWorker<String, Void> {

    private int counter;
    // private double rate;
    private int max;

    public Task(int max) {
        // Adds the PropertyChangeListener to the ProgressBar
        // addPropertyChangeListener(gui);
        // !!rate = (float)100/max;
        this.max = max;
        setProgress(0);
        counter = 0;
    }

    /** Increments the progress in 1 times the rate based on maximum */
    public void step() {
        counter++;
        int progress = (100 * counter) / max;
        progress = Math.min(100, progress);
        setProgress(progress);
        // setProgress((int)Math.round(counter*rate));
    }

    public int getCounter() {
        return counter;
    }

    public int getMax() {
        return max;
    }

    @Override
    public String doInBackground() throws Exception {
        return null;
    }

    @Override
    public void done() {
      Toolkit.getDefaultToolkit().beep();
      System.out.println("Progress done.");
    }
}

Viewing all articles
Browse latest Browse all 2

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>