gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:53:29 25 4
gpt4 key购买 nike

我已经阅读了很多关于 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); }
});
}
}

使用此代码,如果我单击按钮,句点会立即附加到标签上,这对我来说很有意义,因为我正在创建并 hibernate 后台线程,使 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();

关于java - 我是否在 EDT 之外更新 Swing 组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15102389/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com