【问题标题】:JLabel will not update unless something causes the method to hangJLabel 不会更新,除非有什么东西导致方法挂起
【发布时间】:2012-01-18 19:36:34
【问题描述】:

首先,很抱歉,但要为此重建一个 SSCCE 真的很难,尽管我认为我可以很好地解释这种情况并解决我的问题,

我的情况是这样的:我有一个用作状态指示器的 JLabel(例如,它将显示“正在加载...”或“就绪”),我在 MouseAdapter 之前调用了 setText 方法调用方法来执行实际操作。但是,JLabel 文本永远不会更改,除非我执行诸如 call JOptionPane.showMessageDialog() 之类的操作,在这种情况下文本会更新。

那么,是否有人对我如何解决这种情况有任何建议,而无需执行诸如无缘无故(什么会)显示消息框之类的操作?

提前致谢

【问题讨论】:

  • 很抱歉,这似乎是个坏建议,但您是否尝试在更改标签文本后在框架上调用 revalidate()repaint()
  • 糟糕。无视我之前的评论。确保您没有在答案中提到的 EDT 上执行任务。
  • 我认为@fireshadow52 的建议是不错的尝试,最好使用 swingworker,但如果您只是进行原型设计,您可以先尝试一下。
  • @fireshadow52 不,这不是一个坏建议。事实上,我确实尝试过调用这些方法,但显然它没有实现任何效果;但你不知道!和 AKJ,老实说,我不是在设计原型 - 我需要一个非常适合工作的解决方案,所以你能以某种形式为我提供答案/示例吗?
  • 放弃最后一个请求作为示例,@Unai Vive 提供了一个并帮助了我!

标签: java swing text jlabel concurrency


【解决方案1】:

确保您没有在 EDT(事件调度线程)上运行您的任务(您的“正在加载...”过程);如果这样做,您的 GUI 将不会更新。

您必须在单独的线程上运行您的应用程序代码(除非它非常快,比如少于 100 毫秒,没有网络访问,没有数据库访问等)。 SwingWorker(参见 javadocs)类可能会派上用场。

EDT(例如用户界面侦听器内的代码块)应该只包含用于更新 GUI、在 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

【讨论】:

  • 不幸的是,我正在 EDT 中运行任务(我很傻)。不过,我之前还没有真正见过SwingWorker;所以你能给我一个例子吗?谢谢。
  • @Andy 我编辑了答案,添加了一个(不是特别漂亮的)示例。希望它有助于理解机制
  • 感谢您的示例,它真的很有帮助,并且知道我可以正常工作;可能更重要的是,我对SwingWorker也有了更好的理解。再次感谢。
【解决方案2】:

您是否从 EDT 调用 setText() 方法?

【讨论】:

  • +1 你是对的,那可能是正确答案stackoverflow.com/questions/7943584/…
  • OP 说设置文本是从鼠标适配器调用的,它可能应该在 EDT 上运行。
  • @AKJ 是的,鼠标适配器正在 EDT 上运行,也回答了 tilex 的问题。我真的不确定该怎么做,有人可以提供一些例子吗?请!
  • 现在的例子无关紧要,@Unai Vivi 给他添加了一个例子,现在我的程序可以正常工作了。还是谢谢你。
  • 你现在有足够的代表了。制作 cmets。您写的是评论,以后请输入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多