选择 JCombobox 时 GUI 冻结,How to use Timer in Swing Application with Condition Statement in actionListener?

GUI freeze when JCombobox selected, How to use Timer in Swing Application with Condition Statement in actionListener?

我正在处理一个登录框架,我在其中使用用户创建的数据库检索和填充 JComboBox,然后我根据来自 JComboBox 的项目 select 设置 JLabel 的文本。 当用户 select 是 JComboBox 中的一个项目时,我想延迟执行并在 JLabel 中显示 'Connecting...' 文本,但是当我 select 一个项目时,GUI 冻结并在 5 秒后显示 'Connected' 它跳过 'Connecting...' JLabel。

非常感谢。

package com.softoak.dba;

import java.awt.Color;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import javax.swing.JComboBox;

public class Login{

private JFrame frame;
static ArrayList<String> dbcom = new ArrayList<String>();
static String[] usecom;
JLabel status = new JLabel("•");
JLabel lblNotConnected;

/**
 * Launch the application.
 */
public static void main(String[] args) throws Exception{
    Connection m_Connection = DriverManager.getConnection("jdbc:sqlserver://localhost;integratedSecurity=true");

    String dbs =  "SELECT * FROM sys.databases WHERE owner_sid != 1";

    Statement st = m_Connection.createStatement();

    ResultSet m_ResultSet = st.executeQuery(dbs);
    dbcom.add("-None-");

    while(m_ResultSet.next()){
        dbcom.add(m_ResultSet.getString(1));
    }
    usecom = new String[dbcom.size()];
    usecom = dbcom.toArray(usecom);

    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Login window = new Login();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public Login() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */

private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(null);

    status.setBounds(385, 235, 10, 10);
    status.setForeground(Color.red);
    frame.getContentPane().add(status);

    JLabel lblLoginApplication = new JLabel("Login Application");
    lblLoginApplication.setFont(new Font("Lucida Calligraphy", Font.BOLD, 20));
    lblLoginApplication.setBounds(120, 25, 220, 30);
    frame.getContentPane().add(lblLoginApplication);

    JComboBox comboBox = new JComboBox(usecom);
    comboBox.setBounds(230, 80, 110, 30);
    comboBox.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e)  {
                if (comboBox.getSelectedIndex() == 1 || comboBox.getSelectedIndex() == 2) {
                    lblNotConnected.setText("Connecting...");
                    try{
                        Thread.sleep(5000);
                  }catch(InterruptedException ex){
                        JOptionPane.showMessageDialog(null,ex.getMessage());
                  }
                    status.setForeground(Color.green);
                    lblNotConnected.setText("Connected");
                    JOptionPane.showMessageDialog(null, "Connected");
                }
                  else{
                      status.setForeground(Color.red);
                      lblNotConnected.setText("Not Connected");
                  }
                }
      });
    frame.getContentPane().add(comboBox);

    JLabel lblSelectDatabase = new JLabel("Select Database");
    lblSelectDatabase.setFont(new Font("Microsoft Sans Serif", Font.BOLD, 14));
    lblSelectDatabase.setBounds(91, 79, 129, 30);
    frame.getContentPane().add(lblSelectDatabase);

    lblNotConnected = new JLabel("Not Connected");
    lblNotConnected.setFont(new Font("Elephant", Font.PLAIN, 12));
    lblNotConnected.setBounds(280, 230, 110, 20);
    frame.getContentPane().add(lblNotConnected);
}

}

在侦听器中执行的代码在 Event Dispatch Thread(EDT) 上执行。当您使用 Thread.sleep() 时,这会导致 EDT 休眠,这意味着 GUI 无法自行重绘。阅读 Concurrency 上的 Swing 教程部分了解更多信息。

出于上述原因,任何可能较长的 运行 任务不应在 EDT 上执行。相反,您应该使用单独的线程。查看上述教程中的 SwingWorker。您可以在那里使用 Thread.sleep() 并发布要显示的值。

但是,为什么要让用户等待 5 秒?我知道我会感到沮丧。

也许您应该使用 ProgressMonitor 来让用户知道您可能正在执行一项较长的 运行 任务。阅读有关 How to Use Progress Bars 的 Swing 教程部分,了解更多信息和工作示例。