Как в JTable установить своего рисовальщика?

Как в JTable установить своего рисовальщика?

Очень просто. Нужно реализовать интерфейс TableSellRenderer, имеюший всего один метод:

public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus, int row, int column)

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

Перейдём к примеру. Работаем в Eclipse.

Содадим новый проект: File->New->Java Project или File->New->Project... и в отрывшемся окне выбираем Java Project, жмём Next. В поле Project Name укажем MyRendEditTable, жмём Finish.

Правой кнопкой по src, в откывшемся меню выбираем New->Package. Имя пакета в поле Name установим myRendEditTable.table.

Правой кнопкой по пакету myRendEditTable.table, выбираем New->Class, в поле Name вводим TableEx и ниже установим флаг public static void main(String[] args), жмём Finish. В окне редактора видим код нашего класса и в виде Package Explorer появился узел класса TableEx.java. Изменим созданный мастером код класса TableEx.java так:

Посмотрим, что получилось: правой кнопкой по классу TableEx -> Run As -> Java Application, Получаем: JTable установить своего рисовальщика

Сейчас ячейки таблицы прорисованы рисовальщиками, установленными в класс JTable по умолчанию. Нас это не совсем устраивает. Таблица нуждается в прокачке. В первом столбце номера строк прижаты к правой стороне, установим их в центре и изменим фон. В столбце “Количество” отрицательные числа нарисуем красным цветом, так принято в бухгалтерском учёте. В последнем столбце прижмём строки к правому краю. Зачем? Мне так захотелось. После прокачки вы не узнаете эту таблицу.

Будем создавать класс рисовальщика, расширяя класс JLabel, рисующий содержимое ячеек. Правой кнопкой по пакету myRendEditTable.table, выбираем New->Class, в поле Name вводим IntegerRenderer, это наш рисовальщик для первого столбца (вообще-то столбцы нумеруют с нуля, так что это нулевой столбец). Код класса-рисовальщика для первого столбца:

Разберём этот класс подробно. Во-первых метод

public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus, int row, int column)

Аргументы здесь такие: table – это наша таблица, value – значение в данной ячейке, isSelected – выделена наша ячейка или нет, hasFocus - имеет ячейка фокус или нет, row - ряд ячейки, которую мы рисуем, column- колонка этой ячейки.

Методом setHorisontalAlignment установим номера строк в центр. Методом setText укажем, что, если значение ячейки не заявлено, то ставим пробел.

Теперь рассмотрим isSelected и hasFocus. IsSelected ==true значит что ячейка выделена, hasFocus == true означает, что ячейка имеет фокус. Но разве ячейка, имеющая фокус не является одновременно выделеной? Да, является. Тогда зачем различать фокус и селектид? Дело здесь вот в чём. Когда мы ставим курсор на строку таблицы, то все ячейки этой сторки получают в своём свойстве isSelected значение true, т.е. isSelected = true. Все остальные ячейки таблицы имеют isSelected = false. Ячейка выделенной строки, именно на которой стоит курсор имеет фокус, т.е. её свойство hasFocus = true, для всех остальных ячеек, включая ячейки выделенной стоки, hasFocus = false. В нашем классе-рисовальщике мы указываем как рисовать ячейки выделенного ряда ( isSelected = true) и той ячейки выделенного ряда, на которой установлен курсор ( hasFocus = true). В классе JTable принято ячейку, имеющую фокус, обводить контуром. Соблюдая этот стиль, установим контур методом setBorder. Стоп. Зачем мы устанавливаем контур фокусной ячейки, если класс JTable и так обводит такие ячейки контуром? Всё просто. Как только мы взяли на себя труд установить рисовальщика для каких-то ячеек, так класс JTable снял с себя всякую ответственность за их прорисовку, мы сами должны всё прописывать: обводить контуром или нет, нужен цветной фон или нет и т.п.

Первый столбец обработан, теперь сделаем рисовальщика для столбца “Количество”. Правой кнопкой по пакету myRendEditTable.table, выбираем New->Class, в поле Name вводим DoubleRenderer, это наш рисовальщик для третьего столбца. Код класса-рисовальщика для столбца “Количество”:

В этом классе проверяем значение, установленное в ячейку, если оно меньше нуля, то цвет числа красный. Метод setForeground как раз и задаёт цвет значения, которое указано в ячейке (а не фона, который задаётся методом setBackground).

Теперь последний столбец. Правой кнопкой по пакету myRendEditTable.table, выбираем New->Class, в поле Name вводим StringRenderer, это наш рисовальщик для третьего столбца. Код класса-рисовальщика для столбца “Склад”:

В этом классе определяем, если номер колонки равен трём (column == 3), то прижимаем значение ячейки к правой границе.

На этот момент ваш проект должен выглядеть так: JTable установить своего рисовальщика

Рисовальщики готовы, осталось сообщить нашей таблице об этом. Рисовальщики устанавливают для столбцов. Каждый столбец имеет тип. Как узнать этот тип? В модели таблицы, а у нас это класс TableExModel, есть вектор vColClass, в нём и объявлены типы, соответствующие каждой колонке. Установить рисовальщика в таблицу означает указать рисовальщика для типа. Тип первой колонки (а точнее нулевой) – Integer. Ставим рисовальщика для колонки типа Integer:

table.setDefaultRenderer(Integer.class, new IntegerRenderer());

Теперь колонка “Номер” будет прорисована нашим рисовальщиком. Обратите внимание на тонкость. У нас только одна колонка имеет тип Integer, а если были бы другие? Тогда и они рисовались бы нашим рисовальщиком. Это не всегда удобно. Но мы с вами уже умеем обойти такую сложность, правда? Да, правда. У нас два столбца типа String. Мы решили значения в последнем столбце прижать к правой стороне, но в столбце “Наименование”, а его тип String, они должны быть прижаты к левой стороне. Вот почему в классе StringRenderer мы указали, что сдвиг вправо дейсвует только для столбца номер три:

Обращаю ваше внимание, что не только последний столбец прорисовывается нашим рисовальщиком StringRenderer, но и столбец “Наименование”, ведь он тоже имеет тип String. Ещё раз. Рисовальщики устанавливают для типа, а если колонок этого типа несколько, то установленный рисовальщик действует во всех колонках этого типа. Чтобы заставить колонки одного типа рисоваться по-разному ставим условия, что, например, if(column == 3), рисовать так-то, а другие так-то.

Измените код конструктора TableEx() так:

Этими строками мы установили своих рисовальщиков для колонок типа String, Double, Integer:

Итак, таблица подверглась грандиозной прокачке. Вы готовы увидеть результат? Правой кнопкой по значку класса TableEx -> Run As -> Java Application: JTable установить своего рисовальщика

Проведём опыт. Два раза левой кнопкой по 18.8 и поставте минус перед ним. Нажмите Enter. Число -18.8 стало красным. Кликнете один раз левой кнопкой 120.0. Весь ряд выделен подсветкой, все ячейки этого ряда имеют свойство isSelected = true, а ячейка со значением 120.0, в которой сейчас курсор, имеет hasFocus = true. Контур вокруг ячейки со 120.0 увидели? Не зря мы старались.