从 ActionListener 调用时 JFrame 未正确显示 [英] JFrame not showing up properly when called from ActionListener

查看:80
本文介绍了从 ActionListener 调用时 JFrame 未正确显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public class Start extends JFrame{
public static void main(String...s){
    Start obj = new Start();
    obj.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    obj.setBounds(100,100,300,300);
    JPanel main = new JPanel();
    obj.add(main);
    JButton btn = new JButton("Login");
    main.add(btn);
    btn.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            obj.setVisible(false);
            obj.dispose();
            new Progress();
        }
    });
    obj.setVisible(true);
}
}


class Progress extends JFrame{
int pro = 0;
Progress(){
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    setBounds(100,100,300,300);
    JPanel main = new JPanel();
    add(main);
    main.add(new JLabel("ejfbasj")); 
    JProgressBar progressBar = new JProgressBar(0,100);
    main.add(progressBar);
    Thread t1 = new Thread() {
        public void run() {
            while(pro<=100) {
                /*
                 * Do something - set progressbar value
                 * */
                try {
                    sleep(10);
                } catch (InterruptedException e) {}
                progressBar.setValue(pro);
                pro++;
            }
        }
    };
    t1.start();
    //Do something - gives progress values
    try {
        t1.join();
    } catch (InterruptedException e) {}
}
}

以上是我的问题的最小、可重现示例.
从 ActionListner 调用 Progress JFrame 时,JFrame 无法正确显示.我得到一个黑色的 JFrame,一秒钟后我得到了带有完整进度条的最终 JFrame.但是如果我直接调用 new Progress() ,它可以正常工作(即看到进度条已填满).
我发现在UI线程中创建新线程无法绘制Frame.我应该使用 Swing.Timer.
我不知道如何使用 Swing.Timer.任何其他方法表示赞赏.

Above is Minimal, Reproducible Example of my problem.
When Progress JFrame is called from ActionListner, the JFrame doesn't appear properly. I get a black JFrame and after a sec I get final JFrame with full progressbar. But if I call new Progress() directly, it works properly(i.e. seeing progressbar filling up).
I found that creating new Thread in UI thread is unable to draw Frame. And I should use Swing.Timer.
I don't know how to do it with Swing.Timer. Any other approach is appreciated.

推荐答案

问题 #1

Progress(){
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

最后调用 setVisible,在您建立 UI 之后.如果你需要在 UI 可见后更新它,你应该调用 invalidaterepaint 来触发一个新的布局和绘制过程

Call setVisible last, after you've established the UI. If you need to update the UI after it's visible, you should call invalidate and repaint to trigger a new layout and paint pass

Thread t1 = new Thread() {
    public void run() {
        while(pro<=100) {
            /*
             * Do something - set progressbar value
             * */
            try {
                sleep(10);
            } catch (InterruptedException e) {}
            progressBar.setValue(pro);
            pro++;
        }
    }
};
t1.start();
//Do something - gives progress values
try {
    t1.join();
} catch (InterruptedException e) {}

好吧,这实际上是两个问题.

Ok, this is actually tw problems.

首先,Swing 不是线程安全的,您不应从事件调度线程的上下文之外更新 UI.正如您所说,您应该使用 Swing Timer 或更合适的方式,使用 SwingWorker

First, Swing is NOT thread safe and you should not update the UI from outside the context of the Event Dispatching Thread. You should, as you said, either use a Swing Timer or probably more suitably, a SwingWorker

其次,t1.join 正在阻塞当前线程.因为此构造函数是从 ActionListener 调用的,这意味着您处于事件调度线程的上下文中,即用于更新 UI 的线程,因此,在线程完成之前不会发生任何变化

Secondly, t1.join is blocking the current thread. Because this constructor was called from the ActionListener, this means you're in the context of the Event Dispatching Thread ie, the thread used to update the UI with, so, nothing will change until the thread is completed

例如:

我还会讨论有关使用多个框架、packsetLocationRelativeTo 之类的东西的 setBounds 以及使用边框或布局等其他东西的事情增加填充的约束,但还有很多其他例子

I'd also discuss things about using multiple frames, setBounds of things like pack, setLocationRelativeTo and using other things like borders or layout constraints to increase the padding, but there are plenty of other examples

这篇关于从 ActionListener 调用时 JFrame 未正确显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