Java GUI线程和更新 [英] Java GUI Threads and Updates

查看:79
本文介绍了Java GUI线程和更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个类,一个名为 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屋!

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