【问题标题】:updating jlabel更新 jlabel
【发布时间】:2012-01-28 14:55:35
【问题描述】:

我在更新方法中的 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!");

【问题讨论】:

  • 你是如何以及从哪里调用的???
  • 您仍然需要显示更多上下文,甚至可能是SSCCE
  • 我认为这有点像......一个运行的程序,并且做我想要它做的事情?我知道它正在使用该方法,因为我做了一个系统输出打印,它打印出来了。
  • droidus:您的错误在于您没有向我们展示的代码。很可能您在非可视化引用上调用了一个方法,但是在您发布有问题的代码之前无法判断。
  • 请学习java命名约定并遵守它们

标签: java swing jlabel concurrency


【解决方案1】:

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

以下是创建 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 方法中创建您的“测试”对象(为了符合 Java 命名约定,应该将其命名为“测试”)。由于它是在 main 内部声明的,因此该变量仅在 main 内部具有作用域,并且在其他任何地方都不可见。

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

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

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

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

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

  public static String[] runDiagnostics() throws IOException {

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

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

另外,Robin 的假设是正确的,即使你解决了这个问题,你也会遇到 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 命名约定。所有类名都应以大写字母开头。这让其他人更容易理解您的代码在做什么。

【讨论】:

  • 好的。这是我的代码:pastebin.com/rBhG4p4zpastebin.com/QCXXt6p1
  • 尽管我讨厌使用 pastebin 代码,但如果它完整,我会偶尔使用它。您发布的代码在任何地方都没有主要方法。怎么会有人测试它?它无法运行,没有意义。请阅读并使用sscce 技术。
  • 出于测试目的,只需运行诊断程序。这就是一个代码 sn-p 的全部目的。我把它改成了 main 方法。
  • @droidus:好的,出于测试目的,我已经运行了您的代码,但我什至没有看到 GUI。如果您不能发布我们可以自己运行和测试的代码,这将变得最令人沮丧。 编辑:现在我已将gui1.startGUI(); 行添加到测试类中,我看到了GUI,还看到了"Now running diagnostics... Please wait!" JLabel。再次阅读我关于如何创建SSCCE 的链接。如果我们有机会帮助您,您需要努力提出适当的问题。
  • @droidus:当您使用 pastebin 帖子时,这意味着您的代码太大而无法在论坛中发布。由于我们都是志愿者,您不应该要求我们阅读与您手头的问题无关的代码。相反,由于您要求我们免费提供帮助,应该首先努力隔离您的问题,然后创建一个sscce,然后将其发布在此处。再次,请阅读链接,因为它会解释一切。
【解决方案2】:

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

“正在运行诊断...请稍候!”

消息,我假设您正在运行诊断程序并尝试在同一线程上更新 UI。您发布的代码不包含任何明显的错误,这可以解释您的调用原因

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

不会更新标签内容。

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

有了这些信息和链接,您应该能够找到所有相关信息。同样在这个网站上,您会发现多个关于如何使用 SwingWorker 执行后台计算和更新 UI 的示例,例如 my answer on a previous question

【讨论】:

  • 这可能是比我更好的答案。 1+ 如果通过他的代码验证,我会删除我的答案。
  • @HovercraftFullOfEels 这仍然是一个猜测,所以我也可能完全错了。一个包含所有信息的体面问题会让事情变得更容易
  • 根据他在 pastebin 中发布的代码,我们似乎都是正确的。
猜你喜欢
  • 2020-06-26
  • 2012-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多