繁体   English   中英

我是否在EDT之外更新Swing组件?

[英]Am I updating Swing component outside of EDT?

我已经阅读了很多有关Swing,线程,invokeLater(),SwingWorker等的内容,但是我似乎无法完全理解所有内容,因此我试图创建一个非常简单的程序来进行说明。 我看了很多示例,但是似乎都没有显示我正在尝试做的事情。

这是我在示例中尝试做的事情。 我有一个按钮和一个标签,当我单击该按钮时,我希望程序暂停3秒,然后在标签的文本后面加上一个句点。 在这3秒钟内,我希望GUI正常显示并继续响应其他点击。 这是我写的:

import javax.swing.SwingWorker;

public class NewJFrame extends javax.swing.JFrame
{
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;

    public NewJFrame()
    {
        initComponents();
    }
    private void initComponents()
    {
        jButton1 = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        jButton1.setText("Button");
        jButton1.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton1ActionPerformed(evt);
            }
        });
        getContentPane().add(jButton1, java.awt.BorderLayout.CENTER);
        jLabel1.setText("Text");
        getContentPane().add(jLabel1, java.awt.BorderLayout.PAGE_END);
        pack();
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
    {
        SwingWorker worker=new SwingWorker()
        {
            protected Object doInBackground()
            {
                try{Thread.sleep(3000);}
                catch (InterruptedException ex){}
                return null;
            }
        };
        worker.execute();
        jLabel1.setText(jLabel1.getText()+".");
    }

    public static void main(String args[])
    {
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run(){ new NewJFrame().setVisible(true); }
        });
    }
}

使用此代码,如果单击按钮,则该句点立即添加到标签上,这对我来说很有意义,因为我正在创建并休眠一个后台线程,因此可以使用EDT来立即更新标签。 所以我尝试了这个:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
    Thread thread = new Thread();
    try{ thread.sleep(3000);}
    catch (InterruptedException ex){}
    jLabel1.setText(jLabel1.getText()+".");
}

除了阻止EDT导致按钮在将句点附加到标签文本之前变为蓝色三秒钟外,这几乎起作用。 我不希望该按钮看起来像是真的被快速单击时就被按下了整整三秒钟,所以我尝试这样做:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
    SwingWorker worker=new SwingWorker()
    {
        protected Object doInBackground()
        {
            try{Thread.sleep(3000);}
            catch (InterruptedException ex){}
            jLabel1.setText(jLabel1.getText()+".");
            return null;
        }
    };
    worker.execute();
}

这似乎可行,但是我不是从后台线程而不是EDT调用jLabel1.setText(...),因此违反了“ Swing单线程规则”吗? 如果是这样,是否有更好的方法来达到预期的效果? 如果没有,请您解释一下原因?

你真的很近...

尝试这样的事情。

SwingWorker worker=new SwingWorker()
{
    protected Object doInBackground()
    {
        try{
            Thread.sleep(3000);
        }catch (InterruptedException ex){}
        return null;
    }

    // This is executed within the context of the EDT AFTER the worker has completed...    
    public void done() {
        jLabel1.setText(jLabel1.getText()+".");
    }
};
worker.execute();

您可以通过使用EventQueue.isDispatchingThread()查看是否在EDT中运行。

更新

您还可以使用javax.swing.Timer ,它可能会更容易...

Timer timer = new Timer(3000, new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        jLabel1.setText(jLabel1.getText()+".");
    }
});
timer.setRepeats(false);
timer.start();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM