Как я могу завершить показ прогресса в JTextArea при выполнении кода, который определяет, что отображать в этой JTextArea?

Я не знаю, возможно ли это. Я делаю лотерею и пытаюсь использовать как можно меньше компонентов графического интерфейса. Итак, у меня есть JTextArea, который должен показывать следующее сообщение (например):

"Расчет...55,4%"

Когда я печатаю его на консоль, он показывает нормально, но не печатает его в JTextArea. Я пытался использовать SwingUtilities.invokeLater, но это тоже не работает.

    for (int x = 0; x < daysBetween; x++)
    {
      completion = "Calculating..." + df.format((100 * (x + 1)) / daysBetween) + "%";
      if (!textArea.getText().equals(completion))
      {
        textArea.setText(completion);
      }
      /*
      Here I have a lot of irrelevant code that compares your tickets to the winning tickets and counts your winnings and other statistics...
      */
    }

    ticketReport += "Computation time: " + getElapsedTime(start, System.nanoTime());
    ticketReport += "\nEnd date: " + (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DAY_OF_MONTH) + "/" + cal.get(Calendar.YEAR); 
    ticketReport += "\nTotal # of tickets purchased: " + numOfTicketsPurchased;
    /*
    etc. with filling out the ticket report
    */
    textArea.setText(ticketReport);

Как вы можете догадаться, я хочу, чтобы JTextArea обновлялся, когда я устанавливал текст textArea в цикле for выше. Он не обновляет JTextArea до конца метода, который является самым нижним, когда я устанавливаю текстовую область для отображения отчета о тикете.

http://i63.tinypic.com/2s85j5t.png

МОЯ КОНЕЦНАЯ ЦЕЛЬ: Я хочу в конечном итоге превратить это в приложение для телефона Android, поэтому я не хочу использовать всплывающие окна или что-то еще.

2 ответа

Решение

Мой оригинальный подход к SwingWorker позволил мне показать процент выполнения в JTextArea. Я добавил опцию, чтобы отменить операцию, и когда я попытался отменить, "поток" (SwingWorker) не будет отменить. Когда я отменяю и перезапускаю, он будет постоянно складываться. Каждый последовательный запуск во время работы другого приводил к тому, что вычисления выполнялись все медленнее и медленнее, а затем давали неверную информацию.

То, как я это сделал во второй раз, решило исходную проблему и эту новую проблему. Я создал новый закрытый класс, который расширяет Thread, переопределяет его метод run() и вставил в этот код код, который будет выполняться в потоке. Я заметил, что любой метод остановки потока устарел из-за потенциальных проблем, поэтому я создал логическое значение, которое должно быть установлено, когда пользователь запрашивает остановку потока, и внутри потока оно периодически читает значение логического значения, а затем завершается, когда оно равно к истине.

Я запускаю поток путем повторной инициализации объекта BackgroundCalc и вызова его метода start().

  private class BackgroundCalc extends Thread
  {
    public void run()
    {
      /*
      initializing stuff here
      */
      for (int x = 0; x < daysBetween; x++)
      {
        progress = (100 * (x + 1)) / daysBetween;
        if (destroyCalcThread) return;
        /*
        background calculations here
        */
      }
      /*
      finish up thread here
      */
    }
  }

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

/* РЕДАКТИРОВАТЬ: Это временно решило проблему, но я столкнулся с другой проблемой. Теперь, когда я попытался отменить SwingWorker, вызвав его метод cancel с параметром true, он не отменил. Пожалуйста, посмотрите мой другой ответ, как я решил это. */

Я понял. Вышеописанный метод, который я поместил внутрь SwingWorker, выглядит следующим образом:

      SwingWorker<Void, Void> sw = new SwingWorker<Void, Void>()
      {
        @Override
        protected Void doInBackground() throws Exception
        {
          //method here
        }
      }

Внутри этого метода я вызвал метод setProgress с параметром "(100 * (x + 1)) / daysBetween", чтобы показать правильный% выполнения. Затем после этого я добавил это:

      sw.execute();
      sw.addPropertyChangeListener(new PropertyChangeListener()
      {
        @Override
        public void propertyChange(PropertyChangeEvent arg0)
        {
          textArea.setText("Calculating..." + sw.getProgress() + "%");
          if (sw.getProgress() == 100)
            textArea.setText(ticketReport);
        }
      });

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

Другие вопросы по тегам