Spec-Zone .ru
спецификации, руководства, описания, API
След: Создание GUI С JFC/Swing
Урок: Используя Компоненты Swing
Раздел: Как Использовать Различные Компоненты
Как Использовать Таблицы
Домашняя страница > Создание GUI С JFC/Swing > Используя Компоненты Swing

Как Использовать Таблицы

С JTable class можно вывести на экран таблицы данных, дополнительно разрешая пользователю отредактировать данные. JTable не содержит или данные кэша; это - просто представление Ваших данных. Вот изображение типичной таблицы, выведенной на экран в пределах области прокрутки:

Снимок TableDemo, который выводит на экран типичную таблицу.

Остальная часть этого раздела показывает Вам, как выполнить некоторые общие связанные с таблицей задачи. Вот являются темы этим разделом покрытия:

Составление Простой Таблицы


Попробуйте это: 
  1. Нажмите кнопку Launch, чтобы работать SimpleTableDemo Сеть Java™ использования Запускается (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

    Запускает пример SimpleTableDemo
  2. Щелкните по ячейке, которая содержит "Сноубординг".
    Вся первая строка выбирается, указывая, что Вы выбрали данные Кэти Смит. Специальное выделение указывает, что ячейка "Сноубординга" доступна для редактирования. Обычно, Вы начинаете редактировать текстовую ячейку двойным щелчком это.

  3. Расположите курсор по "Имени". Теперь нажмите кнопку мыши и перетащите направо.
    Как можно видеть, пользователи могут перестроить столбцы в таблицах.

  4. Расположите курсор только направо от заголовка столбца. Теперь нажмите кнопку мыши и перетащите направо или оставленный.
    Размер изменений столбца, и другие столбцы корректируются, чтобы заполнить остающееся пространство.

  5. Измените размеры окна, содержащего таблицу так, чтобы это было больше чем необходимый, чтобы вывести на экран целую таблицу.
    Все табличные ячейки становятся более широкими, расширяясь, чтобы заполнить дополнительное горизонтальное пространство.

Таблица в SimpleTableDemo.java объявляет имена столбцов в Строковом массиве:

String[] columnNames = {"First Name",
                        "Last Name",
                        "Sport",
                        "# of Years",
                        "Vegetarian"};

Его данные инициализируются и хранятся в двумерном Объектном массиве:

Object[][] data = {
    {"Kathy", "Smith",
     "Snowboarding", new Integer(5), new Boolean(false)},
    {"John", "Doe",
     "Rowing", new Integer(3), new Boolean(true)},
    {"Sue", "Black",
     "Knitting", new Integer(2), new Boolean(false)},
    {"Jane", "White",
     "Speed reading", new Integer(20), new Boolean(true)},
    {"Joe", "Brown",
     "Pool", new Integer(10), new Boolean(false)}
};

Затем Таблица создается, используя эти данные и columnNames:

JTable table = new JTable(data, columnNames);

Есть два JTable конструкторы, которые непосредственно принимают данные (SimpleTableDemo использует первое):

Преимущество этих конструкторов состоит в том, что они удобны. Однако, у этих конструкторов также есть недостатки:

Если Вы хотите обойти эти ограничения, Вы должны реализовать свою собственную табличную модель, как описано в Создании Табличной Модели.

Добавление Таблицы к Контейнеру

Вот типичный код для того, чтобы создать область прокрутки, которая служит контейнером для таблицы:

JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);

Эти две строки в этом отрывке делают следующее:

Область прокрутки автоматически помещает табличный заголовок наверху области просмотра. Имена столбцов остаются видимыми наверху области просмотра, когда табличные данные прокручиваются.

Если Вы используете таблицу без области прокрутки, то следует получить табличный компонент заголовка и поместить его непосредственно. Например:

container.setLayout(new BorderLayout());
container.add(table.getTableHeader(), BorderLayout.PAGE_START);
container.add(table, BorderLayout.CENTER);

Установка и Изменение Ширин столбцов

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

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

Чтобы настроить начальные ширины столбцов, можно вызвать setPreferredWidth на каждом из столбцов Вашей таблицы. Это устанавливает и привилегированные ширины столбцов и их приблизительные относительные ширины. Например, добавляя следующий код к SimpleTableDemo делает его третий столбец больше чем другие столбцы:

TableColumn column = null;
for (int i = 0; i < 5; i++) {
    column = table.getColumnModel().getColumn(i);
    if (i == 2) {
        column.setPreferredWidth(100); //third column is bigger
    } else {
        column.setPreferredWidth(50);
    }
}

Поскольку предыдущий код показывает, каждый столбец в таблице представляется a TableColumn объект. TableColumn метод get предоставлений и методы метода set для минимума, предпочтенных, и максимальных ширин столбца, так же как метода для того, чтобы получить текущий width. Для примера установки ширин ячейки, основанных на приближении пространства, должен был потянуть содержание ячеек, видеть initColumnSizes метод в TableRenderDemo.java.

Когда пользователь явно изменяет размеры столбцов, привилегированные ширины столбцов устанавливаются так, что, определенные пользователем размеры становятся новыми текущими ширинами столбцов. Однако, когда сама таблица изменяется — обычно, потому что окно изменило размеры —; привилегированные ширины столбцов не изменяются. Вместо этого существующие привилегированные ширины используются, чтобы вычислить новые ширины столбцов, чтобы заполнить свободное место.

Можно измениться, таблица изменяют размеры поведения, вызывая setAutoResizeMode.

Пользовательские Выборы

В ее конфигурации значения по умолчанию таблица поддерживает выбор, который состоит из одной или более строк. Пользователь может выбрать непрерывный диапазон строк или произвольный набор строк. Последняя ячейка, на которую указал пользователь, получает специальную индикацию; в Металлическом стили обрисовывается в общих чертах ячейка. Эта ячейка известна как ведущий выбор; это иногда вызывают "ячейкой с фокусом" или "текущей ячейкой".

