JLabel не будет обновляться, если что-то не вызывает зависание метода - PullRequest
1 голос
/ 18 января 2012

Во-первых, извинения, но было бы очень трудно восстановить SSCCE для этого, хотя я думаю, что могу достаточно хорошо объяснить ситуацию и объяснить свой вопрос,

Моя ситуация такова: у меня естьJLabel, который служит индикатором состояния (например, отображает «Загрузка ...» или «Готово»), и я вызываю метод setText в MouseAdapter перед вызовом другого метода для выполнения фактического действия.Тем не менее, текст JLabel никогда не меняется, если я не сделаю что-то вроде вызова JOptionPane.showMessageDialog(), в этом случае текст обновляется.

Итак, есть ли у кого-нибудь какие-либо предложения относительно того, как я могу разрешить эту ситуацию, не делая ничего подобногоотображение окна сообщения для (что было бы) без причины вообще?

Заранее спасибо

Ответы [ 2 ]

6 голосов
/ 18 января 2012

Убедитесь, что вы не запускаете свою задачу (свою процедуру «Загрузка ...») в EDT (Thread Dispatch Thread); если вы сделаете это, ваш графический интерфейс не будет обновлен.

Вы должны запустить код приложения (если он не очень быстрый, скажем, менее 100 мс, нет доступа к сети, нет доступа к БД и т. Д.) В отдельном потоке. Класс SwingWorker (см. Javadocs) может пригодиться для этой цели.

EDT (например, блоки кода внутри слушателей пользовательского интерфейса) должен содержать только код для обновления графического интерфейса, работы с компонентами Swing и т. Д. Все остальное, что вы должны запускать на своем собственном объекте Runnable.

-

РЕДАКТИРОВАТЬ: ответ на комментарий Энди. Вот сырой пример (написанный на лету, он может содержать опечатки и тому подобное, и может не работать как есть), как вы можете использовать SwingWorker класс

Поместите это в событие прослушивания мыши или что-то, что заставляет вашу задачу начать

//--- 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
3 голосов
/ 18 января 2012

Вы вызываете метод setText () из EDT?

...