SwingWorker блокирует графический интерфейс при (неудачном) обновлении JLabel Icon - PullRequest
3 голосов
/ 01 июля 2011

Хорошо, я действительно борюсь с разблокировкой моего графического интерфейса, который заблокирован из-за отдельного потока SwingWorker. В основном то, что делает моя программа: Инициализирует веб-камеру, а затем захватывает один кадр и отображает его в виде значка JLabel (выполнение однократного захвата + отображение при нажатии кнопки очень просто, однако у меня возникают огромные трудности при последовательном выполнении такой операции для выполнения некоторой обработки изображений) , Я стремлюсь получить такой результат:

Захватить кадр -> обработать его -> отобразить как ImageIcon of Jlabel> ... повторить Захватить кадр> ...

Мне нужны результаты при потоковой веб-камере, поэтому я использовал SwingWorker publish и process. В моем коде «обработка части» не включена, так как в этом нет необходимости, поскольку я не могу даже получить надлежащий непрерывный захват кадров. Вообще мой фоновый поток никогда не закончится, если не будет отменен (хорошо, это предположение, поскольку я хочу обрабатывать изображения максимально быстро с максимальным количеством кадров в секунду - если я не должен делать это по-другому?) Я предполагаю, что отдельный поток для захвата и обработки одного кадра будет плохим идея из-за того, что я стремлюсь получить 10+ FPS). Я знаю, что мой поток SwingWorker работает, так как я провел тесты сохранения последовательных изображений на C: \, и это сработало, но мой графический интерфейс в любом случае заблокирован, но по крайней мере я знаю, что поток работает и захватывает фреймы.

Обычно у меня есть 2 проблемы:

  • без обновления значка JLabel
  • Заблокированный графический интерфейс

Мой код SwingWorker:

private class FrameStream extends SwingWorker<Void, BufferedImage> { 
    @Override
    protected Void doInBackground() throws InterruptedException{
        BufferedImage processedImage = null;

        while (!isCancelled()) {
            processedImage = getPIC_COLOR(player);
            publish(processedImage);

            Thread.sleep(5000); // i made such delay to check whether program is not "choking" with data, but its not the case, without this delay everthing is the same
        }            
        return null;
    }

    @Override
    protected void process(List<BufferedImage> mystuff) {
        Iterator it = mystuff.iterator(); 

        while (it.hasNext()) {
            img_field.setIcon(new ImageIcon(mystuff.get(mystuff.size()-1)));
        }
    }

    @Override
    protected void done() {            
        infoBAR.setText("FINISHED");
    }
}

Я настолько отчаялся, что переписал свой код полностью на примере учебного пособия: Flipper , как вы можете видеть, это смехотворно похоже. Все мои предыдущие усилия также заблокировали графический интерфейс, поэтому попробовал «учебный путь», тем не менее, он не сработал, что очень жаль. Я в тупике, потому что понятия не имею, как это исправить. Я отчаянно нуждаюсь в помощи, поскольку, как вы можете видеть, она выглядит точно так же, как учебная, возможно, что-то иное вызывает проблемы: МОЙ ПОЛНЫЙ КОД

Пожалуйста, помогите, я не могу решить это самостоятельно.

Ответы [ 4 ]

4 голосов
/ 01 июля 2011

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

  @Override
  protected void process(List<BufferedImage> mystuff) {
     for (BufferedImage bImage : mystuff) {
        img_field.setIcon(new ImageIcon(bImage));
     }
  }

Я не уверен, что это будет иметь существенное значение, но я верю, что именно так должен быть написан процесс. Еще одна мысль - если BufferedImages большие, вы можете создать ImageIcon в фоновом потоке и опубликовать ImageIcon, а не BufferedImage.

3 голосов
/ 01 июля 2011

Ничто не выделяется как проблема. Шаги, которые я бы предложил для дальнейшей отладки.

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

Во-вторых, поскольку ваш графический интерфейс заблокирован, в EDT все еще что-то происходит. Попробуйте запустить профилировщик или добавить System.out.println в свой код, чтобы узнать, что работает, пока графический интерфейс заблокирован.

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

1 голос
/ 01 июля 2011

хммммм, если я прочитал ваше последнее сообщение об этой проблеме, возможно, есть много возможных ошибок (и я вижу ваш код), это не имеет ничего общего с SwingWorker , другим пример просто замените изменение цвета для JButton # setBackground () на ваш значок или ImageIcon

0 голосов
/ 01 июля 2011

Вы пытались установить метку для наблюдения значка изображения?

icon.setImageObserver(label);
...