简体   繁体   English

摇摆:jLabel.setText调用为时已晚

[英]Swing: jLabel.setText invoked too late

I have application with: 我有以下应用程序:

  • one JTextField for user input, 一个JTextField供用户输入,
  • one JLabel fro showing busy status, 一个JLabel来回显示忙碌状态,
  • one JTextArea for printing results of search. 一个JTextArea用于打印搜索结果。

I want user to write text to textfield, press enter and see results. 我希望用户将文本写入文本字段,然后按Enter键并查看结果。 I have listener like this: 我有这样的听众:

private void searchForPattern(java.awt.event.ActionEvent evt) {
        textArea.setText("");
        busyLabel.setText("Searchnig ...");
        doSearch();
        busyLabel.setText("Idle");
    }

In doSearch there is quite complicated algorithm that opens lots of XML files and searches for given pattern, it takes a while. doSearch中,有一种相当复杂的算法,该算法会打开许多​​XML文件并搜索给定的模式,这需要一段时间。 Text of busyLabel is changed to Searching ... only after doSearch completed. 仅在doSearch完成后,busyLabel的文本才会更改为Searching...。 There is no second thread in doSearch, only lot of IO operations. doSearch中没有第二个线程,只有许多IO操作。

How can I fix this? 我怎样才能解决这个问题?

You've got a classic Swing concurrency issue (tutorial: Concurrency in Swing ) where doSearch is tying up the Swing event thread. 你已经有了一个经典的Swing的并发性问题:(教程并发在Swing其中doSearch被占用Swing事件线程)。 Since this thread is where Swing does all of its painting/drawing and interacting with users, if it gets tied up by code that takes any perceptible amount of time to complete, the whole application "freezes" with no components getting updated and all user interactions getting ignored. 由于该线程是Swing进行所有绘画/绘图以及与用户交互的地方,因此,如果它被需要花费任何明显时间才能完成的代码所束缚,则整个应用程序将“冻结”,而没有组件得到更新并且所有用户交互被忽略。

Solution: do it on a background thread such as that provided by a SwingWorker object. 解决方案:在诸如SwingWorker对象提供的后台线程上执行此操作。 Set the "Idle" String into the JLabel in the SwingWorker's done() method. 在SwingWorker的done()方法中将“ Idle”字符串设置到JLabel中。

ie,

private void searchForPattern(java.awt.event.ActionEvent evt) {
  textArea.setText("");
  busyLabel.setText("Searching ...");
  new SwingWorker<Void, Void>() {
     @Override
     protected Void doInBackground() throws Exception {
        doSearch();
        return null;
     }

     @Override
     protected void done() {
        busyLabel.setText("Idle");
     }
  }.execute();
}

You can use also the SwingUtilities's invokeLater method to to update the GUI swing components from an application thread. 您还可以使用SwingUtilities的invokeLater方法来从应用程序线程更新GUI Swing组件。

private void searchForPattern(java.awt.event.ActionEvent evt) {

  SwingUtilities.invokeLater(
    new Runnable(){
      public void run(){        
         textArea.setText("");
         busyLabel.setText("Searchnig ...");
      }
    }
  );

  doSearch();

  SwingUtilities.invokeLater(
    new Runnable(){
      public void run(){
         busyLabel.setText("Idle");
      }
    }
  );
}

EDIT PS : here i assume that you have not called the searchForPattern() function from the EDT, that's mean if you call it from an ActionListener you have to called like this: 编辑 PS :这里我假设您尚未从EDT调用searchForPattern()函数,这意味着如果您从ActionListener调用它,则必须像这样调用:

new Thread(
   new Runnable(){
      public void run(){
         searchForPattern(....)
      }
    }
  ).start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM