开发者

JButton stays in pressed state

In my Java GUI app I have a JButton and when clicked it calls a function to connect to a database, then calls a function to clear a table in the DB, then calls a function that reads text from one file and loads variables, which calls a function that reads text from another file, compares the data from both and then calls a function to either update or insert data in the DB, all of that works fine.

However my question is related to the JButton, when its clicked I want to run a Indeterminate progress bar just so the user knows work is being done and then right before it leaves the the action listener setIndeterminate to false and set the value of the progress bar to 100(complete), but in my case when you click the button it stays in the clicked state and the progress bar freezes.

What should I implement to prevent this? threading possibly? but Im quite new to threading in java. here is my action listener:

    private class buttonListener implements ActionListener
        {
            public void actionPerformed(ActionEvent e)
            {
                if( e.getSource() == genButton )
                {
                    progressBar.setIndeterminate(true);
                    progressBar.setString(null);
                    try 
                    {
                        dbConnect(); //connects to DB
                        clearSchedules(); // deletes data in tables
                        readFile(); // reads first file and calls the other functions
                        dbClose();// closes the DB
                        progressBar.setIndeterminate(false);
                        progressBar.setValue(100);
                    } 
                    catch (Exception e1){
                        System.err.println("Error: " + e1.getMessage());
                    }
                }
            }
        }开发者_如何学Python

On a side note, I would like to have the action bar actually move as the the program progresses but I wasnt sure how to monitor its progress.

Thanks, Beef.

UPDATE here is my example of SwingWorker and how I used it:

Declared globally

 private functionWorker task;


    private abstract class functionWorker extends SwingWorker { 

        public void execute() {
            try {
                dbConnect();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            clearSchedules();
            try {
                readFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            dbClose();
        }
    }

Inside my actionPerformed method

if( e.getSource() == genButton )
            {

                progressBar.setIndeterminate(true);
                progressBar.setString(null);
                try 
                {
                    task.execute();

                    progressBar.setIndeterminate(false);
                    progressBar.setValue(100);
                } 
                catch (Exception e1){
                    System.err.println("Error: " + e1.getMessage());
                }
            }


The problem is probably related to connecting to doing expensive operations in the UI thread (connecting to a database, reading from a file, calling other functions). Under no circumstances should you call code that uses excessive CPU time from the UI thread, as the entire interface can't proceed while it is executing your code, and it results in a 'dead' looking application, with components remaining in their state at the time before an expensive operation until completion. You should execute another thread, do the expensive work in that, and then use a SwingUtilities.invokeLater(Runnable doRun) with a passed runnable where you'd update the progress.

There may be synchronisation issues relating to the states of components, but you can fix these later.


Could I create the new thread when the action is performed and call the new functions in the thread, or should I do the threading within the actual function itself?

You can start a SwingWorker from your button's handler, as shown here. A related example implementing Runnable is seen here.


One method to handle progressbars are to extend SwingWorker in a class. SwingWorker takes care of running background tasks for you and so you do not have to implement your own threading that can end up in unknown issues. To begin with, your class that takes care of progress bar UI should implement PropertyChangeListener And implement public void propertyChange(PropertyChangeEvent evt) { - to update the progressbar status based on a global variable.

The background task class should look like the following(this could be an inner class) :

class ProgressTask extends SwingWorker<Void, Void> {
        @Override
        public Void doInBackground() {
             //handle your tasks here
             //update global variable to indicate task status.
        }
        @Override
        public void done() {
             //re-enabled your button
        }
}

on your button's event listener :

 public void actionPerformed(ActionEvent evt) {
    //disable your button
    //Create new instance of "ProgressTask"
    //make the task listen to progress changes by task.addPropertyChangeListener(this);
    //calll task.execute();
 }

I have tried to water down code example, you would have to read some tutorial to understand how all these pieces fit together. However, the main point is do not code your Threads, instead use SwingWorker


                    progressBar.setIndeterminate(true);
                    progressBar.setValue(0);                        
dbConnect(); //connects to DB
                    progressBar.setIndeterminate(true);
                    progressBar.setValue(10);
                    clearSchedules(); // deletes data in tables
                    progressBar.setIndeterminate(true);
                    progressBar.setValue(50);
                    readFile(); // reads first file and calls the other functions
                    progressBar.setIndeterminate(true);
                    progressBar.setValue(75);
                    dbClose();// closes the DB
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(100);

You will need to tell the progress bar how much progress has been made because it does not know the percentage completed. Better yet, write a method that updates and repaints the progress bar rather than repeating the method calls here.

updateProgressBar(int progress, boolean isDeterminate, String msg){};

You will also need to make sure that your specific button is firing the action performed.

class IvjEventHandler implements java.awt.event.ActionListener {
        public void actionPerformed(java.awt.event.ActionEvent e) {
            if (e.getSource() == JMyPanel.this.getJButtonUpdate()) 
                connEtoC1(e);
    };
};

The connEtoC1(e); should execute a controller class or SwingWorker rather than firing from the GUI

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