Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
177 views
in Technique[技术] by (71.8m points)

java - SwingWorker in another SwingWorker's done method

First, I need to inform you that I am trying my hardest to learn how to code in Java. Its been a little bit difficult, but, I do believe I have it. I have submitted a couple question in the past in regards to SwingWorkers and the like. Each of which I thought I had it, but come to find out that I still had learning to do. Hopefully this time, is not one of those times.

With that said, please let me know of anything you see that isn't to standard, or, could lead to problems in the future.


Now for the question!

I have constructed a JFrame, of which, loads a couple things before it allows the user to proceed to another page, press buttons, or anything else. Once it loads the data it will then unlock the JFrame to allow the user to interact with the data.

The problem is, (which isn't really a problem, just a clarification) I need to execute another task while the user can interact with the JFrame in such a way it doesn't bother them, but, will update the JFrame based on the results it found. An example might be a version check. Depending if the version is out of date or not, notify user.


Example Sudo Code

protected void startJFrame() {
    JFrame myFrame = new JFrame();//Starts with disable/invisible components. Preventing the user from doing to much before allowed.
    SwingWorker<Void, Progress> loadingWorker = new SwingWorker<Void, Progress>() {
        @Override
        protected Void doInBackground() throws Exception {
            publish(new Progress(0,"Loading This"));      // Set Percent
            loadingTasks.loadThis();                         // Do Work!!
            publish(new Progress(25,"Loading That"));     // Set Percent
            loadingTasks.loadThat();                         // Do Work!!
            publish(new Progress(50,"Loading More"));     // Set Percent
            loadingTasks.loadMore();                         // Do Work!!
            publish(new Progress(75,"Loading Last"));     // Set Percent
            loadingTasks.loadLast();                         // Do Work!!
            publish(new Progress(100,"Loading Complete"));// Set Percent
            return null;
        }
        @Override
        protected void process(List<Progress> ProgressList) {
            for (Progress p : ProgressList) {
                System.out.println(p.getInt() + "% " + p.getString()); //Show user percent and what its doing.
            }
        }
        @Override
        protected void done() {
            try {
                get();
                loadingTasks.WrapUp();//Set Variables or other small stuff.
                myFrame.userAllowed();//Lets the user interact with the whole JFrame.
                SwingWorker<Void, Void> secondWorker = new SwingWorker<Void, Void>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        versionCheck.makeItSo();// Do Work!!
                        return null;
                    }
                    @Override
                    protected void done() {
                        try {
                            get();
                            versionCheck.wrapUp();//Set Variables or other small stuff.
                            myFrame.showLabel();//Show a label with specific info.
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }
                    }
                };
                secondWorker.execute();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
    };
    loadingWorker.execute();
}

Off topic question involving this code.

I am concerned about creating to many objects and not disposing of them, just to pass multiple variables. Specifically the Progress objects being created in the first doInBackground method.

Is it considered OK to do this? Will it auto dispose the Progress Objects automatically? If not, how would i go about disposing them after I'm done with them?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

SwingWorker supports PropertyChange events, that is, you can listener to when the SwingWorker changes state or updates it's progress...yes, SwingWorker even supports progress notification, for example

This means you could set up a PropertyChangeListener to monitor changes to the progress and state properties and take appropriate actions...

A worker that simple sets progress updates...

public class LoadMaster extends SwingWorker<Void, Progress> {

    @Override
    protected Void doInBackground() throws Exception {
        System.out.println("Working hard here, nothing to see...");
        for (int index = 0; index < 100; index++) {
            Thread.sleep(10);
            setProgress(index);
        }
        return null;
    }

    @Override
    protected void done() {
        try {
            get();
        } catch (Exception e) {
        }
    }

}

A example PropertyChangeListener...

public class LoadMasterPropertyChanegHandler implements PropertyChangeListener {

    private SwingWorkerExample example;

    public LoadMasterPropertyChanegHandler(SwingWorkerExample example) {
        this.example = example;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println(evt.getPropertyName());
        if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
            int value = (int) evt.getNewValue();
            example.showProgress(value);
        } else if ("state".equalsIgnoreCase(evt.getPropertyName())) {
            SwingWorker worker = (SwingWorker) evt.getSource();
            if (worker.isDone()) {
                try {
                    worker.get();
                    example.loadCompleted();
                } catch (InterruptedException | ExecutionException exp) {
                    example.loadFailed();
                }
            }
        }
    }

}

