更新jlabel

时间:2012-01-28 14:55:35

标签: java swing jlabel concurrency

我在更新方法中的jlabel时遇到问题。这是我的代码:

    JLabel curStatus = new JLabel("");
JButton jbtnSubmit;

public static void main(String[] args) {
    test gui = new test();
    gui.startGUI();
    // gui.setCurStatus("testing!"); << seems to work here, 
    //but when i call it from another class, it doesn't want to run.
}

// Set up the GUI end for the user
public void startGUI() {
    // These are all essential GUI pieces
    new JTextArea("");
    final JFrame jfrm = new JFrame("my program");
    jfrm.setLayout(new FlowLayout());
    jfrm.setSize(300, 300);
    jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    jbtnSubmit = new JButton("Submit");

    jfrm.add(jbtnSubmit);
    jfrm.add(curStatus);
    jfrm.setVisible(true);
}

public void setCurStatus(String inCurStatus) {
    curStatus.setText(inCurStatus);
    curStatus.setVisible(true);
}

正在发生的事情是标签curStatus没有出现。例如,这是一个电话:

gui1.setCurStatus("Now running diagnostics... Please wait!");

2 个答案:

答案 0 :(得分:2)

您的问题似乎是错误的引用之一。

以下是创建GUI的方法:

  public static void main(String[] args) {
     test gui = new test();
     gui.startGUI();
     // gui.setCurStatus("testing!"); << seems to work here,
     // but when i call it from another class, it doesn't want to run.
  }

您可以在main方法内部创建“test”对象(应该通过符合Java命名约定的方式命名为“Test”)。由于它是在main内部声明的,因此该变量仅在main内部具有范围,并且在其他位置可见。

然后告诉我们您正在调用这样的方法:

gui1.setCurStatus("Now running diagnostics... Please wait!");

gui1变量引用一个测试类对象,但它可能引用一个不同的对象而不是正在显示的测试对象,因为原始显示的测试对象仅由一个本地的变量引用主要方法。

要解决此问题,您必须确保在当前显示的测试对象上调用setCurStatus。如何执行此操作取决于您的其他代码,尽管我们要求您这样做,但您拒绝向我们展示。

编辑:根据您发布的最新代码(由于缺少方法createTasksFile()而仍然无法为我编译),我的假设是正确的,您正在调用对于未显示的gui对象的setCurStatus(...)

  public static String[] runDiagnostics() throws IOException {

     gui gui1 = new gui(); // (A)
     gui1.setCurStatus("Now running diagnostics... Please wait!");

在行(A)上,您创建一个新的gui对象并在其上调用setCurStatus,但它正在显示的GUI对象,但它是一个完全不同且不相关的对象。它唯一的关系是它是一个与正在显示的对象相同的对象,但就是这样。解决方案是获取对显示的GUI的引用,并在该对象上调用此方法,并仅在该对象上调用。

同样,罗宾的假设是正确的,因为即使你解决了这个问题,你也会陷入Swing并发问题。 JLabel不会更新,因为Swing线程正在尝试打开文件:

  public static String[] runDiagnostics() throws IOException {

     gui gui1 = new gui();
     gui1.setCurStatus("Now running diagnostics... Please wait!");

     int i = 0;
     int errorsI = 0;
     File f = new File("tasks.txt");
     String[] errors = { "", "", "", "", "" };

     // try to create the file three times
     do {
        f.createNewFile();
        i++;
     } while (!f.exists() && i < 3);

所以我们都是对的。解决方法是在后台线程上打开文件,SwingWorker在这里可以正常工作。

编辑2
因此,要修复引用问题,请使用gui参数将gui的引用传递给runDiagnostics方法。然后在此参数上调用setCurStatus方法。例如:

  public static String[] runDiagnostics(gui gui1) throws IOException {

     //!! gui gui1 = new gui(); // !! no longer needed
     gui1.setCurStatus("Now running diagnostics... Please wait!");

调用方法时必须传入GUI:

        //!! results = taskBckg.runDiagnostics();
        results = taskBckg.runDiagnostics(gui);

另外,请编辑所有代码,使其遵循Java命名约定。所有类名都应以大写字母开头。这使其他人更容易理解您的代码正在做什么。

答案 1 :(得分:1)

我会根据您要显示的消息进行猜测,因为该问题缺少一些基本信息。基于

  

“正在运行诊断程序......请稍等!”

消息,我将假设您正在运行诊断程序并尝试在同一个线程上更新UI。您发布的代码没有明显的错误,这可以解释为什么您的电话

gui1.setCurStatus("Now running diagnostics... Please wait!");

不会更新标签内容。

您需要做的就是在Swing concurrency tutorial中解释。重点是您更新Event dispatch thread上的UI,并且您永远不会在该线程上执行繁重的计算,因为这将阻止UI,从而导致糟糕的用户体验。应该在工作线程上进行大量计算,例如使用SwingWorker类,并且只有更新UI(例如报告进度)才能在EDT上进行。

通过此信息和链接,您应该能够找到所有相关信息。此外,您还可以在此网站上找到有关如何使用SwingWorker执行后台计算和更新用户界面的多个示例,例如my answer on a previous question