Java Swing: шаблон модели таблицы
Java Swing устарел. Не настолько, чтобы стать ненужным, и не так, чтобы с ним было бы невозможно написать хороший интерфейс. Но он устарел достаточно, чтобы программирование интерфейсов стало рутинным и утомительным процессом. Таблицы используются часто, даже очень. Для создания кастомной модели реализуется интерфейс javax.swing.table.TableModel
или (чаще) наследуются от javax.swing.table.AbstractTableModel
. Но каша из столбцов, констант, индексов и наименований столбцов превращает поддержку модели в ад. Самой ненавистной мною частью является хранение наименований и типов классов в отдельных переменных. Такое можно увидеть и в официальной документации:
class MyTableModel extends AbstractTableModel { private String[] columnNames = ...//same as before... private Object[][] data = ...//same as before... ... }
Из-за этого в других частях кода я часто вижу использование неименованных индексов столбцов и сравнение их по имени. Вот вам совет: используйте перечисления для работы с колонками таблицы:
public enum IntegerFormatColumns { /** * Значение, как оно есть. */ SIMPLE { @Override public Object getValue(Integer i) { return i; } // переопределяем тип возвращаемого значения @Override public Class<?> getColumnClass() { return Integer.class; } }, /** * Шестнадцатиричное представление числа. */ HEX { @Override public Object getValue(Integer i) { return Integer.toHexString(i); } }, /** * Двоичное представление числа. */ BINARY { @Override public Object getValue(Integer i) { return Integer.toBinaryString(i); } } ; /** * Метод, который извлекает показываемое значение из исходных данных * @param i исходные данные * @return отображаемый в таблице результат */ public abstract Object getValue(Integer i); /** * Метод извлечения названия столбца таблицы. * * Для примера название извлекается из именования элемента перечисления. * * @return название столбца таблицы. */ public String getColumnName() { return name(); } /** * Метод извлечения класса отображаемого результата. * * По умолчанию, это класс {@link String}. * * @return класс отображаемого результата */ public Class<?> getColumnClass() { return String.class; } }
Используем этот класс в модели:
public static class IntegerFormatModel extends AbstractTableModel { private final List<Integer> values = new ArrayList<>(); @Override public int getRowCount() { return values.size(); } @Override public int getColumnCount() { return IntegerFormatColumns.values().length; } @Override public String getColumnName(int column) { return IntegerFormatColumns.values()[column].getColumnName(); } @Override public Class<?> getColumnClass(int columnIndex) { return IntegerFormatColumns.values()[columnIndex].getColumnClass(); } @Override public Object getValueAt(int rowIndex, int columnIndex) { return IntegerFormatColumns.values()[columnIndex].getValue(values.get(rowIndex)); } }
Бесплатно вы получите возможность добавлять/изменять/удалять столбцы без вмешательства в саму модель и простой способ получения индекса столбца:
int index = IntegerFormatColumns.HEX.ordinal();
Ещё по теме: