Я заметил, что это обычное дело. Например, его используют DefaultListCellRenderer, DefaultTableCellRenderer и DefaultTreeCellRenderer. Кроме того, многие пользовательские рендереры ячеек, которые я вижу в Интернете, также используют это. Я хочу использовать собственный TableCellRenderer в своем коде, но я не уверен, действительно ли мне нужно создать подкласс JLabel. В чем преимущество подкласса JLabel?
Почему средства визуализации ячеек часто расширяют JLabel?
Ответы (3)
В API для DefaultTableCellRenderer указано:
Класс таблицы определяет средство визуализации одной ячейки и использует его в качестве штампа для визуализации всех ячеек в таблице; он отображает первую ячейку, изменяет содержимое средства визуализации этой ячейки, сдвигает начало координат в новое место, перерисовывает ее и т. д. Стандартный компонент
JLabel
не предназначен для использования таким образом, и мы хотим избежать запускаrevalidate
каждый раз, когда ячейка рисуется. Это значительно снизит производительность, поскольку сообщениеrevalidate
будет передано вверх по иерархии контейнера, чтобы определить, будут ли затронуты какие-либо другие компоненты. Поскольку рендерер создается только на время жизни операции рисования, мы также хотим избежать накладных расходов, связанных с прохождением иерархии для операций рисования. Таким образом, этот класс переопределяет методыvalidate
,invalidate
,revalidate
,repaint
иfirePropertyChange
, чтобы они были неоперативными, и переопределяет методisOpaque
исключительно для повышения производительности. Если вы пишете свой собственный рендерер, помните об этом соображении производительности.
JLabel обладает всей огневой мощью, которая им нужна, а затем и некоторыми — он обрабатывает текст и значки, может центрировать себя, у него по умолчанию непрозрачный фон.... и я мог бы продолжать и продолжать...
Потому что каждый — даже ранняя команда Swing — имеет право время от времени делать что-то не так :-)
И неправильно расширять компонент вместо того, чтобы реализовать интерфейс рендерера и позволить этой реализации делегировать компоненту (который может быть специально реализованным JLabel со всеми свистками, которые они считают необходимыми, лично я я не уверен). Мы все еще страдаем от этого плохого решения по реализации — зловещая «цветовая память» DefaultTableCellRenderer является прямым следствием.
Итак: Не делайте подклассов некоторых компонентов для реализации некоторых Renderer. Тем более не для someComponent == DefaultTableCellRenderer, он сломан!
Кстати, SwingX делает это правильно :-)