Как совместить перекрашивание в Swing? - PullRequest
3 голосов
/ 10 августа 2009

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

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

Почему меня это волнует? Потому что мой код рисования очень тяжелый, и я не могу полностью перерисовать при очень высоком FPS.

Ответы [ 5 ]

2 голосов
/ 10 августа 2009

Частые запросы на перекрашивание автоматически объединяются в один. Лучший способ оптимизировать это - не перерисовывать все это, а вызывать перерисовку с координатами определенной области. Это означает, что вы перекрашиваете только ту область, которая действительно изменилась.

2 голосов
/ 10 августа 2009

Swing объединит для вас перекраску: см. «Рисование в AWT и Swing» на веб-сайте Sun. Если вы запланируете несколько перерисовок в быстрой последовательности, они будут объединены в один вызов paintImmediately ().

1 голос
/ 10 августа 2009

Насколько я понимаю, repaint() просто планирует перерисовку, добавляя область компонента в очередь перерисовки. Если для компонента уже было запрошено перекрашивание, новый регион перерисовки будет просто объединен с ранее запрошенными регионами. Перекраска фактически не выполняется до тех пор, пока не будут обработаны все другие события в очереди событий. Таким образом, ваши дополнительные перерисовки могут не иметь большого значения, то есть ваш код рисования будет выполнен только один раз. См. JComponent.repaint и RepaintManager.addDirtyregion .

0 голосов
/ 14 августа 2009

Я слышу, что вы говорите. Вы действительно можете перекрасить только часть области. В «Выполнении пользовательских примеров рисования» на веб-сайте Sun я нашел полезный пример, который показывает, как рисовать перетаскиваемый прямоугольник, а затем перекрашивать эту область только при движении или отпускании мыши.

Вот соответствующий раздел кода ...

public void mouseDragged(MouseEvent e) {
            updateSize(e);
        }

        public void mouseReleased(MouseEvent e) {
            updateSize(e);
        }

        /* 
         * Update the size of the current rectangle
         * and call repaint.  Because currentRect
         * always has the same origin, translate it
         * if the width or height is negative.
         * 
         * For efficiency (though
         * that isn't an issue for this program),
         * specify the painting region using arguments
         * to the repaint() call.
         * 
         */
        void updateSize(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            currentRect.setSize(x - currentRect.x,
                                y - currentRect.y);
            updateDrawableRect(getWidth(), getHeight());
            Rectangle totalRepaint = rectToDraw.union(previousRectDrawn);
            repaint(totalRepaint.x, totalRepaint.y,
                    totalRepaint.width, totalRepaint.height);
        }

Этот код защищен авторским правом (полный код и уведомление об авторских правах см. Здесь )

См. здесь для дальнейших примеров списков

По правде говоря, у меня похожая проблема с FPS, но это может быть связано с моим в настоящее время плохим кодом! За последние несколько месяцев я многому научился, и теперь я могу сделать свой код более эффективным. Надеюсь, я смогу преодолеть проблему с FPS, когда более 2 «людей» замедляют мою графику! Hummmm ... Я только что реализовал приведенный выше код для того же раздела в своем коде, но не для других, но обязательно попробуй!

0 голосов
/ 10 августа 2009

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

По существу я делаю следующее:

  • Создать ScheduledExecutorService как поле в классе
  • Получите первый запрос на перерисовку и и submit отправьте его исполнителю для запуска на EDT, скажем, за 50 мс, возвращая будущее
  • Получить второй запрос - проверить, завершена ли предыдущая перекраска (fut.isDone()) и, если да, запланировать следующую перерисовку; иначе ничего не делать.

Таким образом, вы должны получать не более 20 запросов на перерисовку в секунду.

Я сделал аналогичные вещи для пакетирования количества вызовов до fireDataTableChanged, когда одновременно происходит множество изменений.

...