Как избежать Swing объединения запросов repaint()?
Swing обычно объединяет несколько запросов repaint(), чтобы вызвать метод paintComponent() только один раз и, таким образом, повысить производительность. Обычно это то, что вы хотите.
Однако в моем приложении это нежелательно. Мой компонент - большой экран, полный текста (как текстовый редактор). Каждый символ включает в себя такие атрибуты, как цвет переднего плана / фона и стили (например, BOLD). Перекрашивание всего экрана (что по умолчанию выполняет repaint(()) - это дорогостоящая операция, которая вносит ненужную задержку при обновлении только нескольких разрозненных символов на экране.
Поэтому я вызываю repaint(x, y, width, height) несколько раз, но только для тех областей, которые фактически изменились (обычно 50 символов или менее, которые могут быть разбросаны по экрану в двух или трех отдельных смежных областях).,
Проблема в том, что обычно меняются символы в верхней и нижней части экрана. Я вызываю repaint для каждой из затронутых областей, но Swing объединяет мои множественные запросы repaint(...) в один запрос repaint(...) (это поведение по умолчанию), вычисляя объединение областей, которые нужно перекрасить. Это приводит к единственному вызову paintComponent(), но с большим прямоугольником отсечения (как возвращается getClipBounds()), который охватывает все области, которые должны быть обновлены. Таким образом, я в любом случае перекрашиваю большую область экрана (основываясь на ClipBounds), что непродуктивно и чего я хочу избежать, так как только небольшая часть экрана была фактически изменена и, следовательно, должна быть изменена. перекрасили.
Вопрос: есть ли способ смягчить это поведение, чтобы мой метод paintComponent() перекрашивал только те области, которые были изменены, и избегал ненужного перекрашивания неизмененных областей?
Дополнительные детали в соответствии с просьбой:
Класс является производным от JComponent. По сути, это просто "пустое" окно, в котором я рисую текстовые символы с помощью API Swing. Максимальный размер окна составляет около 83 строк на 320 столбцов на строку (это на дисплее Apple Cinema), поэтому для шрифта 8x16 это 2560x1328.
По сути, приложение представляет собой текстовый редактор (подумайте: vi). Нижняя строка дисплея - это строка состояния. В худшем случае я мог бы переместить курсор на одну позицию вправо вверху окна. Это приведет к обновлению строки состояния в нижней части окна, чтобы отразить новую позицию курсора (строка, столбец). Итак, у нас есть несколько мест, которые меняются в верхней части окна, и несколько мест, которые меняются в нижней части окна. Я бы выдал 2 запроса на перерисовку (...), по одному для каждой измененной области окна. Однако repaint() объединит эти два запроса и вызовет paintComponent() один раз с ограничительным прямоугольником (который определяет область, которую нужно перекрасить), которая является объединением двух областей, которые были фактически обновлены. Результирующий прямоугольник будет очень большим, простираясь от вершины окна до низа. Таким образом, в paintComponent() я перекрасил большую часть экрана, даже подумав, что подавляющее большинство его не было изменено. Вот чего я пытаюсь избежать.
1 ответ
Есть ли способ смягчить это поведение, так что мой метод paintComponent() перерисовывает только те области, которые были изменены,
Вы можете попробовать использовать paintImmediately(...)
метод JComponent
учебный класс.
Это приведет к тому, что сразу несколько небольших запросов на рисование будут выполняться без RepaintManager
, Только вы можете решить, что несколько небольших запросов работают лучше, чем один больший запрос рисования.