0

jf 是一个 JFrame 我试图每 200 毫秒移动一个像素。我创建了这个方法,所以我可以在继续之前暂停软件 200 毫秒。millis 和 millisn 是静态多头。

public static void waitsec() {

        millis =System.currentTimeMillis();
        millisn =System.currentTimeMillis();
            while (millisn<(millis+200)){
                millisn=System.currentTimeMillis();
            }
                }

以下部分是我试图让我的 JPanel (jp) 在按下按钮时缓慢移动 50 像素的部分:

public void actionPerformed(ActionEvent h){
if (h.getSource() == button){
    for (int i = 0; i <50; ++i){
        waitsec();
        out.println ("" + i);//I'm checkinf if the waitsec() is working OK
        x +=1;
        jp.setLocation(x, 0);
        totalGUI.repaint();
        jp.setVisible(true);//setting visible so I could focus on it
        jp.requestFocusInWindow (); //suspicious part
        jp.requestFocus ();  
}}
}

运行该程序的结果是: 数字在控制台中一个接一个地出现,它们之间的间隔是 200 mmillis,正如预期的那样。一旦数字停止出现(程序运行完毕),JPanel 就不会一直移动。如果我尝试最小化和最大化窗口,它不会显示,直到程序完成运行,就好像程序根本没有焦点一样......为什么它不集中,尽管我已经将它设置为可见并集中它?

4

1 回答 1

2

很多事情...

首先,您阻塞了事件调度线程,阻止它处理任何新事件,包括重绘事件。这将使您的应用程序看起来像挂起一样,因为本质上它已经挂起。

waitSec其次,您应该利用可用的 API 功能,而不是滚动您的方法,例如,而不是尝试循环直到一个时间段过去,虽然消耗 CPU 周期,但您应该使用它Thread.sleep

尽管如此,你永远不应该在 EDT 的上下文中睡觉。

相反,您应该使用类似 a 的东西,javax.swing.Timer它可以配置为定期引发事件。这样做的好处是它会在 EDT 的上下文中引发事件,从而可以安全地从内部更新 UI(例如,与创建自己的线程不同)

查看Swing 中的并发以及如何使用 Swing 计时器了解更多详细信息

第三,JPanel默认是不可聚焦的,所以调用requestFocusInWindow不太可能有任何效果

第四,默认情况下,Swing 使用布局管理器,因此您实际上可能也在为此苦苦挣扎

于 2013-10-27T22:45:11.560 回答