Java 中的 While 循环期间 GUI 冻结 [英] GUI Freezes During While Loop in Java

查看:16
本文介绍了Java 中的 While 循环期间 GUI 冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

当我单击 On 按钮时,它应该开始在 JTextField 中发送垃圾邮件 1.相反,整个 GUI 都冻结了,包括关闭按钮.我正在使用 while 循环,当您再次单击 jButton 时该循环将停止.因为 jButton 被冻结,我无法停止这个程序.我读过线程和多线程会有所帮助,但所有的教程都太复杂了,我无法理解.他们说将循环和 GUI 放在不同的线程上.我想了解这一点以修复我正在处理的另一个更复杂的程序.这就是为什么我做了一个简单的例子来说明我的问题.

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

这就是程序的显示方式.(jTextField 甚至没有更新.我要问的是是否有人知道解决这个问题的方法,无论是否使用线程.我的这个程序的代码如下.

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

}

代码的主要区域是:

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

推荐答案

你有一个无限循环.切换按钮的状态在设置为 true 后永远不会改变.

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

Java 的 UI(以及我使用过的所有 UI)由单个线程驱动.用户输入会在此单线程上反馈给您.渲染也是在这个单线程上完成的.

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.

文本字段永远不会更新的原因是 UI 线程永远不会再次渲染屏幕,因为它被束缚在您的无限循环中.

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.

是的,您需要将此代码放在一个单独的线程中,并在切换按钮被选中时启动它.然后,您需要从这个单独的线程更新文本字段.查看 SwingWorker.

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.

这篇关于Java 中的 While 循环期间 GUI 冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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