#java #swing #jtable #tablecellrenderer
#java #swing #jtable #средство визуализации таблиц
Вопрос:
В Java Swing у нас есть JTable
, TableModel
, ColumnModel
и a TableCellRenderer
, которые работают вместе для отображения таблицы.
Как я могу обеспечить настройку, чтобы получить пользовательский средство визуализации ячеек на основе класса столбца — в отличие от настройки средства визуализации на основе индекса столбца.
final JTable table = new JTable(model);
table.getColumnModel().getColumn(0).setCellRenderer(new DateTimeRenderer());
table.getColumnModel().getColumn(1).setCellRenderer(new SuperDuperDoubleCellRenderer());
Предположим, у меня там 20 числовых ячеек!!!
Вышеуказанное работает, но я не очень заинтересован в этом решении, поскольку оно изменится при изменении модели, поэтому оно недостаточно хорошо инкапсулировано до такой степени — это клиентский код.
TableModel
Понимает базовую структуру данных таблицы, где он может выполнять пользовательское сопоставление со сложным типом (в отличие от DefaultTableModel и Vectors) — где он знает типы данных каждого столбца.
public class DemoTableModel implements TableModel {
@Override
public Class<?> getColumnClass(int columnIndex) {
// date time, double, etc...
return columnInfo.get(columnIndex).getDataType();
}
}
Что я хотел бы сделать, так это сообщить JTable
, что класс столбца (возвращаемый из табличной модели) является пользовательским типом DateTime — используйте CustomDateTimeCellRenderer
. Если это double, то используйте пользовательский SuperDuperDoubleCellRenderer
.
Проблема в том, чтобы просмотреть исходные тексты, чтобы увидеть, где это поведение сочетается браком.
Ответ №1:
Что я хотел бы сделать, так это сообщить JTable, что класс столбца (возвращаемый из табличной модели) является пользовательским типом DateTime — используйте CustomDateTimeCellRenderer . Если это double, то используйте пользовательский SuperDuperDoubleCellRenderer .
Средство визуализации устанавливается на уровне таблицы путем указания класса и средства визуализации:
table.setDefaultRenderer(Double.class, yourDoubleCellRenderer);
table.setDefaultRenderer(CustomDateTime.class, yourCustomDateTimeRenderer);
Комментарии:
1. Бах! Я не видел параметра для класса. Спасибо.
Ответ №2:
Вы можете сделать это на CellRenderer
уровне — средства визуализации ячеек требуются только для реализации
Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column)
Ничто не мешает вам указать всей JTable отображать ячейки, используя, скажем, SmartCellRenderer
a, который смотрит на тип переданного значения и делегирует фактический рендеринг a DoubleCellRenderer
, a StringCellRenderer
или a CuteInternetCatRenderer
. Предполагая, что типы объектов уникальны, это должно быть легко сделать (если несколько уродливо из-за набора if (value instanceof InternetCat) { ... }
, который решает, как отображать каждый объект на основе его класса).
Лучшим решением (не требуется никаких уродливых instanceof
s) является назначение определенных средств визуализации определенным столбцам во время вставки столбца:
// model index 0, width 75, renderer to use, editor to use
myTable.getColumnModel().addColumn(0, 75, cuteInternetCatRenderer, null);
Комментарии:
1. Да, моя забота заключалась в запуске нового экземпляра JTables по всем направлениям и повторении в них этой логики. Я думаю, что наличие абстракции вокруг этого поведения имеет смысл, а не каждый клиент добавляет все средства визуализации ячеек по умолчанию.
2. Типичный способ сделать это — присвоить значение по умолчанию
JTable
, скажем, aCatTable
— и создавать экземпляры только этого подкласса, который инкапсулирует все ваши бизнес-потребности и настройки JTable. Например, например, пользовательские средства визуализации ячеек.