Пользователь использует мышь и/или клавиатуру, чтобы сделать выборы, как описано в следующей таблице:

Работа Действие мыши Действие клавиатуры
Выберите единственную строку. Щелкнуть. Стрелка вверх или Стрелка вниз.
Расширьте непрерывный выбор. Щелчок при нажатой клавише Shift или Перетаскивает по строкам. Стрелка Shift-Up или Стрелка Shift-Down.
Добавьте строку к выбору строки выбора/переключателя. Щелчок управления Переместите ведущий выбор со Стрелкой вверх управления или Стрелкой вниз управления, затем используйте клавишу "Пробел", чтобы добавить к выбору или клавише "Пробел" управления, чтобы переключить выбор строки.

Чтобы видеть, как выборы работают, нажмите кнопку Launch, чтобы работать TableSelectionDemo Сеть Java™ использования Запускается (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

Запускает пример TableSelectionDemo

Этот пример программы представляет знакомую таблицу, и позволяет пользователю управлять определенными опциями JTable. Есть также текстовая область, которая регистрирует события выбора.

В снимке экрана ниже, пользователь выполнил программу, по которой щелкают в первой строке, тогда щелкнутой по управлению в третьей строке. Заметьте схему вокруг последней ячейки, по которой щелкают; это - то, как Металлический стиль выделяет ведущий выбор.

TableSelectionDemo с выбором строки состоящим из нескольких несмежных участков.

Под "Режимом выбора" есть ряд переключателей. Щелкните по тому маркированный "Единственный Выбор". Теперь можно только выбрать одну строку за один раз. Если Вы щелкаете по переключателю "Single Interval Selection", можно выбрать ряд строк, которые должны быть непрерывными.

Все переключатели под "Режимом выбора" вызывают JTable.setSelectionMode. Этот метод берет единственный параметр, который должен быть одной из следующих констант, определенных в javax.swing.ListSelectionModel: MULTIPLE_INTERVAL_SELECTION, SINGLE_INTERVAL_SELECTION, и SINGLE_SELECTION.

Возврат TableSelectionDemo, заметьте три флажка опции под "Опциями Выбора." Каждый флажок управляет состоянием a boolean связанная переменная, определенная JTable:


ОТМЕТЬТЕ: JTable использует очень простое понятие выбора, которым управляют как пересечение строк и столбцов. Это не было разработано, чтобы обработать полностью независимые выборы ячейки.

Если Вы снимаете все три флажка (устанавливающий все три связанных свойства в false), нет никакого выбора; только ведущий выбор показывают.

Можно заметить, что флажок "Cell Selection" отключается в многократном режиме выбора интервала. Это - то, потому что выбор ячейки не поддерживается в этом режиме в демонстрационном примере. Можно определить выбор ячейкой в многократном режиме выбора интервала, но результатом является таблица, которая не производит полезные выборы.

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


ОТМЕТЬТЕ: Установка cellSelectionEnabled к значению имеет побочный эффект также установки обоих rowSelectionEnabled и columnSelectionEnabled к тому значению. Установка обоих rowSelectionEnabled и columnSelectionEnabled к значению имеет побочный эффект также установки cellSelectionEnabled к тому значению. Установка rowSelectionEnabled и columnSelectionEnabled к различным значениям имеет побочный эффект также установки cellSelectionEnabled к false.

Чтобы получить текущий выбор, использовать JTable.getSelectedRows который возвращается, массив строки индексирует, и JTable.getSelectedColumns который возвращается, массив столбца индексирует. Чтобы получить координаты ведущего выбора, обратитесь к моделям выбора для таблицы непосредственно и для модели столбца таблицы. Следующий код форматирует строку, содержащую строку и столбец ведущего выбора:

String.format("Lead Selection: %d, %d. ",
    table.getSelectionModel().getLeadSelectionIndex(),
    table.getColumnModel().getSelectionModel().getLeadSelectionIndex());

Пользовательские выборы генерируют много событий. Для получения информации о них обратитесь к тому, Как Записать Слушателю Выбора Списка в уроке Слушателей События Записи.


ОТМЕТЬТЕ: данные Выбора фактически описывают выбранные ячейки в "представлении" (табличные данные, как это появляется после любой сортировки или фильтрации), а не в табличной модели. Это различие не имеет значения, если Ваши просматриваемые данные не были перестроены, сортируя, фильтруя, или пользовательское манипулирование столбцами. В этом случае следует преобразовать координаты выбора, используя методы преобразования, описанные в Сортировке и Фильтрации.

Создание Табличной Модели

Каждый табличный объект использует табличный объект модели управлять фактическими табличными данными. Табличный объект модели должен реализовать TableModel интерфейс. Если программист не обеспечивает табличный объект модели, JTable автоматически создает экземпляр DefaultTableModel. Это отношение иллюстрируется ниже.

Отношение между таблицей, табличным объектом, объектом модели

JTable конструктор, используемый SimpleTableDemo создает его табличную модель с кодом как это:

new AbstractTableModel() {
    public String getColumnName(int col) {
        return columnNames[col].toString();
    }
    public int getRowCount() { return rowData.length; }
    public int getColumnCount() { return columnNames.length; }
    public Object getValueAt(int row, int col) {
        return rowData[row][col];
    }
    public boolean isCellEditable(int row, int col)
        { return true; }
    public void setValueAt(Object value, int row, int col) {
        rowData[row][col] = value;
        fireTableCellUpdated(row, col);
    }
}

Поскольку предыдущий код показывает, реализовывая табличную модель может быть простым. Обычно, Вы реализуете свою табличную модель в подклассе AbstractTableModel class.

Ваша модель могла бы содержать свои данные в массиве, векторе, или хешировать карту, или это могло бы получить данные от внешнего источника, такого как база данных. Во время выполнения это могло бы даже генерировать данные.

Эта таблица отличается от SimpleTableDemo таблица следующими способами:

См. ниже кода, взятого от TableDemo.java это отличается от SimpleTableDemo.java. Полужирный шрифт указывает на код, который делает модель этой таблицы отличающейся от табличной модели определенный автоматически для SimpleTableDemo.

public TableDemo() {
    ...
    JTable table = new JTable(new MyTableModel());
    ...
}

class MyTableModel extends AbstractTableModel {
    private String[] columnNames = ...//same as before...
    private Object[][] data = ...//same as before...

    public int getColumnCount() {
        return columnNames.length;
    }

    public int getRowCount() {
        return data.length;
    }

    public String getColumnName(int col) {
        return columnNames[col];
    }

    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    public boolean isCellEditable(int row, int col) {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        if (col < 2) {
            return false;
        } else {
            return true;
        }
    }

    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    public void setValueAt(Object value, int row, int col) {
        data[row][col] = value;
        fireTableCellUpdated(row, col);
    }
    ...
}

Прислушивание к Изменениям Данных

У табличной модели может быть ряд слушателей, которые уведомляются всякий раз, когда табличные данные изменяются. Слушатели являются экземплярами TableModelListener. В следующем примере кода, SimpleTableDemo расширяется, чтобы включать такого слушателя. Новый код полужирным.

import javax.swing.event.*;
import javax.swing.table.TableModel;

public class SimpleTableDemo ... implements TableModelListener {
    ...
    public SimpleTableDemo() {
        ...
        table.getModel().addTableModelListener(this);
        ...
    }

    public void tableChanged(TableModelEvent e) {
        int row = e.getFirstRow();
        int column = e.getColumn();
        TableModel model = (TableModel)e.getSource();
        String columnName = model.getColumnName(column);
        Object data = model.getValueAt(row, column);

        ...// Do something with the data...
    }
    ...
}

Увольнение Событий Изменения Данных

Чтобы запустить события изменения данных, табличная модель должна знать, как создать a TableModelEvent объект. Это может быть сложной процедурой, но уже реализуется в DefaultTableModel. Можно или позволить JTable использовать его экземпляр по умолчанию DefaultTableModel, или создайте свой собственный подкласс DefaultTableModel.

Если DefaultTableModel не подходящий основной class для Вашей пользовательской табличной модели class, рассмотрите разделение на подклассы AbstractTableModel. Этот class реализует простую платформу для того, чтобы создать TableModelEvent объекты. Ваш пользовательский class просто должен вызвать один следующий AbstractTableModel методы каждые данные расписания изменяются внешним источником.

Метод Изменение
fireTableCellUpdated Обновление указанной ячейки.
fireTableRowsUpdated Обновление указанных строк
fireTableDataChanged Обновление всей таблицы (данные только).
fireTableRowsInserted Вставляются новые строки.
fireTableRowsDeleted Существующие Удаленные строки
fireTableStructureChanged   Лишите законной силы всю таблицу, и данные и структура.

Понятия: Редакторы и Средства рендеринга

Прежде, чем Вы продолжите к следующим немногим задачам, Вы должны понять, как таблицы тянут свои ячейки. Вы могли бы ожидать, что каждая ячейка в таблице будет компонентом. Однако, по причинам производительности, таблицы Swing реализуются по-другому.

Вместо этого единственное средство рендеринга ячейки обычно используется, чтобы потянуть все ячейки, которые содержат тот же самый тип данных. Можно думать о средстве рендеринга как о конфигурируемом штампе чернил что табличное использование, чтобы штамповать соответственно отформатированные данные на каждую ячейку. Когда пользователь начинает редактировать данные ячейки, редактор ячейки принимает ячейку, управляя поведением редактирования ячейки.

Например, каждая ячейка в столбце # of Years в TableDemo содержит Number данные — определенно, Integer объект. По умолчанию, средство рендеринга ячейки для a Number- содержащий столбец использует сингл JLabel экземпляр, чтобы потянуть соответствующие числа, выровненные по правому краю, на ячейках столбца. Если пользователь начинает редактировать одну из ячеек, редактор ячейки значения по умолчанию использует выровненное по правому краю JTextField управлять редактированием ячейки.

Чтобы выбрать средство рендеринга, которое выводит на экран ячейки в столбце, таблица сначала определяет, определили ли Вы средство рендеринга для того определенного столбца. Если Вы не сделали, то таблица вызывает табличную модель getColumnClass метод, который получает тип данных ячеек столбца. Затем, таблица сравнивает тип данных столбца со списком типов данных, для которых регистрируются средства рендеринга ячейки. Этот список инициализируется таблицей, но можно добавить к этому или изменить это. В настоящий момент, таблицы, помещенные следующие типы данных в списке:

Редакторы ячейки выбираются, используя подобный алгоритм.

Помните, что, если Вы позволяете таблице создавать свою собственную модель, она использует Object как тип каждого столбца. Чтобы определить более точные типы столбца, табличная модель должна определить getColumnClass метод соответственно, как демонстрирующийся TableDemo.java.

Имейте в виду, что, хотя средства рендеринга определяют, как каждая ячейка или взгляды заголовка столбца и могут определить свой текст подсказки, средство рендеринга не обрабатывает события. Если Вы должны поднять события, которые имеют место в таблице, метод, который Вы используете, изменяется видом события, которым Вы интересуетесь:

Ситуация Как Получить События
Обнаружить события от ячейки, которая редактируется... Используйте редактора ячейки (или зарегистрируйте слушателя на редакторе ячейки).
Обнаружить выборы строки/столбца/ячейки и отмены выбора... Используйте слушателя выбора как описано в Обнаружении Пользовательских Выборов.
Обнаружить события от нажатия мыши на заголовке столбца... Зарегистрируйте соответствующий тип слушателя мыши на таблице JTableHeader объект. (См. TableSorter.java для примера.)
Обнаружить другие события... Зарегистрируйте соответствующего слушателя на JTable объект.

Следующие немного разделов говорят Вам, как настроить дисплей и редактирование, определяя средства рендеринга и редакторов. Можно определить средства рендеринга ячейки и редакторов или столбцом или типом данных.

Используя Пользовательские Средства рендеринга

Этот раздел говорит Вам, как создать и определить средство рендеринга ячейки. Можно установить специфичное для типа средство рендеринга ячейки, используя JTable метод setDefaultRenderer. Чтобы определить, что ячейки в определенном столбце должны использовать средство рендеринга, Вы используете TableColumn метод setCellRenderer. Можно даже определить специфичное для ячейки средство рендеринга, создавая a JTable подкласс.

Легко настроить текст или изображение, представленное средством рендеринга значения по умолчанию, DefaultTableCellRenderer. Вы только создаете подкласс и реализуете setValue метод так, чтобы это вызвало setText или setIcon с соответствующей строкой или изображением. Например, вот то, как средство рендеринга даты значения по умолчанию реализуется:

static class DateRenderer extends DefaultTableCellRenderer {
    DateFormat formatter;
    public DateRenderer() { super(); }

    public void setValue(Object value) {
        if (formatter==null) {
            formatter = DateFormat.getDateInstance();
        }
        setText((value == null) ? "" : formatter.format(value));
    }
}

Расширяясь DefaultTableCellRenderer недостаточно, можно создать средство рендеринга, используя другой суперкласс. Самый легкий путь состоит в том, чтобы создать подкласс существующего компонента, заставляя Ваш подкласс реализовать TableCellRenderer интерфейс. TableCellRenderer требует только одного метода: getTableCellRendererComponent. Ваша реализация этого метода должна установить компонент рендеринга, чтобы отразить переданный - в состоянии, и затем возвратить компонент.

В снимке TableDialogEditDemo, средство рендеринга, используемое для Любимых Цветных ячеек, является подклассом JLabel вызванный ColorRenderer. Вот выборки от ColorRenderer.java то шоу, как это реализуется.

public class ColorRenderer extends JLabel
                           implements TableCellRenderer {
    ...
    public ColorRenderer(boolean isBordered) {
        this.isBordered = isBordered;
        setOpaque(true); //MUST do this for background to show up.
    }

    public Component getTableCellRendererComponent(
                            JTable table, Object color,
                            boolean isSelected, boolean hasFocus,
                            int row, int column) {
        Color newColor = (Color)color;
        setBackground(newColor);
        if (isBordered) {
            if (isSelected) {
                ...
                //selectedBorder is a solid border in the color
                //table.getSelectionBackground().
                setBorder(selectedBorder);
            } else {
                ...
                //unselectedBorder is a solid border in the color
                //table.getBackground().
                setBorder(unselectedBorder);
            }
        }
        
        setToolTipText(...); //Discussed in the following section
        return this;
    }
}

Вот код от TableDialogEditDemo.java это регистрирует a ColorRenderer экземпляр как средство рендеринга значения по умолчанию для всех Color данные:

table.setDefaultRenderer(Color.class, new ColorRenderer(true));

Чтобы определить специфичное для ячейки средство рендеринга, Вы должны определить a JTable подкласс, который переопределяет getCellRenderer метод. Например, следующий код заставляет первую ячейку в первом столбце таблицы использовать пользовательское средство рендеринга:

TableCellRenderer weirdRenderer = new WeirdRenderer();
table = new JTable(...) {
    public TableCellRenderer getCellRenderer(int row, int column) {
        if ((row == 0) && (column == 0)) {
            return weirdRenderer;
        }
        // else...
        return super.getCellRenderer(row, column);
    }
};

Определение Подсказок для Ячеек

По умолчанию текст подсказки, выведенный на экран для табличной ячейки, определяется средством рендеринга ячейки. Однако, иногда может быть более просто определить текст подсказки, переопределяя JTable's реализация getToolTipText(MouseEvent) метод. Этот раздел показывает Вам, как использовать оба метода.

Чтобы добавить подсказку к ячейке, используя ее средство рендеринга, Вы сначала должны получить или создать средство рендеринга ячейки. Затем, после удостоверения компонента рендеринга a JComponent, вызовите setToolTipText метод на этом.

Пример установки подсказок для ячеек находится в TableRenderDemo. Нажмите кнопку Launch, чтобы работать, она использующий Сеть Java™ Запускается (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

Запускает пример TableRenderDemo

Исходный код находится в TableRenderDemo.java. Это добавляет подсказки к ячейкам столбца Sport со следующим кодом:

//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
        new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);

Хотя текст подсказки в предыдущем примере статичен, можно также реализовать подсказки, текст которых изменяется в зависимости от состояния ячейки или программы. Вот пара способов сделать так:

Пример добавляющего кода к средству рендеринга ячейки находится в TableDialogEditDemo. Нажмите кнопку Launch, чтобы работать, она использующий Сеть Java™ Запускается (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

Запускает пример TableDialogEditDemo

TableDialogEditDemo использует средство рендеринга для цветов, реализованных в ColorRenderer.java, это устанавливает текст подсказки, используя полужирный код в следующем отрывке:

public class ColorRenderer extends JLabel 
                           implements TableCellRenderer {
    ...
    public Component getTableCellRendererComponent(
                            JTable table, Object color,
                            boolean isSelected, boolean hasFocus,
                            int row, int column) {
        Color newColor = (Color)color;
        ...
        setToolTipText("RGB value: " + newColor.getRed() + ", "
                                     + newColor.getGreen() + ", "
                                     + newColor.getBlue());
        return this;
    }
}

Вот пример того, на что похожа подсказка:

TableDialogEditDemo с подсказкой, описывающей значение RGB moused-по ячейки

Можно определить текст подсказки, переопределяя JTable's getToolTipText(MouseEvent) метод. Программа TableToolTipsDemo шоу, как. Нажмите кнопку Launch, чтобы работать, она использующий Сеть Java™ Запускается (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

Запускает пример TableToolTipsDemo

Ячейки с подсказками находятся в столбцах Sport и Vegetarian. Вот изображение его подсказки:

TableToolTipsDemo с подсказкой для ячейки в столбце Sport

Вот код от TableToolTipsDemo.java это реализует подсказки для ячеек в столбцах Sport и Vegetarian:

JTable table = new JTable(new MyTableModel()) {    
    //Implement table cell tool tips.
    public String getToolTipText(MouseEvent e) {
        String tip = null;
        java.awt.Point p = e.getPoint();
        int rowIndex = rowAtPoint(p);
        int colIndex = columnAtPoint(p);
        int realColumnIndex = convertColumnIndexToModel(colIndex);

        if (realColumnIndex == 2) { //Sport column
            tip = "This person's favorite sport to "
                   + "participate in is: "
                   + getValueAt(rowIndex, colIndex);

        } else if (realColumnIndex == 4) { //Veggie column
            TableModel model = getModel();
            String firstName = (String)model.getValueAt(rowIndex,0);
            String lastName = (String)model.getValueAt(rowIndex,1);
            Boolean veggie = (Boolean)model.getValueAt(rowIndex,4);
            if (Boolean.TRUE.equals(veggie)) {
                tip = firstName + " " + lastName
                      + " is a vegetarian";
            } else {
                tip = firstName + " " + lastName
                      + " is not a vegetarian";
            }

        } else { //another column
            //You can omit this part if you know you don't 
            //have any renderers that supply their own tool 
            //tips.
            tip = super.getToolTipText(e);
        }
        return tip;
    }
    ...
}

Код является довольно прямым, кроме, возможно, для звонка convertColumnIndexToModel. Тот вызов необходим, потому что, если пользователь перемещает столбцы, представление индексирует для столбца, не будет соответствовать, модель индексируют для столбца. Например, пользователь мог бы перетащить столбец Vegetarian (который модель рассматривает, чтобы быть в, индексируют 4), таким образом, это выводится на экран, поскольку первый столбец — при представлении индексирует 0. С тех пор prepareRenderer обеспечивает представление индексируют, Вы должны преобразовать представление, индексируют к модели, индексируют так, можно убедиться, что намеченный столбец был выбран.

Определение Подсказок для Заголовков Столбца

Можно добавить подсказку к заголовку столбца, устанавливая текст подсказки для таблицы JTableHeader. Часто, различные заголовки столбца требуют различного текста подсказки. Можно изменить текст, переопределяя табличный заголовок getToolTipText метод. Поочередно, можно вызвать TableColumn.setHeaderRenderer обеспечить пользовательское средство рендеринга для заголовка.

Пример использования того же самого текста подсказки для всех заголовков столбца находится в TableSorterDemo.java. Вот то, как это устанавливает текст подсказки:

table.getTableHeader().setToolTipText(
        "Click to sort; Shift-Click to sort in reverse order");

TableToolTipsDemo.java имеет пример реализации подсказок заголовка столбца, которые изменяются столбцом. Если Вы работаете TableToolTipsDemo (нажмите кнопку Launch), использующий Сеть Java™ Запускаются (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

Запускает пример TableToolTipsDemo

Вы будете видеть подсказки когда Вы мышь по любому заголовку столбца за исключением первых двух. Никакие подсказки не были suppled для столбцов имени, так как они казались очевидными. Вот изображение одной из подсказок заголовка столбца:

TableToolTipsDemo с подсказкой для заголовка столбца

Следующий код реализует подсказки. В основном это создает подкласс JTableHeader это переопределяет getToolTipText(MouseEvent) метод так, чтобы это возвратило текст для текущего столбца. Связать пересмотренный табличный заголовок с таблицей, JTable метод createDefaultTableHeader переопределяется так, чтобы это возвратило экземпляр JTableHeader подкласс.

protected String[] columnToolTips = {
    null, // "First Name" assumed obvious
    null, // "Last Name" assumed obvious
    "The person's favorite sport to participate in",
    "The number of years the person has played the sport",
    "If checked, the person eats no meat"};
...

JTable table = new JTable(new MyTableModel()) {
    ...

    //Implement table header tool tips.
    protected JTableHeader createDefaultTableHeader() {
        return new JTableHeader(columnModel) {
            public String getToolTipText(MouseEvent e) {
                String tip = null;
                java.awt.Point p = e.getPoint();
                int index = columnModel.getColumnIndexAtX(p.x);
                int realIndex = 
                        columnModel.getColumn(index).getModelIndex();
                return columnToolTips[realIndex];
            }
        };
    }
};

Сортировка и Фильтрация

Табличной сортировкой и фильтрацией управляет объект сортировщика. Самый легкий способ обеспечить объект сортировщика состоит в том, чтобы установить autoCreateRowSorter связанное свойство к true:

JTable table = new JTable();
table.setAutoCreateRowSorter(true);

Это действие определяет сортировщика строки, который является экземпляром javax.swing.table.TableRowSorter. Это обеспечивает таблицу, которая делает простой специфичный для локали вид, когда пользователь щелкает по заголовку столбца. Это демонстрируется в TableSortDemo.java, как замечено в этом снимке экрана:

TableSortDemo после щелчка по Last Name

Чтобы иметь больше контроля над сортировкой, можно создать экземпляр TableRowSorter и определите, что это - объект сортировщика для Вашей таблицы.

TableRowSorter<TableModel> sorter 
    = new TableRowSorter<TableModel>(table.getModel());
table.setRowSorter(sorter);

TableRowSorter использование java.util.Comparator объекты сортировать его строки. class, который реализует этот интерфейс, должен обеспечить вызванный метод compare это определяет, как любые два объекта сравниваются с целью сортировки. Например, следующий код создает a Comparator это сортирует ряд строк последним словом в каждой строке:

Comparator<String> comparator = new Comparator<String>() {
    public int compare(String s1, String s2) {
        String[] strings1 = s1.split("\\s");
        String[] strings2 = s2.split("\\s");
        return strings1[strings1.length - 1]
            .compareTo(strings2[strings2.length - 1]);
    }
};

Этот пример довольно упрощен; более обычно, a Comparator реализация является подклассом java.text.Collator. Можно определить свой собственный подкласс, использовать методы фабрики в Collator получить a Comparator для определенной локали, или использования java.text.RuleBasedCollator.

Определить который Comparator использовать для столбца, TableRowSorter попытки применить каждое из следующих правил поочередно. Правила сопровождаются в упомянутом ниже порядке; первое правило, которое предоставляет сортировщику a Comparator используется, и проигнорированные правила remainining.

  1. Если компаратор был определен, вызывая setComparator, используйте тот компаратор.
  2. Если табличная модель сообщает, что данные столбца состоят из строк (TableModel.getColumnClass возвраты String.class для того столбца), используйте компаратор, который сортирует строки, основанные на текущей локали.
  3. Если столбец class, возвращенный TableModel.getColumnClass реализации Comparable, используйте компаратор, который сортирует строки, основанные на значениях, возвращенных Comparable.compareTo.
  4. Если строковый преобразователь был определен для таблицы, вызывая setStringConverter, используйте компаратор, который сортирует получающиеся строковые представления, основанные на текущей локали.
  5. Если ни одно из предыдущих правил не применяется, используйте компаратор, который вызывает toString на данных столбца и видах получающиеся строки, основанные на текущей локали.

Для более сложных видов сортировки, подкласса TableRowSorter или его родительский class javax.swing.DefaultRowSorter.

Чтобы определить порядок сортировки и приоритет вида для столбцов, вызвать setSortKeys. Вот пример, который сортирует таблицу, используемую в примерах на первые два столбца. Приоритет столбцов в виде обозначается по приказу ключей сортировки в списке ключа сортировки. В этом случае у второго столбца есть первый ключ сортировки, таким образом, они строки сортируются именем, тогда фамилия.

List <RowSorter.SortKey> sortKeys 
    = new ArrayList<RowSorter.SortKey>();
sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
sorter.setSortKeys(sortKeys); 

В дополнение к переупорядочению результатов табличный сортировщик может также определить, какие строки будут выведены на экран. Это известно как фильтрация. TableRowSorter использование фильтрации реализаций javax.swing.RowFilter объекты. RowFilter реализации несколько методов фабрики, которые создают общие виды фильтров. Например, regexFilter возвраты a RowFilter это фильтрует основанный на регулярном выражении.

В следующем примере кода Вы явно создаете объект сортировщика, таким образом, можно позже использовать его, чтобы определить фильтр:

MyTableModel model = new MyTableModel();
sorter = new TableRowSorter<MyTableModel>(model);
table = new JTable(model);
table.setRowSorter(sorter);

Затем Вы фильтруете основанный на текущей стоимости текстового поля:

private void newFilter() {
    RowFilter<MyTableModel, Object> rf = null;
    //If current expression doesn't parse, don't update.
    try {
        rf = RowFilter.regexFilter(filterText.getText(), 0);
    } catch (java.util.regex.PatternSyntaxException e) {
        return;
    }
    sorter.setRowFilter(rf);
}

В последующем примере, newFilter() вызывается каждый раз изменения текстового поля. Когда пользователь вводит сложные регулярные выражения, try...catch препятствует тому, чтобы исключение синтаксиса вмешалось во ввод.

Когда таблица использует сортировщика, данные, которые видят пользователи, могут быть в различном порядке чем определенное по условию модель, и, возможно, не включают все строки, определенные по условию модель. Данные, которые фактически видит пользователь, известны как представление, и имеют свой собственный набор координат. JTable обеспечивает методы, которые преобразовывают из координат модели, чтобы просмотреть координаты — convertColumnIndexToView и convertRowIndexToView — и то преобразование от представления координирует, чтобы смоделировать координаты — convertColumnIndexToModel и convertRowIndexToModel.


ОТМЕТЬТЕ: При использовании сортировщика всегда не забывайте преобразовывать координаты ячейки.

Следующий пример объединяет идеи, обсужденные в этом разделе. TableFilterDemo.java добавляет небольшое количество изменений к TableDemo. Они включают фрагменты кода ранее в этот раздел, которые предоставляют сортировщику для основной таблицы, и используют текстовое поле, чтобы предоставить регулярное выражение фильтрации. Следующие шоу снимка экрана TableFilterDemo перед любой сортировкой или фильтрацией был сделан. Заметьте, что строка 3 в модели является все еще тем же самым как строкой 3 в представлении:

TableFilterDemo без сортировки

Если пользователь щелкает дважды по второму столбцу, четвертая строка становится первой строкой — но только в представлении:

TableFilterDemo с обратной сортировкой во втором столбце

Как ранее отмечено, текст, который пользователь вводит в текстовое поле "Filter Text", определяет фильтр, который определяет, какие строки показывают. Как с сортировкой, фильтрация может заставить координаты представления отклоняться от координат модели:

TableFilterDemo с фильтрацией

Вот код, который обновляет поле состояния, чтобы отразить текущий выбор:

table.getSelectionModel().addListSelectionListener(
        new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent event) {
                int viewRow = table.getSelectedRow();
                if (viewRow < 0) {
                    //Selection got filtered away.
                    statusText.setText("");
                } else {
                    int modelRow = 
                        table.convertRowIndexToModel(viewRow);
                    statusText.setText(
                        String.format("Selected Row in view: %d. " +
                            "Selected Row in model: %d.", 
                            viewRow, modelRow));
                }
            }
        }
);

Используя Поле комбинированного списка как Редактор

Устанавливая поле комбинированного списка, поскольку редактор прост как следующие шоу в качестве примера. Полужирная строка кодовых наборов поле комбинированного списка как редактор для определенного столбца.

TableColumn sportColumn = table.getColumnModel().getColumn(2);
...
JComboBox comboBox = new JComboBox();
comboBox.addItem("Snowboarding");
comboBox.addItem("Rowing");
comboBox.addItem("Chasing toddlers");
comboBox.addItem("Speed reading");
comboBox.addItem("Teaching high school");
comboBox.addItem("None");
sportColumn.setCellEditor(new DefaultCellEditor(comboBox));

Вот изображение редактора поля комбинированного списка в использовании:

Редактор ячейки поля комбинированного списка в использовании

Предыдущий код от TableRenderDemo.java. Можно работать TableRenderDemo (нажмите кнопку Launch), использующий Сеть Java™ Запускаются (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

Запускает пример TableRenderDemo

Используя Других Редакторов

Устанавливаете ли Вы редактора для единственного столбца ячеек (использующий TableColumn setCellEditor метод) или для определенного типа данных (использующий JTable setDefaultEditor метод), Вы определяете редактора, использующего параметр, который придерживается TableCellEditor интерфейс. К счастью, DefaultCellEditor class реализует этот интерфейс и предоставляет конструкторам, чтобы позволить Вам определять компонент редактирования, который является a JTextField, JCheckBox, или JComboBox. Обычно Вы не должны явно определить флажок как редактора, начиная со столбцов с Boolean данные автоматически используют средство рендеринга флажка и редактора.

Что, если Вы хотите определить редактора кроме текстового поля, флажка, или поля комбинированного списка? Как DefaultCellEditor не поддерживает другие типы компонентов, следует сделать немного больше работы. Вы должны создать class, который реализует TableCellEditor интерфейс. AbstractCellEditor class является хорошим суперклассом использования. Это реализует TableCellEditor's суперинтерфейс, CellEditor, избавление от необходимости Вас реализовать код увольнения события, необходимый для редакторов ячейки.

Ваш редактор ячейки class должен определить по крайней мере два метода — getCellEditorValue и getTableCellEditorComponent. getCellEditorValue метод, требуемый CellEditor, возвращает текущую стоимость ячейки. getTableCellEditorComponent метод, требуемый TableCellEditor, должен сконфигурировать и возвратить компонент, который Вы хотите использовать в качестве редактора.

Вот изображение таблицы с диалоговым окном, которое служит, косвенно, как редактор ячейки. Когда пользователь начинает редактировать ячейку в столбце Favorite Color, кнопка (истинный редактор ячейки) появляется и переводит в рабочее состояние диалоговое окно, с которым пользователь может выбрать различный цвет.

Редактор ячейки переводит диалоговое окно в рабочее состояние

Можно работать TableDialogEditDemo (нажмите кнопку Launch), использующий Сеть Java™ Запускаются (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

Запускает пример TableDialogEditDemo

Вот код, взятый от ColorEditor.java, это реализует редактора ячейки.

public class ColorEditor extends AbstractCellEditor
                         implements TableCellEditor,
                                    ActionListener {
    Color currentColor;
    JButton button;
    JColorChooser colorChooser;
    JDialog dialog;
    protected static final String EDIT = "edit";

    public ColorEditor() {
        button = new JButton();
        button.setActionCommand(EDIT);
        button.addActionListener(this);
        button.setBorderPainted(false);

        //Set up the dialog that the button brings up.
        colorChooser = new JColorChooser();
        dialog = JColorChooser.createDialog(button,
                                        "Pick a Color",
                                        true,  //modal
                                        colorChooser,
                                        this,  //OK button handler
                                        null); //no CANCEL button handler
    }

    public void actionPerformed(ActionEvent e) {
        if (EDIT.equals(e.getActionCommand())) {
            //The user has clicked the cell, so
            //bring up the dialog.
            button.setBackground(currentColor);
            colorChooser.setColor(currentColor);
            dialog.setVisible(true);

            fireEditingStopped(); //Make the renderer reappear.

        } else { //User pressed dialog's "OK" button.
            currentColor = colorChooser.getColor();
        }
    }

    //Implement the one CellEditor method that AbstractCellEditor doesn't.
    public Object getCellEditorValue() {
        return currentColor;
    }

    //Implement the one method defined by TableCellEditor.
    public Component getTableCellEditorComponent(JTable table,
                                                 Object value,
                                                 boolean isSelected,
                                                 int row,
                                                 int column) {
        currentColor = (Color)value;
        return button;
    }
}

Как можно видеть, код довольно прост. Единственная часть, которая немного хитра, является звонком fireEditingStopped в конце обработчика действия кнопки редактора. Без этого вызова редактор остался бы активным, даже при том, что модальное диалоговое окно больше не видимо. Звонок fireEditingStopped позволяет таблице знать, что она может деактивировать редактора, позволяя ячейке быть обработанным средством рендеринга снова.

Используя Редактора, чтобы Проверить Вводимого пользователем текста

Если редактор значения по умолчанию ячейки позволяет ввод текста, Вы получаете некоторую проверку на ошибки бесплатно, если тип ячейки определяется как что-то другое чем String или Object. Проверка на ошибки является побочным эффектом преобразования вводимого текста в объект надлежащего типа.

Автоматическая проверка вводимых пользователем строк происходит, когда редактор значения по умолчанию пытается создать новый экземпляр class, связанного со столбцом ячейки. Редактор значения по умолчанию создает этот экземпляр, используя конструктора, который берет a String как параметр. Например, в столбце, у ячеек которого есть тип Integer, когда пользователь вводит "123", редактор значения по умолчанию создает соответствие Integer использование кода, эквивалентного new Integer("123"). Если конструктор выдает исключение, схема ячейки покраснела и отказывается позволить фокусу перемещаться из ячейки. Если Вы реализуете class, используемый в качестве типа данных столбца, можно использовать редактора значения по умолчанию, если Ваш class предоставляет конструктора, который берет единственный параметр типа String.

Если Вы любите иметь текстовое поле как редактор для ячейки, но хотите настроить это — возможно, чтобы проверить вводимый пользователем текст более строго или реагировать по-другому, когда текст недопустим — можно изменить редактора ячейки, чтобы использовать отформатированное текстовое поле. Отформатированное текстовое поле может проверить значение или непрерывно в то время как пользователь вводит или после того, как пользователь указал на конец ввода (такой, поскольку нажатием Входят).

Следующий код, взятый от демонстрационного примера, называют TableFTFEditDemo.java, устанавливает отформатированное текстовое поле как редактора, который ограничивает все целочисленные значения, чтобы быть между 0 и 100. Можно работать TableFTFEditDemo (нажмите кнопку Launch), использующий Сеть Java™ Запускаются (загрузите JDK 6 или позже). Или, чтобы скомпилировать и выполнить пример самостоятельно, консультируйтесь, пример индексируют.

Запускает пример TableFTFEditDemo

Следующий код делает отформатированное текстовое поле редактором для всех столбцов, которые содержат данные типа Integer.

table.setDefaultEditor(Integer.class,
                       new IntegerEditor(0, 100));

IntegerEditor class реализуется как подкласс DefaultCellEditor это использует a JFormattedTextField вместо JTextField это DefaultCellEditor поддерживает. Это выполняет это первой установкой отформатированного текстового поля, чтобы использовать целочисленный формат и иметь указанные минимальные и максимальные значения, используя API, описанный в том, Как Использовать Отформатированные Текстовые поля. Это тогда переопределяет DefaultCellEditor реализация getTableCellEditorComponent, getCellEditorValue, и stopCellEditing методы, добавляя операции, которые необходимы для отформатированных текстовых полей.

Переопределение getTableCellEditorComponent устанавливает свойство значения отформатированного текстового поля (и не только текстовое свойство, от которого оно наследовалось JTextField) прежде, чем редактора показывают. Переопределение getCellEditorValue сохраняет значение ячейки как Integer, а не, скажем, Long значение, которое синтаксический анализатор отформатированного текстового поля имеет тенденцию возвращать. Наконец, переопределение stopCellEditing позволяет Вам проверять, допустим ли текст, возможно мешая редактору быть отклоненным. Если текст не допустим, Ваша реализация stopCellEditing поднимает диалоговое окно, которое дает пользователю опцию продолжения отредактировать или возвращение к последнему хорошему значению. Исходный код является немного слишком длинным, чтобы включать здесь, но можно найти это в IntegerEditor.java.

Печать

JTable обеспечивает простой API для того, чтобы он напечатал таблицы. Самый легкий способ распечатать таблицу состоит в том, чтобы вызвать JTable.print без параметров:

try {
    if (! table.print()) {
        System.err.println("User cancelled printing");
    }
} catch (java.awt.print.PrinterException e) {
    System.err.format("Cannot print %s%n", e.getMessage());
}

Вызов print на нормальном Swing приложение переводит стандартное диалоговое окно печати в рабочее состояние. (На бездисплейном приложении просто печатается таблица.) Возвращаемое значение указывает, продолжил ли пользователь задание печати или отменил это. JTable.print может бросить java.awt.print.PrinterException, который является проверенным исключением; именно поэтому вышеупомянутый пример использует a try ... catch.

JTable обеспечивает несколько перегрузок print с различными вариантами. Следующий код от TablePrintDemo.java шоу, как определить верхний колонтитул страницы:

MessageFormat header = new MessageFormat("Page {0,number,integer}");
try {
    table.print(JTable.PrintMode.FIT_WIDTH, header, null);
} catch (java.awt.print.PrinterException e) {
    System.err.format("Cannot print %s%n", e.getMessage());
}

Для более сложных приложений печати использовать JTable.getPrintable получить a Printable объект для таблицы. Для больше на Printable, обратитесь к уроку Печати в 2-D Графическом следе.

Примеры то Использование Таблицы

Эта таблица приводит примеры то использование JTable и где те примеры описываются.

Пример Где Описано Примечания
SimpleTableDemo Составление Простой Таблицы Основная таблица без пользовательской модели. Не включает код, чтобы определить ширины столбцов или обнаружить пользователя, редактирующего.
SimpleTable-
SelectionDemo
Обнаружение Пользовательских Выборов Добавляет единственное обнаружение выбора и выбора к SimpleTableDemo. Изменяя программу ALLOW_COLUMN_SELECTION и ALLOW_ROW_SELECTION константы, можно экспериментировать с альтернативами табличному значению по умолчанию разрешения только строк, которые будут выбраны.
TableDemo Создание Табличной Модели Основная таблица с пользовательской моделью.
TableFTFEditDemo Используя Редактора, чтобы Проверить Вводимого пользователем текста Изменяет TableDemo использовать пользовательского редактора (отформатированная разновидность текстового поля) для всех Integer данные.
TableRenderDemo Используя Поле комбинированного списка как Редактор Изменяет TableDemo использовать пользовательского редактора (поле комбинированного списка) для всех данных в столбце Sport. Также разумно размеры столбца выборов. Средства рендеринга использования, чтобы вывести на экран подсказки для спортивных ячеек.
TableDialogEditDemo Используя Других Редакторов Изменяет TableDemo иметь средство рендеринга ячейки и редактора, которые выводят на экран цвет и позволяют Вам выбирать новый, используя цветное диалоговое окно селектора.
TableToolTipsDemo Определение Подсказок для Ячеек, Определение Подсказок для Заголовков Столбца, Демонстрирует, как использовать несколько методов, чтобы установить текст подсказки для заголовков столбца и ячеек.
TableSortDemo Сортировка и Фильтрация Демонстрирует сортировщика значения по умолчанию, который позволяет пользователю сортировать столбцы, щелкая по их заголовкам.
TableFilterDemo Сортировка и Фильтрация Демонстрирует, как сортировать и фильтровать, и как это может заставить координаты представления отклоняться от координат модели.
TablePrintDemo Печать Демонстрирует табличную печать.
ListSelectionDemo Как Записать Слушателю Выбора Списка Шоу, как использовать все режимы выбора списка, используя слушателя выбора списка, это совместно используется таблицей и списком.
SharedModelDemo Нигде Основывается ListSelectionDemo создание модели данных быть совместно использованным таблицей и списком. Если Вы редактируете элемент в первом столбце таблицы, новое значение отражается в списке.

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Как Использовать Снабженные вкладками Области
Следующая страница: Как Использовать Текстовые области