обновление JList с помощью DefaultListModel

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

Я сделал функцию, которая должна инициализировать и обновлять список под названием populateList().

Вот соответствующие части моего кода:

public class GUI extends JFrame{
    private int maxBankNr;
    private BankAccountDAO bankAccountDAO;
    private DBManager dbm;
    ...

    public GUI(){
        initComponents(); //sets up the Swing GUI
        this.dbm = new DBManager();
        this.bankAccountDAO = dbm.getBankAccountDAO();
        ...

        populateList();

    }

    private void populateList(){
        updateAll = false; //this seems to stop baAccountListValueChanged from throwing an exception
        this.maxBankNr = bankAccountDAO.getMaxBankNr(); //max number of bank accounts in database
        BankAccount ba;
        DefaultListModel dlm = new DefaultListModel();

        baAccountList.setModel(dlm);

        for(int i = 1; i <= this.maxBankNr; i++){
            ba = bankAccountDAO.getBankAccount(i);

            dlm.addElement(ba.getName());
        }

    updateAll = true;
}
...

private void baRefreshButtonActionPerformed(java.awt.event.ActionEvent evt){                                                
    populateList();
} 

...

Моя проблема в том, что populateList() работает нормально, когда программа запускается, но когда она вызывается из baRefreshButtonActionPerformed, она ничего не делает. Список остается точно таким же.

Я пробовал множество разных подходов, таких как использование вектора, использование JList.setListData(), повторная проверка, проверка и перерисовка всех соответствующих контейнеров. Я также пытался использовать различные типы ListModel.

Кроме того, я читал, что вызов fireContentsChanged() должен работать, но DefaultListModel этого не позволяет, и я уверен, что он все равно вызывается автоматически.

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

Я надеюсь, что это достаточно информации, дайте мне знать, если вам нужно знать что-то еще, спасибо.

РЕДАКТИРОВАТЬ Мне наконец удалось это исправить, к моему большому облегчению :D

Это вообще не имело ничего общего с моим ListModel, но имело отношение к моему классу BankAccountDAO. Это старая версия:

package com.accounts;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class BankAccountDAO {
private String insertBankAccountSQL =
        "INSERT INTO accounts.bankaccounts(bankNr, sortCode, accountNumber, balance, interest, details, name) " +
        "VALUES (?, ?, ?, ?, ?, ?, ?)";

private String getBankAccountSQL = 
        "SELECT bankNr, sortCode, accountNumber, balance, interest, details, name " +
        "FROM accounts.bankaccounts WHERE bankNr = ?";

private Connection conn = null;
private PreparedStatement pstmt = null;
private int maxBankNr = 0;

public BankAccountDAO(Connection theConn){
    this.conn = theConn;

    try{
        this.pstmt = conn.prepareStatement(getBankAccountSQL);

        Statement stmt = conn.createStatement();

        ResultSet rs = stmt.executeQuery("SELECT MAX(bankNr) FROM accounts.bankaccounts");

        if(rs.next()){
            maxBankNr = rs.getInt(1);

        }

        rs.close();
        stmt.close();
    }catch(SQLException se){
       printSQLException(se); 
    }
}

public int getMaxBankNr(){     
    return(this.maxBankNr);
}

public void insertBankAccount(int bankNr, int sortCode, int accountNumber, double balance, double interest, String details, String name){
    PreparedStatement ins = null;

    try{
        ins = conn.prepareStatement(insertBankAccountSQL);
        ins.setInt(1, bankNr);
        ins.setInt(2, sortCode);
        ins.setInt(3, accountNumber);
        ins.setDouble(4, balance);
        ins.setDouble(5, interest);
        ins.setString(6, details);
        ins.setString(7, name);

        ins.execute();
    }catch(SQLException se){
        printSQLException(se);
    }
}

public BankAccount getBankAccount(int targetBankNr){
    BankAccount ba = null;

    try{
        pstmt.clearParameters();
        pstmt = conn.prepareStatement(getBankAccountSQL);
        pstmt.setInt(1, targetBankNr);

        ResultSet rs = pstmt.executeQuery();

        if(rs.next()){
            int bankNr = rs.getInt("bankNr");
            int sortCode = rs.getInt("sortCode");
            int accountNumber = rs.getInt("accountNumber");
            double balance = rs.getDouble("balance");
            double interest = rs.getDouble("interest");
            String details = rs.getString("details");
            String name = rs.getString("name");

            ba = new BankAccount(bankNr, sortCode, accountNumber, balance, interest, details, name);

        }

        rs.close();
    }catch(SQLException se){
        printSQLException(se);
    }

    return ba;
}

private void printSQLException(SQLException se){
    while(se != null){

        System.out.print("SQLException: State: " + se.getSQLState());
        System.out.println("Severity:            " + se.getErrorCode());
        System.out.println(se.getMessage());

        se = se.getNextException();
    }
}
}

Я изменил геттер getMaxBankNr() следующим образом:

public int getMaxBankNr(){
    try{
        Statement stmt = conn.createStatement();

        ResultSet rs = stmt.executeQuery("SELECT MAX(bankNr) FROM accounts.bankaccounts");


        if(rs.next()){
            maxBankNr = rs.getInt(1);

        }
    }catch(SQLException e){
        printSQLException(e);
    }

    return(this.maxBankNr);
}

При вызове this.maxBankNr = bankAccountDAO.getMaxBankNr() он не возвращал обновленный maxBankNr. Для возврата правильного значения требовался новый оператор SQL.

Любой, кто использует базу данных со списком так же, как я (я заметил довольно много людей с той же проблемой, что и я, когда гуглил), должен убедиться, что цикл for действительно знает, сколько раз повторять .

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


person kyul    schedule 19.05.2013    source источник
comment
1) Чтобы быстрее получить помощь, опубликуйте SSCCE. 2) Если сомневаетесь, распечатайте! Удачный вызов System.out.println(thing.toString()) может избавить от многих головных болей. В качестве альтернативы используйте отладчик вашей IDE для пошагового выполнения кода. 3) Не расширяйте рамку или другие контейнеры верхнего уровня. Вместо этого создайте и используйте экземпляр одного.   -  person Andrew Thompson    schedule 19.05.2013


