Java 从 SQL 数据库加载时的进度条

Java Progress Bar While Loading From SQL Database

我的目标:从数据库加载时的进度条

我目前正在开发一个日程安排程序,我的一位经理将出于多种目的使用它,但主要是为员工设置每周日程安排。当从远程位置访问 SQL 数据库 时,显然需要一秒钟以上的时间来加载,我想为用户提供一些 反馈 让他们知道程序仍然是 运行。

我真的很想要一个进度条,显示在加载时 table 中已加载的行占总行数的百分比,但我不知道这是否可能.我在想一些不确定的东西,比如 JProgressBar,它只是在建立连接和处理结果集时移动。谢谢!


代码

以下代码是连接到SQL数据库并处理结果集的方法:

public static String[][] getEmps(String sqlQuery) {
    String[][] employee = new String[countRows("SELECT COUNT(*) FROM employee;")][10]; //creates array for employees
    ResultSet rs = null; //declares result set
    try(Connection conn = DriverManager.getConnection(url,uname,pass)) { //connects to database
        Integer count = 0;
        try(Statement stmt = conn.createStatement()) {
            rs = stmt.executeQuery(sqlQuery);
            while (rs.next()){
                employee[count][0] = rs.getString("fname");                 //Employee's First Name
                employee[count][1] = rs.getString("lname");                 //Employee's Last Name
                employee[count][2] = String.valueOf(rs.getInt("enum"));     //Employee's Employee ID
                employee[count][3] = rs.getString("dept");                  //Employee's Department
                employee[count][4] = rs.getString("position");              //Employee's Position in Dept
                employee[count][5] = String.valueOf(rs.getInt("class"));    //Employee's Class
                employee[count][6] = String.valueOf(rs.getInt("cashNum"));  //Employee's Cashier Num
                employee[count][7] = String.valueOf(rs.getInt("assNum"));   //Employee's Assistant Num
                employee[count][8] = String.valueOf(rs.getInt("age"));      //Employee's Age
                employee[count][9] = String.valueOf(rs.getDate("dob"));     //Employee's Date of Birth

                count++;
            }
        return employee;
        }catch (SQLException ex) { //Prints Errors When DB Connection Fails
            System.err.println("SQLException: " + ex.getMessage());
            System.err.println("SQLState: " + ex.getSQLState());
            System.err.println("VendorError: " + ex.getErrorCode());
            System.exit(1);
        }
    }catch (SQLException ex) { //Prints Errors When DB Connection Fails
        System.err.println("SQLException: " + ex.getMessage());
        System.err.println("SQLState: " + ex.getSQLState());
        System.err.println("VendorError: " + ex.getErrorCode());
        System.exit(1);
    }
    return null;
}

...以及我希望出现并显示进度的进度条 class:

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.Dimension;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.JLabel;
import javax.swing.border.TitledBorder;
import java.awt.Font;
import java.awt.Color;
import java.awt.Cursor;

public class ProgressBar extends JFrame {

private JPanel contentPane;
private JPanel pnlProgressBar;

private String title = null;

private ProgressBar progressWindow = this;

private BufferedImage icon;
private JProgressBar progressBar;
private JPanel panel;
private JPanel panel_1;

public static void main(String[] args){
    ProgressBar progressbar = new ProgressBar("TEST");
}

public JProgressBar getProgressBar() {
    return progressBar;
}

public ProgressBar(String title){
    this.title = title;
    mbOSBoot.setLaf();
    initialize();
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    setVisible(true);
}

private void initialize() {
    setTitle("Loading.");
    setPreferredSize(new Dimension(400, 125));
    setLocationRelativeTo(null);
    setBounds(new Rectangle(0, 0, 400, 125));
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setBounds(100, 100, 400, 125);

    //Animates a Loading... as title of window
    class AnimatedLoading extends TimerTask {
        @Override
        public void run() {
            String currTitle = progressWindow.getTitle();
            switch(currTitle){
            case "Loading.": progressWindow.setTitle("Loading..");
                break;
            case "Loading..": progressWindow.setTitle("Loading...");
                break;
            case "Loading...": progressWindow.setTitle("Loading.");
                break;
            }
        }
    }
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new AnimatedLoading(), 0, 1000);
        }
    });
    //End Window Animation

    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);
    {
        pnlProgressBar = new JPanel();
        pnlProgressBar.setBorder(new TitledBorder(null, title, TitledBorder.LEADING, TitledBorder.TOP, null, new Color(59, 59, 59)));
        contentPane.add(pnlProgressBar, BorderLayout.CENTER);
        pnlProgressBar.setLayout(new BorderLayout(0, 0));
        {
            progressBar = new JProgressBar(0,100);
            progressBar.setFont(new Font("SansSerif", Font.BOLD, 13));
            progressBar.setStringPainted(false);
            pnlProgressBar.add(progressBar);
            progressBar.setVisible(true);
        }
        {
            panel = new JPanel();
            pnlProgressBar.add(panel, BorderLayout.NORTH);
        }
        {
            panel_1 = new JPanel();
            pnlProgressBar.add(panel_1, BorderLayout.SOUTH);
        }
    }
}

}

编辑 2017 年 3 月 26 日

所以,我意识到我遗漏了一些重要信息...方法 getEmps() 正在被另一个 class 调用,需要将结果 String[][] 提供给创建图形用户界面。我是否必须在调用 getEmps() 方法的 class 中包含有关 SwingWorker 等的所有代码,或者为了组织起见,我是否可以在单独的 class 中执行此操作?调用getEmps()方法的一段代码如下:

        if(SQLDatabase.countRows("SELECT COUNT(*) FROM employee;") == 0){
        JOptionPane.showMessageDialog(null, "No Employees Could Be Found in the Database. If You Believe This is an Error, Please Contact Your Network Administrator");
    }else{
        for(int i = 0; i < SQLDatabase.countRows("SELECT COUNT(*) FROM employee;"); i++){
            String[][] emps = new String[SQLDatabase.countRows("SELECT COUNT(*) FROM employee;")][10];
            emps = SQLDatabase.getEmps();

            EmployeeInfoPanel empInfoPanel = new EmployeeInfoPanel(pnlViewPane, emps, i, title, frmGuiAllEmps);
        }
    }

按照建议 , you should retrieve rows in the background using SwingWorker. To see the effect, start from this complete

  • 添加一个JProgressBar:

    f.add(model.jpb, BorderLayout.NORTH);
    …
    private static class JDBCModel extends AbstractTableModel {
    
        private final JProgressBar jpb = new JProgressBar();
        …
    }
    
  • 设置工作线程启动时indeterminate属性:

    JDBCWorker worker = new JDBCWorker();
    jpb.setIndeterminate(true);
    worker.execute();
    
  • 在worker的实现中清除done():

    @Override
    protected void done() {
        jpb.setIndeterminate(false);
    }
    

如果您决定显示中间进度,请参阅此相关 example