Search code examples
javamultithreadingswingworkerprogressmonitor

ProgressMonitor always finishes at 100 even after increasing maximum


I have a ProgressMonitor that shows while I process some database tables. The number of tables is not known at first, so I create the ProgressMonitor with a maximum value of 100.

Once processing has begun in the SwingWorker thread, it gets the number of tables and sets the maximum of the ProgressMonitor to the number of tables (about 530 in my test). However, the ProgressMonitor still finishes at 100 and stops the execution of the thread, even though the maximum has increased and the progress bar shows 100/530 accurately.

Any idea why this happens?

The actionListener to start the ProgressMonitor and SwingWorker (named TaskThread) from the button press:

public void actionPerformed(ActionEvent e) 
{
    String cmd = e.getActionCommand();

    if (cmd.equals("generate")) {
        progressMonitor = new ProgressMonitor(this, "Generating...", "", 0, 100);
        task = new TaskThread();
        task.addPropertyChangeListener(this);
        task.execute();
        genButton.setEnabled(false);
    }
}

PropertyChangeListener that updates the ProgressMonitor:

public void propertyChange(PropertyChangeEvent evt) 
{
    if ("progress" == evt.getPropertyName() ) 
    {
        int progress = (Integer) evt.getNewValue();
        progressMonitor.setProgress(progress);
        String message = String.format("Completed %d%%.\n", progress);
        progressMonitor.setNote(message);
        if (progressMonitor.isCanceled() || task.isDone()) 
        {
            Toolkit.getDefaultToolkit().beep();
            if (progressMonitor.isCanceled()) {
                task.cancel(true);
            }
            genButton.setEnabled(true);
        }
    }
}

The SwingWorker class:

class TaskThread extends SwingWorker<Void, Void> 
{
    @Override
    public Void doInBackground() 
    {
        String tableList = tablesArea.getText().trim();
        script = "";
        String filename = outPath.getText

        // Connect to Database
        Connection conn = getDbConnection();
        if (conn == null)
            return null;

        try {
            // if tableList is blank, get all tables from the From Database afm_tbls table
            if (tableList.equals(""))
            {
                // code omitted
            }
        }
        catch (SQLException se) {
            canWriteFile = false;
            handleError(se);
        }

        String[] tables = tableList.split(",");
        generateRecordCount(conn, tables);

        // Close the connection
        if(conn != null)
        {
            try {
                conn.close();
            }
            catch (Exception ignored) {}
        }

        // Write SQL code to a file
        writeScript(filename);

        return null;
    }

    private void generateRecordCount(Connection conn, String[] tables)
    {
        setProgressMax(tables.length);
        setProgress(0);

        // Loop through tables  
        for (int i = 0; i < tables.length; i++)
        {
            // Get record count for each table
            try { 
                String sql = "SELECT COUNT(*) AS reccount FROM " + tables[i];
                Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                ResultSet rs = stmt.executeQuery(sql);
                rs.next();

                int recCount = rs.getInt("reccount");
                if (recCount > 0)
                    script += tables[i] + ": " + recCount + nl;

                // Set progress of SwingWorker, ProgressMonitor is updated by PropertyChangeListener
                int prog = getProgress() + 1;
                setProgress(prog);
            }
            catch(SQLException se)
            {
                handleError(se);
            }
        }
    }
}

Solution

  • I figured out why. So hopefully for someone else's benefit, here is the problem:

    The SwingWorker.setProgress() function has bounds of 0 and 100, so even though the ProgressMonitor can handle higher max values, the SwingWorker thread is ended by an IllegalArgumentException when the value reaches 101.