Проблема с обновлением JTable

У меня проблемы с обновлением данных JTable.

Я реализую свой собственный TableModel, расширяющийся от javax.swing.table.AbstractTableModel, с помощью метода, который получает java.util.ArrayList<> и обрабатывает его для создания Object[][], откуда считываются данные таблицы.

Логика следующая:

Я реализую JList с некоторыми ключами записей, когда пользователь выбирает один, запускается метод, который подбирает ключ и запрашивает базу данных MySQL для получения записей, связанных с этим ключом. Конечным результатом является ArrayList‹>, который я передал в TableModel для построения данных, а затем установил их в свою таблицу.

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

Это отрывок из кода:

Способ построения данных таблицы:

public void createTableData(java.util.ArrayList<Lote> alLote) {
    //Lote is an entity class modeling the database table.
    TABLE_DATA = new Object[alLote.size()][TABLE_COLUMNS.length];
    //TABLE_DATA is an Object array, TABLE_COLUMNS is a String[] containing the names of the columns.
    int i = 0;
    for (Lote element : alLote) {
        int j = 0;
        TABLE_DATA[i][j++] = element.getFirstColumnValue();
        //and so son
        i++;
    }
    super.fireTableDataChanged();
}

При запуске GUI он начинается с пустого ArrayList‹>:

LoteTableModel ltm = new LoteTableModel();
arrayList = new ArrayList<Lote>();
ltm.createTableData(arrayList);
myTable = new JTable();
myTable.setModel(ltm);
scrollPane = new JScrollPane(myTable);

Кстати, я использую DesignGridLayout, RowGroup, который скрывает, когда в таблице нет записей, и показывает, когда в ней есть результаты, и JScrollPane в качестве контейнера таблицы.

dgl = new DesignGridLayout(panel);
dgl.row().center().group(group).add(scrollPaneContainingTable).fill();
centerPanel.add(panel, BorderLayout.CENTER);
getContentPane().add(centerPanel);
centerPanel.setVisible(true);

Затем каждый раз, когда пользователь выбирает элемент из JList, я запрашиваю базу данных и извлекаю записи, связанные с выбранным значением:

public void listSelectionChanged() {
    bloque = alBloque.get(listBloque.getSelectedIndex());
    //bloque is another entity, alBloque is an ArrayList<Bloque> from which the JList (named listBloque) ListModel is constructed.
    try {
        //database query here, omitted
        if (result.getStatus() == SUCCESS) {
            //the query returned a populated ArrayList<Lote>
            alLote = result.getArray();
            ((LoteTableModel) myTable.getModel()).createTableData(alLote);
            myTable.revalidate();
        }
    } catch (Exception e) {}
}

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

Любая помощь будет оценена.


person Noe    schedule 05.03.2013    source источник
comment
Не глотайте исключения.   -  person trashgod    schedule 05.03.2013
comment
На самом деле это было сделано для сокращения при создании вопроса. Делаю multicatch для java.io.IOException и ClassNotFoundException.   -  person Noe    schedule 05.03.2013
comment
попробуйте покрасить панель содержимого. Это обновляет графический интерфейс.   -  person shriguru nayak    schedule 05.03.2013
comment
Я не знаю, почему вы переводите ArrayList в Object[][], мне кажется, что у вас есть все данные, необходимые для модели таблицы, хранящиеся в ArrayList.   -  person MadProgrammer    schedule 05.03.2013
comment
@shrigurunayak, если модель правильно зарегистрирована в таблице и таблица добавлена ​​к просматриваемому компоненту, тогда метод fireTableStructureChanaged потребует, чтобы таблица перерисовывала себя (а также перестраивала свою модель столбца и сбрасывала свои средства визуализации и редакторы)   -  person MadProgrammer    schedule 05.03.2013
comment
Единственное, что приходит на ум из фрагмента, это убедиться, что вы применяете значения таблицы к модели изнутри в контексте EDT.   -  person MadProgrammer    schedule 05.03.2013
comment
@MadProgrammer Спасибо. Это была проблема, с которой я столкнулся, когда создавал настольное приложение с помощью swings. Просто поделился своим опытом.   -  person shriguru nayak    schedule 05.03.2013
comment
всего пара комментариев: а) в модели с правильным поведением никогда нет необходимости в повторной проверке или наоборот: если повторная проверка устраняет проблему с обновлением, что-то неправильно с вашей моделью б) вы, скорее всего, хотите обновить данные только один раз после окончательного изменения выбора, чтобы убедиться, что проверяется свойство getValueIsAdjusting события   -  person kleopatra    schedule 05.03.2013
comment
Большое спасибо за ваши комментарии. Я проверю предложение @MadProgrammer, чтобы убедиться, что я в контексте EDT. @kleopatra, на самом деле событие listSelectionListener запускает поведение valueChanged только тогда, когда getValueIsAdjusting имеет значение false.   -  person Noe    schedule 05.03.2013
comment
Я проверил код, изменения вносятся в EDT. Действительно как-то странно. Я буду продолжать искать. Большое спасибо, ребята.   -  person Noe    schedule 05.03.2013
comment
@Noe Внесите свое последнее изменение, касающееся решения этого вопроса, опубликовав его ниже, а затем отметьте его как принятый ответ, нажав на галочку. Удачи в поиске решения!   -  person Anthony Neace    schedule 06.03.2013
comment
@HyperAnthony, спасибо, я так и сделал :)   -  person Noe    schedule 06.03.2013


Ответы (1)


Я нашел проблему, и, как я думал, это была проблема с графическим интерфейсом, а не с обновлением, а с неправильным использованием пакета Layout :)

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

Я поместил таблицу в RowGroup и вызвал метод show(), когда в базе данных были результаты, и таблица была загружена с этими результатами, таким образом отображая их; Я вызывал метод hide(), когда результатов не было найдено и, следовательно, таблица будет пустой, поэтому я его скрываю.

Дело в том, что вызов метода hide() является кумулятивным... Если бы я вызвал метод 3 раза, мне также нужно было бы вызвать метод show() 3 раза, чтобы показать его, поэтому, если я выберу 3 последовательных строки в моем JList с пустыми наборами результатов для таблицы, я буду вызывать метод hide() 3 раза, поэтому, когда я выберу строку, которая действительно имеет результаты для таблицы, я буду вызывать метод show() только один раз, поэтому таблица никогда не будет отображаться должным образом. до 3 попыток выбора строк с результатами для таблицы.

Я поместил поле управления, которое заставляет приложение вызывать метод hide() только один раз, потому что, к сожалению, пакет DesignGridLayout не включает метод isHide() для проверки, был ли вызван hide().

Спасибо большое за вашу поддержку. Мой загадочный вопрос теперь решен.

person Noe    schedule 06.03.2013
comment
DesignGridLayout RowGroup не может иметь isHidden() API, поскольку у него нет собственного состояния. Он просто делегирует show() и hide() принадлежащим ему строкам. - person jfpoilpret; 18.05.2013
comment
Однако должно быть возможно добавить новый API в rows и RowGroup, например forceShow(), который будет отображать строку (или все строки в группе), даже если hide() вызывался много раз до этого. - person jfpoilpret; 18.05.2013
comment
@jfpoilpret, это действительно было бы здорово. Я понимаю, почему у нас не может быть тестового метода, но также полезно иметь метод, который заставляет отображать строки. Спасибо за ваш комментарий. - person Noe; 18.05.2013