Java:在等待另一个线程完成时更新 UI

标签 java swing event-dispatch-thread

我有一些 Java Swing 登录面板。当用户单击“登录”按钮时,会发生广泛的数据库通信。我有一个想法将该数据库通信放入另一个线程中(该数据库通信用于填充一些 HashMap 和单例)。将通信放入单独的线程后,当用户输入其用户名和密码时,会发生数据库繁重的工作。当用户单击“登录”按钮时,代码将等待“繁重”线程加入,然后继续。

问题是,当我的代码等待数据库线程加入时,似乎无法完成 UI 更新。我不认为我可以使用 SwingWorker 进行数据库通信,因为用户可以随时单击“登录”按钮,甚至在 SW 完成之前,而且我没有办法加入 SwingWorker (数据库通信必须在实际登录之前进行) .

有没有办法在等待另一个线程加入时启用 Swing ui 更新?我错过了什么吗?

最佳答案

只需放置两个标志,然后在两个操作(数据库通信和用户单击)结束时,调用相同的方法并验证两个标志的状态。如果您想阻止用户输入,可以在模式对话框中显示进度条:

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UnsupportedLookAndFeelException;

public class TestThreadJoin {

    private boolean dbWorkDone = false;
    private boolean credentialsProvided = false;
    private JTextField loginTF;
    private JTextField passwordTF;

    protected void initUI() {
        final JFrame frame = new JFrame(TestThreadJoin.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel = new JPanel(new GridBagLayout());
        JLabel login = new JLabel("Login: ");
        JLabel password = new JLabel("Password: ");
        loginTF = new JTextField(20);
        passwordTF = new JPasswordField(20);
        GridBagConstraints gbc = new GridBagConstraints();
        panel.add(login, gbc);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        panel.add(loginTF, gbc);
        gbc.gridwidth = 1;
        panel.add(password, gbc);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        panel.add(passwordTF, gbc);
        JButton loginButton = new JButton("Login");
        loginButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                credentialsProvided = true;
                proceed();
            }
        });
        frame.add(panel);
        frame.add(loginButton, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
        SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {

            @Override
            protected Void doInBackground() throws Exception {
                Thread.sleep(10000);
                return null;
            }

            @Override
            protected void done() {
                super.done();
                dbWorkDone = true;
                proceed();
            }
        };
        worker.execute();
    }

    protected void proceed() {
        if (credentialsProvided && dbWorkDone) {
            System.err.println("Continuing ");
        }
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestThreadJoin().initUI();
            }
        });
    }
}

关于Java:在等待另一个线程完成时更新 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14276095/

相关文章:

java - 如何在 Java 8 流中增加计数

Java Swing 将类动态加载到面板中

java - 在 JButton 按下时运行函数

Java API "Run on EDT if not on EDT"

java - JPanel 不绘画,JFrame 保持空白

java - 将 System.out.print 转换为 JOptionPane?

java - 如何在主类中从另一个类的构造函数初始化数组字段?

java - 我的 java UI 单元测试将焦点集中在 GNOME 桌面上的原因可能是什么

Java socket BufferedReader一次从循环中读取所有输入

java - wait() 和 sleep() 有问题吗?