0

I'm building a user-interface with Java's swing library, and I've run into a problem.

When updating a text-area in a long method, there is a pause while the method runs, and then the text area is updated all at once, instead of a little bit at a time.

I managed to fix the problem using a new thread in the following manner:

private void jButtonActionPerformed(java.awt.event.ActionEvent evt) {
    Thread x = new Thread() {public void run() {
    // do things that update a text area
    }}; x.start();
}

This works perfectly for having the text area update in small pieces, as opposed to all at once.

However, the only problem is that this method can only be called once or Java crashes. I read that this has to do with only being able to create the thread one time. How can I modify the code to keep the desired functionality?

Any help would be greatly appreciated.

3 Answers 3

4

Well, I doubt you codes crashing because of the Thread creation, because each time the method is called, you're creating a new Thread (you can't restart an existing instance of a Thread that has already been started (even if it's completed or not)), the likely cause is you're getting a concurrent modification exception because Swing is not Thread safe...

Probably the easiest solution would be to use a SwingWorker which will allow you to execute your long running task in the background, but provide easy to use functionality to update the UI safely, through the publish, process and done methods.

Do prevent possible issues, you might also consider disabling the button until the load action is completed, which will prevent people from mashing the button spawning multiple background processes...

Sign up to request clarification or add additional context in comments.

2 Comments

Agreed, Or simply wrap the updates of the UI components into a SwingUtilites.invoke... method
@NielsBechNielsen SwingUtilities.invoke... has issues with providing variables, where process can handle this. Obviously, this is contextual, but when it comes to "introducing" people to Swing and concurrency, I like to show them SwingWorker first ;)
0

Well you can make new object of the Thread and override all the method means runnable.

new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("Executed..*****");
            }
        }).start();

try this.

9 Comments

That's only half the story, failing to properly synchronise updates back to the UI will cause no end of issues
@MadProgrammer Ayee sir :) U are right :) but can we just destroy thread in the case of that Exception?
Remember, Swing is not thread safe which needs to be taken into consideration when dealing with concurrency in Swing, so not mentioning how to create a Thread, but failing to mention the need to use something like SwingUtilities.invokeLater ca
SwingUtilities.invoke so we should use this for make??
Wow, my comment was awesome...SwingUtilities.invokeLater/wait must be used if you want to update the UI from any other thread then then EDT (although SwingUtilities.invokeLater is the source of some interesting hacks which originate from the EDT, but that's another story)
|
-1

Just for comparison's sake, here is an example using SwingUtilities.invokeLater. I echo MadProgrammer's advice though, learning about SwingWorker is much more beneficial in the long term and gives better variable handling.

newGame.addActionListener(new ActionListener() {
    @Override
        public void actionPerformed(final ActionEvent arg0) {
            panelList.get("newGame").setEnabled(false);     
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    // this is where the heavy processing occurs
                    newGameButton();
                    // re-enables the button afterwards
                    panelList.get("newGame").setEnabled(true);
                }
            });             
        }
});

Also, once your code is working better, you can probably look into ways to optimise the speed of the update (even when dealing with Swing objects). The above call used to hang for a second or so, but I've got the delay to about 50 - 100ms or so with further work on the model :)

5 Comments

// this is where the heavy processing occurs ehhh... no: you are on the EDT and don't want to block it, do you :-)
It doesn't block the EDT, as you're not invoking the methods directly within the actionListener.
well, you do it on the EDT after the actionPerformed finished .. not such a big difference, is there ;-)
There's a difference of quite a lot of operation time and user responsiveness :P
actually, there isn't much of a difference - except that the button get's "unpressed" before blocking the ui ;-) Repeating: whatever you do in invokeLater will happen on the EDT, and that's not the thread for doing heavy lifting.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.