简体   繁体   English

在 Java 中的 While 循环期间 GUI 冻结

[英]GUI Freezes During While Loop in Java

http://i.stack.imgur.com/XvHm5.png http://i.stack.imgur.com/XvHm5.png

When I click the On button it should start spamming 1's across the JTextField.当我单击 On 按钮时,它应该开始在 JTextField 中发送垃圾邮件 1。 Instead The entire GUI freezes, including the close button.相反,整个 GUI 都冻结了,包括关闭按钮。 I am using a while loop that will stop when you click the jButton again.我正在使用一个 while 循环,当您再次单击 jButton 时该循环将停止。 Because the jButton is frozen i cannot stop this program.因为 jButton 被冻结,我无法停止这个程序。 I have read that Threads and Multithreading would help but all of the tutorials are too complex for me to understand.我读过线程和多线程会有所帮助,但所有的教程都太复杂了,我无法理解。 They say to put the loop and GUI on different threads.他们说将循环和 GUI 放在不同的线程上。 I want to understand this to fix another program that I am working on which is much more complex.我想了解这一点以修复我正在处理的另一个更复杂的程序。 Thats why I made a simple example to show my problem.这就是为什么我做了一个简单的例子来说明我的问题。

http://i.stack.imgur.com/tbNAF.png http://i.stack.imgur.com/tbNAF.png

This is how the program shows.程序是这样显示的。 (The jTextField is not even updated. What I am asking is if someone knows a way to fix this, whether using threads or not. My code for this program is below. (jTextField 甚至没有更新。我要问的是是否有人知道解决这个问题的方法,无论是否使用线程。我的这个程序的代码如下。

public class whileLoop extends javax.swing.JFrame {
public whileLoop() {
    initComponents();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    jTextField1 = new javax.swing.JTextField();
    jToggleButton1 = new javax.swing.JToggleButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jToggleButton1.setText("On");
    jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jToggleButton1ActionPerformed(evt);
        }
    });

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jToggleButton1)
            .addGap(18, 18, 18)
            .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE)
            .addContainerGap())
    );
    jPanel1Layout.setVerticalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(jPanel1Layout.createSequentialGroup()
            .addContainerGap()
            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(jToggleButton1))
            .addContainerGap(12, Short.MAX_VALUE))
    );

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    );

    pack();
}// </editor-fold>

private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    if (jToggleButton1.isSelected()) {
        jToggleButton1.setText("Off");
        while (jToggleButton1.isSelected()) {
            jTextField1.setText(jTextField1.getText() + "1");
        }
    } else {
        jToggleButton1.setText("On");
    }
}
public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new whileLoop().setVisible(true);
        }
    });
}
// Variables declaration - do not modify
private javax.swing.JPanel jPanel1;
private javax.swing.JTextField jTextField1;
private javax.swing.JToggleButton jToggleButton1;
// End of variables declaration

} }

The main area of the code is:代码的主要区域是:

private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    if (jToggleButton1.isSelected()) {
        jToggleButton1.setText("Off");
        while (jToggleButton1.isSelected()) {
            jTextField1.setText(jTextField1.getText() + "1");
        }
    } else {
        jToggleButton1.setText("On");
    }
}

You have an infinite loop.你有一个无限循环。 The state of the toggle button is never changed after being set to true.切换按钮的状态在设置为 true 后永远不会改变。

Java's UI (and all UI I've worked with) is driven by a single thread. Java 的 UI(以及我使用过的所有 UI)由单个线程驱动。 User input is fed back to you on this single thread.用户输入会在此单线程上反馈给您。 Rendering is also done on this single thread.渲染也是在这个单线程上完成的。

The reason the textfield is never updated is the UI thread is never getting to render the screen again, as its tied up in your infinite loop.文本字段永远不会更新的原因是 UI 线程永远不会再次渲染屏幕,因为它被束缚在您的无限循环中。

Yes, you need to put this code in a separate thread, and start it when the toggle button becomes selected.是的,您需要将此代码放在一个单独的线程中,并在切换按钮被选中时启动它。 Then, you need to update the textfield from this separate thread.然后,您需要从这个单独的线程更新文本字段。 Look into SwingWorker .查看SwingWorker

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

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