Java JLabel在while循环中不更新

Java JLabel在while循环中不更新,java,swing,awt,actionlistener,event-dispatch-thread,Java,Swing,Awt,Actionlistener,Event Dispatch Thread,我对编程非常陌生,我想知道你们是否知道这个问题的答案。我正在使用AWT gui,我正在尝试制作一个程序,以快速的速度逐字向您读取文本文件,以训练您更快地阅读。问题是应该一次显示一个单词的JLabel没有更新。提前谢谢大家,如果我的代码很难阅读或凌乱,我深表歉意 package fastreader; // this is a program where you input a location of a text file and it will read the file to you on

我对编程非常陌生,我想知道你们是否知道这个问题的答案。我正在使用AWT gui,我正在尝试制作一个程序,以快速的速度逐字向您读取文本文件,以训练您更快地阅读。问题是应该一次显示一个单词的JLabel没有更新。提前谢谢大家,如果我的代码很难阅读或凌乱,我深表歉意

package fastreader; 
// this is a program where you input a location of a text file and it will read the file to you one word at a time very fast.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import static java.lang.Thread.sleep;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
/**
 *
 * @author S578748
 */
public class FastReader implements ActionListener{
    //Frame
    private static JFrame frame;            
    //Panel
    private static JPanel selectPanel;      
    //Buttons
    private static JButton enterButton;  
    //Labels
    private static JLabel selectFile;
    public static JLabel readLabel;
    //TextField
    private static JTextField fileLocation;
    //Strings
    public static String file;
    public static String word;
    public static String data;
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        frame = new JFrame();
        selectPanel = new JPanel();
        enterButton = new JButton();
        
        frame.setSize(450, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(selectPanel);
        
        selectPanel.setLayout(null);
        
        selectFile = new JLabel("Enter Location of File");
        selectFile.setBounds(10, 20, 160, 25);
        selectPanel.add(selectFile);
        
        fileLocation = new JTextField();
        fileLocation.setBounds(200, 20, 160, 25);
        selectPanel.add(fileLocation);
        
        enterButton = new JButton("Enter");
        enterButton.setBounds(10, 40, 80, 25);
        enterButton.addActionListener(new FastReader());
        selectPanel.add(enterButton);
        
        readLabel = new JLabel("");
        readLabel.setBounds(10, 60, 160, 25);
        selectPanel.add(readLabel);
        
        frame.setVisible(true);
    }

    
    //Action Field if Button is Pressed
    @Override
    public void actionPerformed(ActionEvent e) {
        //Getting the file location from the TextField.
        file = fileLocation.getText();
        Scanner s = null;
            try{
                s = new Scanner(new FileInputStream(file));
            }catch (FileNotFoundException ex) {
                Logger.getLogger(FastReader.class.getName()).log(Level.SEVERE, null, ex);
            }
        
        while (s.hasNextLine()) {
                data = s.nextLine();
                
                while(data.contains(" ")){
                    word = data.substring(0,data.indexOf(" ")); // this splits the lines into words.
                    data = data.substring(data.indexOf(" ")+1);
                    
                    readLabel.setText(word); // this is where it messes up, it is supposed to change the JLabel in the program but it doesn't seem to update.
                    
                    if(word.length()<3){
                        try {
                            sleep(100); // these timers are supposed to create a delay where you can read the word.
                        } catch (InterruptedException ex) {
                            Logger.getLogger(FastReader.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                        
                    else if(word.length()<6){
                        try {
                            sleep(200);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(FastReader.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                    
                    else{
                        try {
                            sleep(300);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(FastReader.class.getName()).log(Level.SEVERE, null, ex);
                        }                       
                    } 
                    System.out.println(word);
                }
                readLabel.setText(data);
            }    
    }
    
}
包快速阅读器;
//这是一个程序,你输入一个文本文件的位置,它会以非常快的速度一次读取一个单词。
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.io.FileInputStream;
导入java.io.FileNotFoundException;
导入静态java.lang.Thread.sleep;
导入java.util.Scanner;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入javax.swing.*;
/**
*
*@作者S578748
*/
公共类FastReader实现ActionListener{
//框架
私有静态JFrame;
//面板
专用静态JPanel selectPanel;
//钮扣
私有静态JButton enterButton;
//标签
私有静态JLabel选择文件;
公共静态JLabel readLabel;
//文本字段
私有静态JTextField文件位置;
//弦
公共静态字符串文件;
公共静态字符串字;
公共静态字符串数据;
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args){
frame=新的JFrame();
selectPanel=newjpanel();
enterButton=newjbutton();
框架。设置尺寸(450200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(选择面板);
选择panel.setLayout(空);
选择File=newjlabel(“输入文件位置”);
选择file.setBounds(10,20,160,25);
selectPanel.add(selectFile);
fileLocation=newjtextfield();
setBounds(200,20,160,25);
选择Panel.add(文件位置);
enterButton=新的JButton(“回车”);
enterButton.setBounds(10,40,80,25);
enterButton.addActionListener(新的FastReader());
选择Panel.add(输入按钮);
readLabel=新的JLabel(“”);
readLabel.setBounds(10,60,160,25);
选择Panel.add(读取标签);
frame.setVisible(true);
}
//按下按钮时的操作字段
@凌驾
已执行的公共无效操作(操作事件e){
//从文本字段获取文件位置。
file=fileLocation.getText();
扫描器s=null;
试一试{
s=新扫描仪(新文件输入流(文件));
}捕获(FileNotFoundException ex){
Logger.getLogger(FastReader.class.getName()).log(Level.SEVERE,null,ex);
}
而(s.hasNextLine()){
data=s.nextLine();
while(data.contains(“”){
word=data.substring(0,data.indexOf(“”);//这会将行拆分为单词。
data=data.substring(data.indexOf(“”+1);
readLabel.setText(word);//这就是它出错的地方,它应该更改程序中的JLabel,但似乎没有更新。

if(word.length()这个问题有点技术性。Java的AWT框架只有一个线程来更新UI,这个线程被while循环和
sleep
调用占用。在
actionPerformed
方法的实现中,您正在进行
sleep
调用。一个解决方案是将它全部封装在一个线程中

    @Override
    public void actionPerformed(ActionEvent e) {
        new Thread(() -> {
            // here goes your current code
        }).start();
    }
这是假设您使用的至少是Java8,它可以在具有不同语法的其他版本中完成。
希望有帮助。

Swing是一个单线程库。所有绘制任务都在事件调度程序线程()中执行。在EDT上运行长进程(如睡眠)会使该线程保持忙碌,因此它不会执行更新gui等其他操作。gui会变得无响应(冻结)。此外,您不希望每次单击按钮时都构造一个新的
FastReader
实例。请使用
enterButton.addActionListener(此)
1)非常不鼓励使用
null布局
。请阅读并了解如何使用它们。2)我不是多线程专家,因此我会建议一种可能更简单的方法。读取文件肯定会在控制台打印
word
时正常工作。您可以通过填写一个列表来拆分收集数据和显示数据的两个操作使用当前线程中的
word
字符串,读取整个文件并收集数据后,您可以迭代列表以更新标签。