Java GUI线程和更新 [英] Java GUI Threads and Updates
问题描述
我有两个类,一个名为 GUIFrame ,其中包含所有图形元素,另一个线程类称为 squeak .在 GUIFrame 中,有两个图形元素,第一个是单击该按钮将启动线程的按钮:
I have two classes one called GUIFrame which holds all the graphical elements and a thread class called squeak. In the GUIFrame are two graphical elements, the first a button which when clicked launches the thread:
futures.put(1, pool.submit(new squeak("SqueakyThread",this.jTextArea1)));
第二个是 javax.swing.JTextArea ,其中包含一个名为 jTextArea1 的变量.
The second is a javax.swing.JTextArea with a variable called jTextArea1.
提到的第二个类是称为 squeak(可运行的实现)的线程类,并包含 while(true)循环.该类所做的全部工作是生成1到10之间的随机数,然后将该数字输出到 GUIFrame 类中的 jTextArea1 .
The second class as mentioned is the thread class called squeak (implements Runnable) and houses the while(true) loop. All this class does is generate a random number between 1 and 10 and then output that number to the jTextArea1 in the GUIFrame class.
问题:这是在Java中更新GUI元素的正确正式方法吗?
Question: Is this the correct formal way to update a GUI element in Java ?
我知道这个问题已经问了很多,但是有了所有不同的答案,我希望这可以为我自己和其他人提供一个简单的模板.
I realise this question has been asked a lot but with all the different answers out there I hope that this might provide a simple template for myself and others.
GUIFrame.java
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class GUIFrame extends javax.swing.JFrame {
public GUIFrame() {
this.pool = Executors.newCachedThreadPool();
initComponents();
}
private ExecutorService pool;
private Map<Integer, Future<?>> futures = new HashMap<>();
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jButton1 = new javax.swing.JButton();
jScrollPane2 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jButton1.setText("Start");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jTextArea1.setEditable(false);
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane2.setViewportView(jTextArea1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 468, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 188, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 444, Short.MAX_VALUE))
.addContainerGap())
);
pack();
}// </editor-fold>
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
futures.put(1, pool.submit(new squeak("SqueakyThread",this.jTextArea1)));
}
/**
* @param args the command line arguments
*/
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(GUIFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(GUIFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(GUIFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(GUIFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new GUIFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1;
// End of variables declaration
}
squeak.java
import java.util.Random;
import java.util.concurrent.TimeUnit;
import javax.swing.SwingUtilities;
public class squeak implements Runnable {
private String Type = "";
private javax.swing.JTextArea MW;
squeak (String type, javax.swing.JTextArea MW)
{
this.Type = type;
this.MW = MW;
}
@Override
public void run ()
{
while(true)
{
UpdateGUI(RandomNumber()+"\r\n");
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e)
{
UpdateGUI("Thread is now Exiting!\r\n");
//Return cause program to exit the while(true) loop and end
return;
}
}
}
private int RandomNumber(){
Random r = new Random();
int num = r.nextInt(10-1) + 1;
return num;
}
private void UpdateGUI(final String foo) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Here, we can safely update the GUI
// because we'll be called from the
// event dispatch thread
MW.append(foo);
}
});
}
}
推荐答案
关于
private void updateGUI(final String foo) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Here, we can safely update the GUI
// because we'll be called from the
// event dispatch thread
MW.append(foo);
}
});
}
是的,这绝对是允许非SWING事件线程中的代码更新Swing组件的一种方法-通过SwingUtilities.invokeLater(new Runnable() {...})
将Runnable排队到Swing事件线程队列中.
Yes, that is definitely one way to do allow code in a non-Swing event thread to update a Swing component -- by queuing a Runnable on to the Swing event thread queue via SwingUtilities.invokeLater(new Runnable() {...})
.
另一种方法,也是我的首选方法,是使用SwingWorker,因为它具有内置的机制,可以在后台线程中运行代码,并且仍然能够在Swing事件线程上安全地进行Swing调用.
Another way, and my preferred way, is to use a SwingWorker since this has built in machinery to allow for running code in a background thread and still being able to safely make Swing calls on the Swing event thread.
我的第一个批评(我必须找到要批评的东西,对吧?)是您的代码应遵循Swing命名约定.例如,变量名应以小写字母开头,而不是大写字母.如果您只是出于自己的喜好创建代码,那么这并不是很重要,但是如果您希望其他人查看或更新或维护您的代码,则变得非常重要.
My first criticism (and I have to find something to criticize, right?) is that your code should follow Swing naming conventions. For instance, variable names should start with a lower-case letter, not an upper case letter. This isn't so important if you are just creating code for your own enjoyment but becomes very important if you want others to review or update or maintain your code.
我的第二个批评是在这里
My second criticism is here:
jButton1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(java.awt.event.MouseEvent evt) {
jButton1MouseReleased(evt);
}
});
您不应该将MouseListeners用于JButton,因为它的级别太低了.请使用ActionListeners,因为这是它们的用途,并且更安全.例如,如果您的代码禁用了按钮的操作或其模型,则按钮不应响应,但是您的代码将无法正常运行,也将不会被正确禁用.
You shouldn't use MouseListeners for JButtons as that's getting too low level. Use ActionListeners as this is what they are made for and is much safer. For instance if your code disables the button's Action or its model, the button shouldn't respond, but your code will not behave correctly and will not be correctly disabled.
这篇关于Java GUI线程和更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!