Ответы (2)


Хм... Это сложно. Я думаю, что если populateList() работает сам по себе, то baRefresButtonActionPerformed сам по себе не выполняется.

Я бы попробовал обычный ActionEvent и ActionPerformed в качестве слушателя или поместил в него какой-то вывод, например, если baRefreshButtonActionPerformed, чтобы он показывал всплывающее окно, сообщающее, что переопределение выполнено.

Удачного кодирования!

person Galen Nare    schedule 19.05.2013
comment
Спасибо, Гален Наре :) Я сделал System.out.println() и baRefreshButtonActionPerformed определенно вызывается :( - person kyul; 19.05.2013

Обычно вы должны вызвать один из следующих методов, чтобы уведомить объект JList об измененных данных, как это уместно:

fireContentsChanged(Object source, int index0, int index1)
fireIntervalAdded(Object source, int index0, int index1) 
fireIntervalRemoved(Object source, int index0, int index1)

См. документ API для модели AbstractListModel.

person Hakan Serce    schedule 19.05.2013
comment
Это не обязательно для DefaultListModel. - person Hovercraft Full Of Eels; 19.05.2013
comment
На самом деле вы правы. DefaultListModel вызывает внутренние методы fireXXX по мере необходимости. Спасибо. - person Hakan Serce; 19.05.2013
comment
в других случаях хороший ответ, но я думаю, что о EDT, потому что вызвал эти (d) эффекты :-) или baAccountList.setModel(dlm); должна быть последней строкой кода в конструкторе или недействительной, что угодно - person mKorbel; 19.05.2013