Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 9 of 9

Thread: SwingWorker implemented - how to do additional GUI processing?

  1. #1
    Junior Member
    Join Date
    Jun 2014
    Posts
    25
    Thanks
    0
    Thanked 2 Times in 2 Posts

    Default SwingWorker implemented - how to do additional GUI processing?

    In a previous question I asked how I could implement processor-intensive work, which was called by a Swing component, without the GUI locking up. I was then pointed to the SwingWorker class. I implemented this and it works! But...

    I am writing a program that solves sudoku puzzles. It has a Swing GUI with a "solve" button. I have written an actionListener class with an actionPerformed method that is invoked when the user presses this button. It is the following:

            public void actionPerformed(ActionEvent event) {
                try {
                    worker = new SudokuSolveWorker();
                    worker.addPropertyChangeListener(this);
                    worker.execute();
                    SolveFrame sf = new SolveFrame();
                } catch (Exception exc) {
                    System.out.println(exc.getMessage());
                    exc.printStackTrace();
                }
            }

    The code creates a worker, a new instance of SudokuSolveWorker. The worker.execute() statement causes the doInBackground() method of this class to be called. This solves the Sudoku. A property change listener "picks up" the result:

            public void propertyChange(PropertyChangeEvent event) {
                try {
                    SudokuModel solvedModel = (SudokuModel) worker.get();
                    if (solvedModel.solved) {
                        model = solvedModel;
                        repaint();
                    } else {
                        JOptionPane.showMessageDialog(null, "Sudoku cannot be solved");
                    }
                } catch (Exception exc) {
                    System.out.println(exc.getMessage());
                    exc.printStackTrace();
                }
            }

    As I wrote, this works without freezing up the user interface in the sense that the program seems unstable. However, the user interface does not respond to "commands" (mouse clicks) anymore until the worker thread has finished.

    In the first code fragment I create an instance of SolveFrame. This is a simple frame with a "cancel" button. It is drawn on the screen, even though it is called after the worker.execute() statement. I'd like the user to be able to click this "cancel" button, after which the solving of the sudoku puzzle should be stopped. However, since the program does not respond to mouse clicks anymore, the "cancel" button cannot be pressed.

    How can I solve this?
    Last edited by evert67; October 8th, 2014 at 11:46 AM.


  2. #2
    Senior Member
    Join Date
    Jul 2013
    Location
    Europe
    Posts
    666
    Thanks
    0
    Thanked 121 Times in 105 Posts

    Default Re: SwingWorker implemented - how to do additional GUI processing?

    You have to do what your propertyChange listener does within the EDT since you call repaint(). I dont know if this is the only issue but try it and come back if you still need help.

  3. #3
    Junior Member
    Join Date
    Jun 2014
    Posts
    25
    Thanks
    0
    Thanked 2 Times in 2 Posts

    Default Re: SwingWorker implemented - how to do additional GUI processing?

    Thanks. But I don't understand this.

    1) I'd like the user to be able to press a Cancel button before the worker threat has finished. The property change listener is only called after the worker thread has finished. (There is a repaint() statement there to display the solved sudoku puzzle on the screen. This works fine.) So how can what the propertyChange listener does be relevant?

    2) As far as I am aware, the propertyChange listener runs within the EDT. At least it is a method of a subclass of the overall GUI class. And this overall GUI class runs on the EDT.

    But I'm teaching myself Java, so there must be something wrong with my reasoning :-) .

  4. #4
    Senior Member
    Join Date
    Jul 2013
    Location
    Europe
    Posts
    666
    Thanks
    0
    Thanked 121 Times in 105 Posts

    Default Re: SwingWorker implemented - how to do additional GUI processing?

    Classes dont run on threads. Classes have absolutely nothing to do with threads.
    Objects dont run on threads either. Bot these things are completely disconnected.

    Each thread can run the methods of every object of every class in your entire program. Nothing is reserved just for one thread unless you program it exactly this way.
    Since the property change event is fired on your worker thread your propertyChanged method is also fired on your worker thread.


    I am not going to explain you every detail about threads. Perhaps this is the right time for you to pick up a book or an online tutorial and read some more information about threads and how they work. The programming language is mostly irrelevant since threading is an issue on almost every programming language out there.

  5. #5
    Junior Member
    Join Date
    Jun 2014
    Posts
    25
    Thanks
    0
    Thanked 2 Times in 2 Posts

    Default Re: SwingWorker implemented - how to do additional GUI processing?

    OK, I understand that classes or objects don't run on threads. I didn't express myself carefully enough. I'm teaching myself Java with two books: Teach yourself Java in 21 days (Cadenhead) and Thinking in Java (Eckel). The second one more for reference.

    I added a statement to the propertyChange listener and removed some code that is not absolutely necessary:

            public void propertyChange(PropertyChangeEvent event) {
                try {
                    System.out.println("" + javax.swing.SwingUtilities.isEventDispatchThread());
                    SudokuModel solvedModel = (SudokuModel) worker.get();
     
                } catch (Exception exc) {
                    System.out.println(exc.getMessage());
                    exc.printStackTrace();
                }
            }

    The code still works. Line 3 now results in a "true" output. According to the Oracle docs (The Event Dispatch Thread (The Java™ Tutorials > Creating a GUI With JFC/Swing > Concurrency in Swing)), this means the propertyChange listener runs on the EDT.

    But apart from that, I still don't understand how this property change listener running or not running on the EDT is relevant to my question.

  6. #6
    Senior Member
    Join Date
    Jul 2013
    Location
    Europe
    Posts
    666
    Thanks
    0
    Thanked 121 Times in 105 Posts

    Default Re: SwingWorker implemented - how to do additional GUI processing?

    I am not 100% sure how you fire the event so perhaps what I said earlier, that your event is fired on the SwingWorker was not true. It is still a good practice though to put the code into an InvokeLater method call of the EDT.

    To know exactly why your GUI doesnt work anymore we would need to see more of your GUI class and your SolveFrame class.
    Is SolveFrame a JFrame or is it a JDialog? Might it be that, if it is a dialog, the dialog is modal?

  7. #7
    Junior Member
    Join Date
    Jun 2014
    Posts
    25
    Thanks
    0
    Thanked 2 Times in 2 Posts

    Default Re: SwingWorker implemented - how to do additional GUI processing?

    I fire off the GUI as follows:

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    ViewController_Graphics view = new ViewController_Graphics(model);

    Every code I showed above is a method of (a subclass of) ViewController_Graphics.

    SolveFrame is a JFrame. Here is the code:

        public class SolveFrame extends JFrame {
            SolveFrame() {
                super("Solving");
                setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                JPanel mainPanel = new JPanel();
                JPanel topPanel = new JPanel();
                JPanel bottomPanel = new JPanel();
                topPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
                bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
                mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
                mainPanel.add(topPanel);
                mainPanel.add(bottomPanel);
                topPanel.add(new JLabel("Solving sudoku..."));
                JButton cancelButton = new JButton("Cancel");
                bottomPanel.add(cancelButton);
                add(mainPanel);
                setSize(new Dimension(170,120));
                setVisible(true);
            }
        }

    But I don't think the problem is this SolveFrame. Also if I don't create this frame, the user interface does not respond to user input.

    --- Update ---

    I think I may have found a clue to an answer. I thought that the propertyChange listener was only invoked when the worker thread ended. However, I just found out that it gets called right after the worker thread is started. And then one of the first lines executed is the worker.get statement. And this is blocking until the worker thread has finished.

    That would explain why the GUI becomes unresponsive.

    However, what I don't understand then is why the propertyChange listener is invoked before the worker thread ends. According to the docs I have read it should only be invoked then. But apparently my docs are not correct. Who can tell me under what conditions the propertyChange listener is invoked? And how do I make something (a listener or so...) that gets invoked only when the thread has ended?
    Last edited by evert67; October 8th, 2014 at 01:42 PM.

  8. #8
    Senior Member
    Join Date
    Jul 2013
    Location
    Europe
    Posts
    666
    Thanks
    0
    Thanked 121 Times in 105 Posts

    Default Re: SwingWorker implemented - how to do additional GUI processing?

    There are probably many different kinds of properties and you should check within your PropertyChangeListener which particular property was changed.
    Perhaps the documentation can tell what kinds of properties exist.

    Here, I found the following line in one of the Oracle tutorials:
    The background task can define bound properties. Changes to these properties trigger events, causing event-handling methods to be invoked on the event dispatch thread.
    Source: http://docs.oracle.com/javase/tutori...cy/worker.html


    This means YOU have to define your own properties if you want to use the property change listener.
    By the way, perhaps you should instead use the "done()" method from the SwingWorker class.

  9. #9
    Junior Member
    Join Date
    Jun 2014
    Posts
    25
    Thanks
    0
    Thanked 2 Times in 2 Posts

    Default Re: SwingWorker implemented - how to do additional GUI processing?

    Ah, that's it! The done method works. I also just found it in the Oracle docs :-).

    Thanks!

    Just don't always believe Teach yourself Java in 21 days (a pretty decent book otherwise).

Similar Threads

  1. Adding additional $10?
    By gotdatdough in forum What's Wrong With My Code?
    Replies: 4
    Last Post: November 3rd, 2013, 05:45 PM
  2. [SOLVED] How to complete the process( ) for this swingworker ??
    By harshilshah in forum AWT / Java Swing
    Replies: 0
    Last Post: May 1st, 2013, 01:26 AM
  3. [SOLVED] SwingWorker updating JTABLE ...
    By harshilshah in forum AWT / Java Swing
    Replies: 2
    Last Post: April 30th, 2013, 11:41 PM
  4. (Beginner's calculator) Additional calculation after first result...
    By skw4712 in forum What's Wrong With My Code?
    Replies: 5
    Last Post: January 30th, 2013, 04:56 PM
  5. [SOLVED] New to SwingWorker how to use process?
    By Niteawk in forum Threads
    Replies: 3
    Last Post: December 5th, 2012, 10:17 AM