有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java的灵活性有问题。invokeLater()更新GUI

我整天都在尝试不同的变化,但几乎没有成功。有人能帮我解释一下我做错了什么吗?我只是一个线程方面的初学者

private JTextArea text = new JTextArea();
private JButton button = new JButton("Cancel");
    public StatusFrame() {
        text.setEditable(false);
        this.add(text);
        this.add(button, BorderLayout.EAST);
        this.setSize(new Dimension(150, 100));
        this.setVisible(true);
    }

    public void updateStatus(String textIn) {
        text.setText(textIn);
    }

    public JButton getButton() {
        return button;
    }

在另一个类中,我调用的方法可能需要一段时间才能完成。我希望能够调用StatusFrame。updateStatus()方法,以随时通知用户进度。 这就是我所拥有的:

someMethod() {
    // prevent GUI from freezing using threads
    final Runnable r = new Runnable() {
        public void run() {
            status = new StatusFrame();
        }
    };
    SwingUtilities.invokeLater(r);

//do something 
    status.update("process 1 completed");
//do something else
    status.updateStatus("Process 2 completed");
}

框架出现,但runnable之后的所有代码均未运行/处理。它只是停下来/挡住了/什么的。但GUI仍然处于活动状态

谢谢你的建议

注:我尝试过使用invokeAndWait()方法,但同样不确定我是否用正确的方法。因为我还没有学到很多关于线程的知识,所以现在最好是快速修复。欢迎任何指示


共 (3) 个答案

  1. # 1 楼答案

    你的概念倒过来了

    这是你的密码

    someMethod() {
        // prevent GUI from freezing using threads
        final Runnable r = new Runnable() {
            public void run() {
                status = new StatusFrame();
            }
        };
        SwingUtilities.invokeLater(r);
    
    //do something 
        status.update("process 1 completed");
    //do something else
        status.updateStatus("Process 2 completed");
    

    您应该在线程中执行长时间运行的代码,并使用SwingUtilities invokeLater方法更新GUI

    someMethod() {
        // prevent GUI from freezing using threads
        final Runnable r = new Runnable() {
            public void run() {
                status = new StatusFrame();
            }
        };
        new Thread(r).start();
    
    // inside the StatusFrame
    //do something 
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                update("process 1 completed");
            }
        );
    
     //do something else sometime later
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                 update("Process 2 completed");
            }
        );
    

    我不知道我的回答是否清楚

    1. 要有勇气。启动Java应用程序以确保Swing组件位于事件调度线程(EDT)上时调用
    2. 从EDT中,将长时间运行的进程作为可运行线程调用
    3. 在可运行线程中,由于您不在EDT上,请执行SwingUtilities。无论何时更新Swing组件,都可以使用invokeLater。这样可以确保在EDT上更新Swing组件

    每个Swing应用程序都应该从这样一个类开始:

    import javax.swing.SwingUtilities;
    
    import com.ggl.text.entry.model.TextEntryModel;
    import com.ggl.text.entry.view.TextEntryFrame;
    
    public class TextEntry implements Runnable {
    
        @Override
        public void run() {
            new TextEntryFrame(new TextEntryModel());
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new TextEntry());
        }
    
    }
    

    这门课做三件事

    1. 构建GUI数据模型
    2. 构建GUI框架
    3. 确保回转组件位于EDT上
  2. # 2 楼答案

    你也需要在EDT上致电更新。我建议您在主线程上睡觉,这样GUI就有机会在任何其他工作之前出现:

    someMethod() {
        // prevent GUI from freezing using threads
        Runnable r = new Runnable() {
            public void run() {
                status = new StatusFrame();
            }
        };
        SwingUtilities.invokeLater(r);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
        }
    
    //do something
        r = new Runnable() {
        public void run() {
                status.update("process 1 completed");
            }
        };
        SwingUtilities.invokeLater(r);
    
    
    //do something else
     r = new Runnable() {
        public void run() {
                status.update("Process 2 completed");
            }
        };
        SwingUtilities.invokeLater(r);
    }
    
  3. # 3 楼答案

    Concurrency in Swing

    您可能会发现使用Swing Worker更容易操作,因为它使用了一个线程,并且具有允许您正确更新GUI的方法