Now, all this does is sends back information to the SwingWorkerExample (it's coming) which allows it to determine what it should do...

In this example, the loadCompleted method updates the UI and then starts the second worker...

protected void loadCompleted() {
    //...
    LoadStuffWorker stuffWorker = new LoadStuffWorker(this);
    stuffWorker.execute();
}

In all truth, I might use interfaces instead, so I'm not overtly exposing the class, but that's a topic for another day...

And the full example...

Worker

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
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 SwingWorkerExample {

    private JProgressBar pb;
    private JPanel content;

    public static void main(String[] args) {

        new SwingWorkerExample();

    }

    public SwingWorkerExample() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                pb = new JProgressBar();
                content = new JPanel();
                content.setBorder(new EmptyBorder(10, 10, 10, 10));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setContentPane(content);
                frame.setLayout(new GridBagLayout());
                frame.add(pb);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                LoadMaster master = new LoadMaster();
                master.addPropertyChangeListener(new LoadMasterPropertyChanegHandler(SwingWorkerExample.this));
                master.execute();
            }
        });
    }

    protected void showProgress(int value) {
        pb.setValue(value);
    }

    protected void loadCompleted() {
        content.removeAll();
        content.setLayout(new GridLayout(0, 1));
        content.add(new JLabel("All your base are belong to us"));
        content.revalidate();

        LoadStuffWorker stuffWorker = new LoadStuffWorker(this);
        stuffWorker.execute();
    }

    protected void loadFailed() {
        content.removeAll();
        content.setLayout(new GridLayout(0, 1));
        content.add(new JLabel("Fail"));
        content.revalidate();
    }

    protected void setVersion(String value) {
        content.add(new JLabel("Version: " + value));
        content.revalidate();
    }

    protected void failed(String fail) {
        content.add(new JLabel(fail));
        content.revalidate();
    }

    public class LoadMaster extends SwingWorker<Void, Progress> {

        @Override
        protected Void doInBackground() throws Exception {
            System.out.println("Working hard here, nothing to see...");
            for (int index = 0; index < 100; index++) {
                Thread.sleep(10);
                setProgress(index);
            }
            return null;
        }

        @Override
        protected void done() {
            try {
                get();
            } catch (Exception e) {
            }
        }

    }

    public class LoadStuffWorker extends SwingWorker<String, Void> {

        private SwingWorkerExample example;

        public LoadStuffWorker(SwingWorkerExample example) {
            this.example = example;
        }

        @Override
        protected String doInBackground() throws Exception {
            System.out.println("Hanging about in the background");
            Thread.sleep(3000);
            return "Hello from the dark side";
        }

        @Override
        protected void done() {
            try {
                String value = get();
                example.setVersion(value);
            } catch (InterruptedException | ExecutionException ex) {
                example.failed("Fail while doing version check");
            }
        }

    }

    public class Progress {
    }

    public class LoadMasterPropertyChanegHandler implements PropertyChangeListener {

        private SwingWorkerExample example;

        public LoadMasterPropertyChanegHandler(SwingWorkerExample example) {
            this.example = example;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println(evt.getPropertyName());
            if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
                int value = (int) evt.getNewValue();
                example.showProgress(value);
            } else if ("state".equalsIgnoreCase(evt.getPropertyName())) {
                SwingWorker worker = (SwingWorker) evt.getSource();
                if (worker.isDone()) {
                    try {
                        worker.get();
                        example.loadCompleted();
                    } catch (InterruptedException | ExecutionException exp) {
                        example.loadFailed();
                    }
                }
            }
        }

    }

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...