?

Log in

No account? Create an account

Previous Entry | Next Entry

Очередная статья родилась. Времени на нее я потратил чуть не четыре месяца – было много работы, да и статья обширная, иллюстративных примеров много потребовалось. Статья посвящена внутреннему устройству GUI в Java, а точнее в Swing, ибо AWT, во-первых, устарел, во-вторых, устроен немного по-другому.

В общем, сама статья выложена: http://www.skipy.ru/technics/gui_int.html. Здесь будем ее обсуждать.

Comments

miklegarin
Jan. 16th, 2011 07:19 pm (UTC)
Возможные уточнения/дополнения к статье
Хотел бы, сперва, сказать большое спасибо, ибо даже после 3ех лет плотной работы со Swing'ом нашел кое-что новое и интересное :)


Также хотел бы отметить несколько вещей из Вашей статьи, которые можно было бы уточнить/дополнить...


1) К части про "Области отсечения"

Конечно, оптимизация перерисовки отсечением ненужных частей может являться неотъемлимой частью оптимизации отрисовки, но все же, как мне кажется, clip реже используется в этих целях при написании своих компонентов.

Даже если при отрисовке компонента будет стоять некий ограничивающий clip, все равно все вычисления и вызовы, которые нужны для отрисовки, будут выполнены внутри метода paint(), пока вы сами их не оптимизируете, например, проверками нахождения в видимой области и т.п.
А как показывает практика, чаще проблемы не в скорости отрисовки, а в скорости гор производимых вычислений.
Конечно отрисовкой тоже не стоит пренебрегать, но это немного другое...

По своему недавнему опыту могу сказать, что пара "неудачных" методов по вычислению места, где должна отрисоваться та или иная часть компонента, по времени исполнения перекрывают в сотни раз саму отрисовку.

Как мне кажется, clip чаще используется в двух следующих случаях:

- Стандартный clip, обрезающий отрисовку по краям компонента
В данном случае от разработчика ничего не требуется, кроме как передать управление super.paint() в начале отрисовки для установки оным стандартного clip'а

- Свой clip, необходимый для корректной отрисовки содержимого
Например если необходимо внутри компонента ограничивать отрисовки неких внутренних частей.
Главное при этом не забывать, что при отрисовке устанавливается всего 1 clip и можно нечаянно выйти за границы самого компонента, установив свой "внутренний" clip.

Но это, все же, сугубо мое личное мнение.


2) "DebugGraphics.BUFFERED_OPTION – создает отдельное окно и показывает в нем отрисовку, проводимую на буфере компоненты. Полезно при включенной буферизации. Если честно, мне не удалось включить этот режим."

Как-то давно тоже удивился, что данная опция вообще ничего не делает. Т.е. фактически - не работает.

Также на паре ресурсов по Java находил заметки на эту тему:

DebugGraphics.BUFFERED_OPTION: This is supposed to pop up a frame showing rendering as it occurs in the offscreen buffer if double-buffereing is enabled. As of the Java 2 FCS this option is not functional.


3) К части статьи - "Прозрачность компонент и смысл свойства opaque"

Я бы добавил, что opaque=true, конечно хорошо, но у него есть и обратная сторона медали.
Такая непрозрачность может сильно осложнить написание/отладку компонентов, которые могут динамически перерисовываться со временем, вне зависимости от действий пользователя.

Самым ярким примером (из доступных) являются 2 перекрывающие друг друга кнопки с установленным нативным Windows LnF в ОС WindowsVista/Windows7. Они имеют вредную привычку "моргать" при наличии фокуса.
Если их расположить друг поверх друга на панели (например) с null лэйаутом и сделать непрозрачными (setOpaque(true)), то после пары переключений/наведений минусы проявят себя во всей красе :)

Этот случай конечно немного наигранный, но он самый простой.
Я уже встречал и более сложные моменты, когда после нескольких часов мучений и гор "ужастного" кода все решалось простой установкой opaque в false (и далее, если надо, ручным отрисовыванием фона компонента).


P.S. Из того, что я отметил, вроде все :)
Было бы интересно интересно почитать схожие статьи непосредственно про производительность при отрисовке, а точнее, что-то вроде такого списка:
- Частые ошибки, приводящие к потере производительности при работе с Graphics/Graphics2D в Java
- Возможные пути оптимизации отрисовки
- Сравнения производительности разных методов Graphics/Graphics2D
- Производительность отрисовки Swing-компонентов
- Более подробное описание различий paint/paintAll/print/printAll
Возможно еще что-то в этом духе... Это то, что первое пришло в голову
miklegarin
Jan. 17th, 2011 10:08 am (UTC)
Re: Возможные уточнения/дополнения к статье
Да, тут вспомнилась еще 1 вещь...

4) "paintComponent – этот метод позволяет отрисовать саму компоненту. Т.е. делает то, что в AWT делал paint(Graphics). Именно этот метод необходимо переопределять для того, чтобы отрисовать что-то на компоненте. Можно, конечно, переопределить и paint(Graphics) – а те, кто начинал с AWT, часто этим грешат! – но тогда при использовании рамок (border) начнутся сложности."

Тут также важно понимать то, что метод paintComponent зачастую вызывается при частичных перерисовках компонента с разными указанными clip'ами. Также он может быть и вовсе не вызван, если перерисовываемая часть полностью закрыта opaque компонентами.
Метод же paint будет вызываться всегда при "возможной" необходимости перерисовки (будь то перекрытие другим компонентом, ресайз или что еще). Таким образом не всегда paintComponent лучше в использовании.
Тем более в сложном графическом компоненте использование его, а не paint может породить различные проблемы с перерисовкой частей.
Но для простых компонентов, когда нет смысла/времени заморачиваться с оптимизацией - да, paintCompomponent однозначно более удачный выбор.


5) Еще одно замечание к тому же paintComponent...

После части статьи про отрисовку и рамки создается немного двойственное ощущение, что использование метода paintComponent решает проблему с рамкой, т.е. (например) делает за вас отступы и подгоняет размеры (прямо, естественно об этом не говорится, но нет и обратного).
Даже лишний раз проверил реализацию метода paint/paintComponent, чтобы удостовериться, что я все еще в себе :)

Думаю, тут стоит еще раз напомнить, что замена paintComponent (вместо paint) решает проблему с отрисовкой бордера, а не с отступами, создаваемыми бордером.
skipy_ru
Feb. 14th, 2011 01:40 pm (UTC)
Re: Возможные уточнения/дополнения к статье
Добрый день!

Спасибо за комментарии, обстоятельно. В принципе, со всем согласен. Если соберусь пересматривать/дополнять, возможно, что-то добавлю в статью. А пока – Вы очень хорошо всё это изложили и без меня, а ссылка на это обсуждение в статье есть.

Касательно исследований производительности и т.п. - явно не сейчас. Мне на ответ найти времени - месяц понадобился.
miklegarin
Feb. 14th, 2011 02:18 pm (UTC)
Re: Возможные уточнения/дополнения к статье
Ну, с кое-чем из моих замечаний (думаю) можно было бы и поспорить, как мне уже сейчас кажется...

Касательно исследований производительности и т.п. - явно не сейчас. Мне на ответ найти времени - месяц понадобился.
Это само собой, просто тема мало где затронута (если вообще не проигнорирована) и хотелось бы побольше накопать в этом направлении.
Также, если интересно или нужно - могу позднее собрать некоторую долю материала по этой теме из того, что удалось самому найти/узнать на собственных ошибках при написании крупного приложения для прототипирования (фактически - сплошная работа с графикой).

В любом случае еще раз спасибо за содержательную статью!
Буду ждать продолжения :)