Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > robot в не EDT потоке


Автор: Mirkes 5.9.2012, 12:37
Из модального диалога запускается поток, который производит следующую процедуру:
1. По некоему алгоритму нечто отрисовывает в окне основной программы
2. Пытается снять получившуюся картинку с помощью робота.

В результате я получаю вместо кратинок пустые файлы, исключений не возникает. 
Система Windows7

вот фрагмент кода

Код

                        pane.setCSteps(i); \\ Команда отрисовать. Исполнитель упаковывает ее как положено (Следующий фрагмент кода)
                        try {
                            Robot r = new Robot();
                            BufferedImage buf = r.createScreenCapture(new Rectangle(sour.getLocationOnScreen(), sour.getSize()));
                            ImageIO.write(buf, ext, new File(fileName+"-"+cc+ext));
                        } catch (IOException f) {
                            System.out.println(f.getMessage());
                        } catch (AWTException e) {
                            System.out.println(e.getMessage());
                        }



Вот код команды на отрисовку

Код

    public void setCSteps(int step) {
        cSteps = step;
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ready = true;
                drawState();   \\ собственно рисующая программа
                ready = false;
            }
        });
    }


Я не понимаю что происходит. Сообщений об исключениях нет. Рисование вроде происходит, но слишком быстро. А файлы на выходе пустые. 
Подскажите куда смотреть?

Автор: jk1 5.9.2012, 14:19
А где гарантия что на момент снятия скриншота все уже отрисовалось? Из кода этого не видно

Автор: Mirkes 5.9.2012, 16:26
Гарантии пока нет. Но там что-то точно было, а файлов нет совсем. Пусть будет пока не то, что мне нужно, но ведь нет совсем ничего. Вот что меня напрягает.

Автор: jk1 6.9.2012, 10:57
Результат и правда странный.
Я бы попробовал зашедулить вызов робота также на EDT, причем использовать в обоих случаях не invokeLater, а invokeAndWait.
Так вызов будет синхронным.

Автор: Mirkes 6.9.2012, 22:25
С отсутствием файла разобрался - не правильно передавал расширение.
Однако проблема состоит даже не в отрисовке, а в принципиальной возможности применения робота.
Существует три сущности.
1. Основное окно программы, в котором что-то рисуется.
2. Модальный диалог, который запускает поток отрисовки и снятия изображений.
3. Собственно тот поток, который передает команду главной форме отрисоваться, а потом вызывает робота для снятия изображения.

Допустим поток (3) может поймать момент завершения отрисовки. При запуске робота в файл выгружается изображение модального диалога, перекрывающее нужный компонент. 

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

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

В Delphi каждый компонент имеет TCanvas, с которого всегда можно считать изображение, даже если компонент не виден на экране. Неужели в Java нет ничего подобного?

Нашел набросок http://www.javatalks.ru/sutra101769.php. Пока не проверил.

Автор: Mirkes 7.9.2012, 08:15
Проблема разрешилась.
Для тех, кто столкнется с аналогичной задачей привожу описание фрагмента, который работает даже в случае закрытого компонента - как в моем случае когда компонент был перекрыт модальным диалогом.
Код

       SwingUtilities.invokeAndWait(new Runnable() {  // Необходимо, если задача отрисовки и считывания запускается не из потока
               public void run() {                                        // EDT. Я запускал не из него
                     pane.setCStepSimpl(currStep);                 // некое конфигурирование компонента для отрисовки
                      // Создем BufferedImage нужных размеров и типа. deskTop - тот компонент, изображение которого я хотел считать
                      bI = new BufferedImage(deskTop.getWidth(), deskTop.getHeight(), BufferedImage.TYPE_INT_ARGB);
                      Graphics2D g2 = bI.createGraphics();       // вспомогательное необходимое действо
                       deskTop.paint(g2);                                  // А вот это и есть главное - отрисовка компонента в буфере!
                }
       });
       //Write result
       ImageIO.write(bI, "png", new File(fileName)); // теперь делаем с Image то что хотим. Я записал на диск



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

Код

       // Создем BufferedImage нужных размеров и типа. deskTop - тот компонент, изображение которого я хотел считать
       BufferedImage bI = new BufferedImage(deskTop.getWidth(), deskTop.getHeight(), BufferedImage.TYPE_INT_ARGB);
       Graphics2D g2 = bI.createGraphics();       // вспомогательное необходимое действо
       deskTop.paint(g2);                                  // А вот это и есть главное - отрисовка компонента в буфере!
       ImageIO.write(bI, "png", new File(fileName)); // теперь делаем с Image то что хотим. Я записал на диск

Детальное описание работы с рисованием на компонентах приведено http://www.skipy.ru/technics/gui_int.html
Возможно стоит написать статью в FAQ, но он временно не работает.
jk1, а где сейчас складывают такие вещи? А то подобных вопросов я встречал на форуме множество, и решение всегда предлагалось через робота. Хотелось бы закрыть тему (не эту, а получения изображения с компонента).

Автор: jk1 12.9.2012, 10:31
Цитата

jk1, а где сейчас складывают такие вещи? 


Раньше было http://base.vingrad.ru/ , но похоже оно умерло. Так что получается, что некуда.

Автор: Mirkes 17.9.2012, 06:31
При чтении старых цепочек обнаружил ссылку на старый faq, которая сработала!
Может пока новый FAQ мертв, перейти в старый?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)