Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

java - JLabel will not update unless something causes the method to hang

Firstly, apologies but it would be really hard to reconstruct a SSCCE for this, though I think I can explain the situation considerably well and get my question across,

My situation is as thus: I have a JLabel that serves as a status indicator (e.g. that will display "Loading..." or "Ready") and I call the setText method in a MouseAdapter before another method is called to do the actual action. However, the JLabel text never changes, unless I do something like call JOptionPane.showMessageDialog() in which case the text does update.

So, does anybody have any suggestions as to how I can resolve this situation without doing something like displaying a message box for (what would be) no reason whatsoever?

Thanks in advance

See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

Make sure you don't run your task (your "Loading..." procedure) on the EDT (Event Dispatch Thread); if you do so, your GUI won't get updated.

You have to run your application code (unless it's very fast, say less than 100ms, no network access, no DB access, etc) on a separate thread. The SwingWorker (see javadocs) class might come handy for this purpose.

The EDT (e.g. code blocks inside user interface listeners) should only contain code for updating the GUI, operating on Swing components, etc. Everything else you should run on its own Runnable object.

--

EDIT: reponse to Andy's comment. Here's a raw example (written on the fly, it might have typos and such and might not run as-is) of how you can use the SwingWorker class

Put this in your mouse listener event or whatever makes your task start

//--- code up to this point runs on the EDT
SwingWorker<Boolean, Void> sw = new SwingWorker<Boolean, Void>()
{

    @Override
    protected Boolean doInBackground()//This is called when you .execute() the SwingWorker instance
    {//Runs on its own thread, thus not "freezing" the interface
        //let's assume that doMyLongComputation() returns true if OK, false if not OK.
        //(I used Boolean, but doInBackground can return whatever you need, an int, a
        //string, whatever)
        if(doMyLongComputation())
        {
            doSomeExtraStuff();
            return true;
        }
        else
        {
            doSomeExtraAlternativeStuff();
            return false;
        }
    }

    @Override
    protected void done()//this is called after doInBackground() has finished
    {//Runs on the EDT
        //Update your swing components here
        if(this.get())//here we take the return value from doInBackground()
            yourLabel.setText("Done loading!");
        else
            yourLabel.setText("Nuclear meltdown in 1 minute...");
        //progressBar.setIndeterminate(false);//decomment if you need it
        //progressBar.setVisible(false);//decomment if you need it
        myButton.setEnabled(true);
    }
};
//---code under this point runs on the EDT
yourLabel.setText("Loading...");
//progressBar.setIndeterminate(true);//decomment if you need it
//progressBar.setVisible(true);//decomment if you need it
myButton.setEnabled(false);//Prevent the user from clicking again before task is finished
sw.execute();
//---Anything you write under here runs on the EDT concurrently to you task, which has now been launched

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...