JButton остается в нажатом состоянии - PullRequest
4 голосов
/ 23 сентября 2011

В моем приложении Java GUI у меня есть JButton, и при нажатии он вызывает function для подключения к database, а затем вызывает function до clear a table в DB затем вызывает function, который читает текст из одного файла и загружает variables, который вызывает function, который читает текст из другого файла, сравнивает data из обоих файлов и затем вызывает function с любым из них update или insert данные в БД, все это прекрасно работает.

Однако мой вопрос связан с JButton, когда его щелкнули, я хочу запустить Indeterminate progress bar только для того, чтобы пользователь знал, что работа выполняется, а затем прямо перед тем, как он покинул action listener setIndeterminate to false и установил значение от progress bar до 100(complete), но в моем случае, когда вы нажимаете button, он остается в нажатом состоянии, а progress bar останавливается.

Что я должен реализовать, чтобы предотвратить это? возможно нарезка резьбы? но я новичок в потоках в Java. вот мой слушатель действий:

    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());
                    }
                }
            }
        }

Кстати, я бы хотел, чтобы панель действий фактически двигалась по мере продвижения программы, но я не был уверен, как следить за ее ходом.

Спасибо, Говядина.

ОБНОВЛЕНИЕ Вот мой пример SwingWorker и как я его использовал:

Объявлено глобально

 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();
        }
    }

Внутри моего действия Выполненный метод

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());
                }
            }

Ответы [ 4 ]

7 голосов
/ 23 сентября 2011

Проблема, вероятно, связана с подключением к выполнению дорогостоящих операций в потоке пользовательского интерфейса (подключение к базе данных, чтение из файла, вызов других функций).Ни при каких обстоятельствах не следует вызывать код, который использует чрезмерное время ЦП, из потока пользовательского интерфейса, поскольку весь интерфейс не может продолжить работу, пока он выполняет ваш код, и это приводит к «мертвому» виду приложения, при этом компоненты остаются в своем состоянии вВремя до дорогой операции до завершения.Вы должны выполнить другой поток, выполнить дорогостоящую работу в этом направлении, а затем использовать SwingUtilities.invokeLater(Runnable doRun) с переданным runnable, где вы будете обновлять ход выполнения.

Могут быть проблемы с синхронизацией, связанные с состояниями компонентовно вы можете исправить это позже.

6 голосов
/ 23 сентября 2011

Могу ли я создать новый поток при выполнении действия и вызвать новые функции в потоке, или я должен выполнить поток внутри самой функции?

Вы можете начатьSwingWorker из обработчика вашей кнопки, как показано здесь .Смежный пример реализации Runnable виден здесь .

5 голосов
/ 23 сентября 2011

Один метод для работы с индикаторами прогресса - это расширение SwingWorker в классе. SwingWorker берет на себя выполнение фоновых задач, поэтому вам не нужно реализовывать собственные потоки, которые могут привести к неизвестным проблемам. Начнем с того, что ваш класс, который заботится о пользовательском интерфейсе индикатора выполнения, должен реализовать PropertyChangeListener И внедрить public void propertyChange(PropertyChangeEvent evt) { - обновить статус индикатора выполнения на основе глобальной переменной.

Класс фоновой задачи должен выглядеть следующим образом (это может быть внутренний класс):

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
        }
}

в обработчике событий вашей кнопки:

 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();
 }

Я попытался описать пример кода, вам нужно прочитать какое-то руководство, чтобы понять, как все эти части сочетаются друг с другом. Однако главное - не кодируйте свои потоки, вместо этого используйте SwingWorker

0 голосов
/ 23 сентября 2011
                    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);

Вам нужно будет указать индикатор выполнения, какой прогресс был достигнут, потому что он не знает процент выполнения.Еще лучше написать метод, который обновляет и перерисовывает индикатор выполнения, а не повторяет вызовы методов здесь.

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

Вам также необходимо убедиться, что ваша кнопка запускает выполненное действие.

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);следует выполнять класс контроллера или SwingWorker, а не запускать из GUI

...