【问题标题】:JAVA Swing Gui Window HangsJAVA Swing Gui 窗口挂起
【发布时间】:2012-11-28 16:20:42
【问题描述】:

我在使用 SWING GUI 时遇到问题,或者至少我认为是 Swing gui。

这是我的主要代码文件:

/**
 * 
 */
package com.tda.t2.ctas.slasher;

import javax.swing.SwingUtilities;

import com.tda.t2.ctas.slasher.gui.mainFrame;
import com.tda.t2.ctas.slasher.utils.MyCloseListener;



public class SLASHer {

    public SLASHer () {
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        //EventQueue.invokeLater(new Runnable() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ConfigData myconfig = new ConfigData();
                try {
                    //TdaUrlHelper window = new TdaUrlHelper();
                    //window.tdaFrame.setVisible(true);
                    mainFrame tdaFrame = new mainFrame();
                    tdaFrame.setVisible(true);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

}

创建框架并打开它的简单调用。还有其他文件我没有放在这里以获得空间。但是我遇到的问题(我已经在几台机器和操作系统上尝试过)是窗口上的按钮似乎挂起。我可以选择窗口并单击按钮,它们会像被击中一样突出显示,但没有任何反应。我有一个选项卡式平面,单击其他选项卡也无济于事。有时会持续约 15 秒,有时会持续几分钟。但它总是最终会回来并响应新的输入(即它不记得我在它回来之前所做的所有点击)。整个应用程序很简单,因为它一直等到用户执行某项操作后再执行某项操作,所以我对它为什么会挂起感到困惑。

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 您的问题出在未显示的代码中。很可能您在 JButton 的 ActionListeners 中没有遵守 Swing 线程规则,但在我们看到有问题的代码之前谁知道。
  • 听起来像是 GUI 线程正在打印堆栈跟踪 ( :\. ) 或者您的多线程操作不正确。
  • 注意mainFrame类应该重命名为MainFrame。所有类名都应以大写字母开头。如果您希望其他人(比如我们!)能够理解您的代码并为您提供帮助,这一点很重要。
  • 发布的代码与问题无关 - 您必须检查您的应用程序以找出瓶颈所在:使用调试器,或者通过尝试在每一层上打印出东西来采用肮脏的方式应用程序,每次都走得更远。
  • 听起来像是一个ActionListener 附加到按钮上,该按钮使用工作线程在 EDT iso 上启动繁重的任务。查看concurrency in swing 教程

标签: java swing user-interface swingutilities


【解决方案1】:

附加到挂起按钮的违规代码是什么?检查您的控制台是否有异常,并在该代码的顶部和底部放置一些 System.out.println() 语句。看看你是否看到那些打印语句打印出来。观察顶部的打印和底部的打印需要多长时间。如果您看到这两个语句,那么您知道整个块正在执行,但是如果需要一段时间来显示最后一个语句,您就知道您正在挂起 Swing 线程(也称为 EDT - 事件调度线程)。 Swing UI 中的第一条规则在执行 ActionListener 时不能重绘。

为了制作响应式 UI,您必须在 10-100 毫秒(视觉上几乎是瞬间)内看到第一个和最后一个语句出现在控制台上。如果你真的想变得花哨,你可以在停止和底部使用 System.currentTimeMillis() 。减去这两个值并 println() 它。这将准确地告诉您该侦听器运行了多长时间。如果它大于 100 毫秒,您需要通过改进算法或卸载线程上的长计算来重构代码(参见 SwingWorker tutorial)。

public void actionPerformed(ActionEvent event) {
    System.out.println("Starting SomeProcess");
    long start = System.currentTimeMillis();

    // all your code belongs here

    long duration = System.currentTimeMillis() - start;
    System.out.printf("SomeProcess took %,d ms%n", duration );
}

【讨论】:

  • 我没有添加按钮代码,因为面板上总共有81个按钮。在那一点上,我按下什么按钮都没有关系。当它被挂起时,所有按钮都不起作用,直到它变得未挂起。几乎就像它没有意识到它现在有焦点,这就是我发布我所做的事情的原因。
  • 嗯,您需要多少帮助取决于您。你可以按照我的建议去做,自己找出问题的细节,或者只是为那些挂起 UI 的按钮之一发布代码。你是对的,我不会查看 81 个按钮侦听器,但我会查看 1 个按钮侦听器。我想如果你按照我的建议去做,你就会知道问题出在哪里。如果您无法弄清楚,请发布更多代码。
  • 我同意。出于某种原因,@JesterHawk 似乎不想发布任何侦听器代码。在他这样做之前,我们所能做的就是想知道发生了什么。可能只有一个听众就足够了。
  • 好吧,我们都知道他在高层做什么。他挂断了 EDT 线程,需要在线程上卸载一个长时间运行的计算。很可能是直接来自 EDT 线程的某种网络服务调用,但在他发布代码之前,我们真的无法告诉他到底出了什么问题。 :-)
  • 我同意;你的回答是体面的。 1+ 赞成票。我对计时器不太确定,因为在程序创建和测试运行期间时间可能很短,但在现实世界中时间很长。在某些情况下,无论测试程序中的时间如何,都需要后台线程。文件 I/O 和数据库方法就是其中之一。
猜你喜欢
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 2011-01-06
  • 2023-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
相关资源
最近更新 更多