Основное неопределенное использование панели JProgress

Я просто хочу иметь неопределенную анимацию JProgressBar в левом нижнем углу моего кадра, когда выполняется длинная загрузка.

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

Мне нужна помощь, чтобы узнать, куда поместить мой вызов download().

class MyFunClass extends JFrame {
  JProgressBar progressBar = new JProgressBar();

  public void buttonClicked() {
    progressBar.setVisible(true);
    progressBar.setIndeterminate(true);

    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        progressBar.setIndeterminate(true);
        progressBar.setVisible(true);

        // Do I do my download() in here??

    }});

    // Do download() here???
    progressBar.setVisible(false);
  }
}

Заранее спасибо!



Решение

Редактировать: Для тех, у кого в будущем возникнет такая же проблема, как у меня, это базовое решение основной проблемы. Это не мой код дословно, а общий набросок. Внутри buttonClicked():

public void buttonClicked() {
  class MyWorker extends SwingWorker(String, Object) {
     protected String doInBackground() {
       progressBar.setVisible(true);
       progressBar.setIndeterminate(true);

       // Do my downloading code
       return "Done."
     }

     protected void done() {
        progressBar.setVisible(false)
     }
  }

  new MyWorker().execute();

}

person Bill VB    schedule 04.05.2012    source источник
comment
Вам следует взглянуть на docs.oracle.com/javase/tutorial/ uiswing/components/, хотя это кажется сложным. Что вам нужно сделать, так это запустить загрузку в другом потоке (backgroundworker). Затем основной поток (gui) выполняет анимацию progressBar. То, как вы это делаете, на самом деле наоборот.   -  person user845279    schedule 04.05.2012
comment
См. Редактировать 2 к моему ответу, чтобы исправить некоторые проблемы.   -  person Hovercraft Full Of Eels    schedule 04.05.2012


Ответы (1)


Ваш текущий код не показывает создание фонового потока, а скорее показывает, что вы пытаетесь поставить код в очередь в потоке Swing изнутри потока Swing, что не имеет смысла для эту проблему (хотя иногда вы можете захотеть это сделать, но опять же, не здесь). Единственный способ добиться успеха — использовать фоновый поток. Стандартный Oracle учебник JProgressBar и Параллелизм в Swing проходит через все это.

Основная вещь заключается в том, что вы должны обновить JProgressBar из потока Swing, который будет выполнять ваш длительный процесс в фоновом потоке, например, предоставляемый объектом SwingWorker. У нас слишком много деталей, чтобы мы могли рассмотреть их все здесь, поэтому все, что я могу сделать, это предоставить ссылку, но мы будем рады помочь вам разобраться в деталях после того, как вы ознакомитесь с учебными пособиями. Просто ознакомьтесь с учебными пособиями и вернитесь с конкретными вопросами, если вы все еще застряли.

Изменить 1
Вы указываете:

Могу ли я просто создать новый объект потока в функции buttonClicked()?

Да, вы можете создать объект SwingWorker внутри buttonClicked() метода и выполнить его там.

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

Извините, но я понятия не имею, о чем вы говорите и какие проблемы, по вашему мнению, вызовет многопоточность. Метод buttonClicked(), скорее всего, должен выполняться в EDT, а не в фоновом потоке.

Также обратите внимание, что в большинстве моих более сложных графических интерфейсов Swing я часто выполняю загрузку файлов в другом объекте (модели) и создаю свой SwingWorker в другом объекте (элемент управления) из объекта графического интерфейса (представление). Такой способ может показаться более сложным, но намного проще отлаживать, поддерживать и улучшать мою программу, когда я делаю это таким образом, особенно когда я интенсивно использую интерфейсы, чтобы я мог тестировать все компоненты программы изолированно.

Редактировать 2
Некоторые исправления в сообщении о решении. Вы опубликовали:

public void buttonClicked() {
  class MyWorker extends SwingWorker(String, Object) {
     protected String runInBackground() {
       progressBar.setVisible(true);
       progressBar.setIndeterminate(true);

       // ...

у которого есть проблемы

  • это doInBackground(), а не runInBackground()
  • но что более важно, вы выполняете вызовы Swing из фонового потока, чего никогда не следует делать (если вызов не является потокобезопасным, и даже тогда...).

Итак, измените его:

public void buttonClicked() {
  progressBar.setVisible(true);
  progressBar.setIndeterminate(true);
  class MyWorker extends SwingWorker<String, Void> {
     protected String doInBackground() {

       // ...
person Hovercraft Full Of Eels    schedule 04.05.2012
comment
Могу ли я просто создать новый объект потока в функции buttonClicked()? Дело в том, что у меня есть свой API и библиотека всех функций, для которых я разрабатываю графический интерфейс, и кажется, что обходной путь заключается в том, чтобы обернуть вызов этой функции в поток. - person Bill VB; 04.05.2012
comment
Спасибо за ваше время до сих пор. Я согласен с этим подходом и отмечу принятый ответ, как только у меня это заработает. Немного расстраивает то, что создание простого графического интерфейса для моей в остальном хорошо сконструированной библиотеки протоколов требует гораздо больше времени и кода, чем я думал изначально. - person Bill VB; 04.05.2012
comment
@B.VB: разочаровывает, да, но неизбежно на любом языке. Вы не можете наступать на поток, который взаимодействует с пользователем или отрисовывает графический интерфейс, если вы хотите, чтобы ваш графический интерфейс оставался отзывчивым, и поэтому фоновые потоки для этих ситуаций являются обязательными. - person Hovercraft Full Of Eels; 04.05.2012