【发布时间】:2014-12-16 09:54:54
【问题描述】:
我找到了很多关于我的问题的答案,但我仍然不明白为什么我的应用程序没有抛出任何异常。 我在 NetBeans 8 中创建了一个新的 java 表单应用程序。 我的表单是这样创建并显示在 main 方法中的:
public static void main(String args[])
{
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try
{
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
{
if ("Nimbus".equals(info.getName()))
{
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (ClassNotFoundException ex)
{
java.util.logging.Logger.getLogger(MainForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
catch (InstantiationException ex)
{
java.util.logging.Logger.getLogger(MainForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
catch (IllegalAccessException ex)
{
java.util.logging.Logger.getLogger(MainForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
catch (javax.swing.UnsupportedLookAndFeelException ex)
{
java.util.logging.Logger.getLogger(MainForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
new MainForm().setVisible(true);
}
});
}
因此,这个新的 Runnable 创建了新的 MainForm 并将其设置为可见。
然后,在我的代码中,我启动了更新一些 jButton 和 jTextField 的新线程。代码如下:
private void updateUI() {
updateUIThread = new Thread(() ->
{
while (true) {
try {
jtfIP.setEnabled(!Start && !autoRec);
jtfPort.setEnabled(!Start && !autoRec);
jtfSlaveID.setEnabled(!Start && !autoRec);
jtfTimeout.setEnabled(!Start && !autoRec);
jtfReqInterval.setEnabled(!Start && !autoRec);
jCheckBox1.setEnabled(!Start && !autoRec);
jCBReconnect.setEnabled(!Start && !autoRec);
if (db != null) {
if (!db.getIsOpen()) {
jPBD.setBackground(Color.RED);
jPBD.setForeground(Color.WHITE);
jPBD.setText("ER");
} else {
jPBD.setBackground(Color.GREEN);
jPBD.setForeground(Color.BLACK);
jPBD.setText("OK ");
}
} else {
jPBD.setBackground(Color.RED);
jPBD.setForeground(Color.WHITE);
jPBD.setText(" ER ");
}
if (autoRec){
jbtnConnect.setText("Auto");
if (Start && Connected) {
jbtnConnect.setForeground(Color.BLACK);
jbtnConnect.setBackground(Color.GREEN);
} else {
jbtnConnect.setForeground(Color.WHITE);
jbtnConnect.setBackground(Color.RED);
}
} else {
if (Start) {
jbtnConnect.setText("Disconnect");
jbtnConnect.setForeground(Color.BLACK);
jbtnConnect.setBackground(Color.GREEN);
} else {
jbtnConnect.setText("Connect");
jbtnConnect.setForeground(Color.WHITE);
jbtnConnect.setBackground(Color.RED);
}
}
jtfErroriCitire.setText(String.valueOf(totalErrors));
try
{
Thread.sleep(300);
jPanel4.repaint(1);
}
catch (InterruptedException ex)
{
Logger.getLogger(MainForm.class.getName()).log(Level.SEVERE, null, ex);
}
}
catch (Exception ex) {
Logger.getLogger(MainForm.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
updateUIThread.start();
}
还有其他像上面这样启动的线程,我得到不同的值,这些值在上面的线程中更新。
我的问题是为什么我的代码不会引发任何关于从另一个线程更新的 UI 元素的异常?我没有使用SwingUtilities.invokeLater(new Runnable() { //code here });
而且我的代码执行得很完美……
谢谢!
【问题讨论】:
-
因为他们不这样做,所以由开发人员确保他们正确地将更新与 EDT 同步。做出该决定的原因很可能部分是由于这种设计的复杂性,部分是由于“可能”改变状态的组件的每种方法都会产生的费用必须检查是否正确线程
-
好的,所以我的代码应该使用 SwingUtilities.invokeLater(new Runnable() {});并且我的方法 UpdateUI() 应该在 invokeLater(new Runnable() { updateUI();} 中调用,或者我的方法应该在我的线程中调用 invokeLater,例如: private void updateUI() { updateUIThread = new Thread(() - > { while (true) { try { SwingUtilities.invokeLater(new Runnable() //code here });
-
当您想要更新 UI 时,您应该在 EDT 的上下文中执行此操作。一个好的方法是在 EDT 中使用
SwingWorker和publish内容为processed或触发属性更改事件...
标签: java multithreading user-interface elements invokelater