首页 > 解决方案 > 使用线程更新jlabel的内容

问题描述

单击一个按钮时,我想使用线程来更改 JLabel 的内容。此按钮将处理一个花费大量时间的文档。但是当我点击按钮时,JLabel 的内容会在处理完文档后显示出来。我希望它可以立即显示。

这是代码

public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        String command = e.getActionCommand();
        // Load button
        if (command.equals("Load")) {
            // set load to true
            load = true;
            // get text area name
            name = nameField.getText();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    loadState.setText("Loading document "+name+" . Please wait!");
                }           
            }).start();
            // load daffodils
            if (name.toLowerCase().equals("daffodils.txt")) {
                try {
                    loadText(tpPoem);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
}

任何人都可以告诉我为什么这个线程不起作用。

标签: javaswingevent-dispatch-thread

解决方案


Swing 大多是单线程的,从多个线程调用方法可能会导致问题。您应该在称为事件调度线程 (EDT) 的特殊线程上修改您的标签。

ActionListener.actionPerformed在这个线程上运行,所以而不是

new Thread(new Runnable() {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        loadState.setText("Loading document "+name+" . Please wait!");
    }           
}).start();

你可以写:

loadState.setText("Loading document "+name+" . Please wait!");

您的加载似乎也在 EDT 上运行:

if (name.toLowerCase().equals("daffodils.txt")) {
    try {
        loadText(tpPoem);
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}

如果您在该方法中使用后台线程,则可以,否则请查看SwingWorker。那是为了在后台线程中执行冗长的任务。如果您使用长时间运行的任务阻止 EDT,则在任务完成之前不会更新标签。

如果您想从后台线程更新您的 GUI,则SwingWorker有相应的方法。此外,您可能会发现这个问题很有趣:When and Where to call EventQueue.invokeLater() method


推荐阅读