GUI Freezes During While Loop in Java

我的梦境 提交于 2019-12-02 15:41:01

问题


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

When I click the On button it should start spamming 1's across the JTextField. Instead The entire GUI freezes, including the close button. I am using a while loop that will stop when you click the jButton again. Because the jButton is frozen i cannot stop this program. 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. 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

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.

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");
    }
}

回答1:


You have an infinite loop. The state of the toggle button is never changed after being set to true.

Java's UI (and all UI I've worked with) is driven by a single thread. 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.

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.



来源:https://stackoverflow.com/questions/17953590/gui-freezes-during-while-loop-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!