4

やあ、

TableModel を作成しましたが、新しい行を追加したら JTable を更新したいと考えています。JTable を「リフレッシュ」するには、リスナーに何を追加する必要がありますか?

public class MyTableModel implements TableModel  {
    private Set<TableModelListener> listeners = new HashSet<TableModelListener>();

    //List<Staff> staffs = Factory.getInstance().getStaffDAO().getAllStaff();
    private List<Staff> staffs;

    public MyTableModel(List<Staff> staffs){
        this.staffs = staffs;
    }

    @Override
    public int getRowCount() {
        return staffs.size();
    }

    @Override
    public int getColumnCount() {
        return 5;  
    }

    @Override
    public String getColumnName(int columnIndex) {
        switch (columnIndex){
            case 0:
                return "First Name";
            case 1:
                return "Second Name";
            case 2:
                return "Date";
            case 3:
                return "Position";
            case 4:
                return "Salary";
        }
        return "";  
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return Object.class;  
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return true;  
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Staff staff = staffs.get(rowIndex);
        switch (columnIndex){
            case 0:
                return staff.getName();
            case 1:
                return staff.getSurname();
            case 2:
                return staff.getDate();
            case 3:
                return staff.getPosition();
            case 4:
                return staff.getSalary();
        }
        return "";  
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    }

    @Override
    public void addTableModelListener(TableModelListener l) {
    }

    @Override
    public void removeTableModelListener(TableModelListener l) {
    }
}

行追加ボタンのリスナーは次のとおりです。

 @Override
    public void actionPerformed(ActionEvent e) {
        Staff staff = new Staff();
        staff.setName(JOptionPane.showInputDialog("Enter First Name"));
        staff.setSurname(JOptionPane.showInputDialog("Enter Second Name"));
        staff.setDate(JOptionPane.showInputDialog("Enter Date"));
        staff.setPosition(JOptionPane.showInputDialog("Enter Position"));
        staff.setSalary(JOptionPane.showInputDialog("Enter Salary"));
        try {
            Factory.getInstance().getStaffDAO().addStaff(staff);
        } catch (SQLException e1) {
            e1.printStackTrace();  
        }
!!!Here should be some code that will be firing my table after adding new row!!!
}

actionPerformed() で AbstractTableModel のメソッド firetabledatachanged() を使用しようとしましたが、運が悪く、ClassCastException が表示されます。

更新 1

WorkPlaceGui.java

public class WorkPlaceGui extends JFrame implements ActionListener {

    AbstractTableModel model;
    JTable jTable;
    JScrollPane jScrollPane;

    public WorkPlaceGui()throws SQLException{


        List<Staff> staffs = Factory.getInstance().getStaffDAO().getAllStaff();
        for(int i = 0; i < 0; i++) {
                staffs.add(new Staff("First Name " + staffs.get(i).getName(), "Second Name " + staffs.get(i).getSurname(), "Date " + staffs.get(i).getDate(), "Position " + staffs.get(i).getPosition(), "Salary " + staffs.get(i).getSalary()));
        }

        model = new MyTableModel(staffs);
        jTable = new JTable(model);
        JButton jBtnAdd = new JButton("Добавить");
        JButton jBtnDel = new JButton("Удалить");
        JButton jBtnUpd = new JButton("Обновить");
        JButton jBtnAdmin = new JButton("Админка");
        JPanel panelNorth = new JPanel();
        JPanel panelCenter = new JPanel();
        JPanel panelSouth = new JPanel();
        jTable.setPreferredScrollableViewportSize(new Dimension(350, 150));
        jScrollPane = new JScrollPane(jTable);


        panelNorth.setLayout(new FlowLayout());
        panelNorth.add(jBtnAdd);
        panelNorth.add(jBtnDel);
        panelNorth.add(jBtnUpd);
        panelNorth.add(jBtnAdmin);
        panelCenter.add(jScrollPane);

        setLayout(new BorderLayout());
        add(panelNorth, BorderLayout.NORTH);
        add(panelCenter, BorderLayout.CENTER);

        jBtnAdd.addActionListener(this);

        setPreferredSize(new Dimension(550, 300));
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setTitle("Staff data base");
        pack();
        setVisible(true);
        setLocationRelativeTo(null);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Staff staff = new Staff();
        staff.setName(JOptionPane.showInputDialog("Enter First Name"));
        staff.setSurname(JOptionPane.showInputDialog("Enter Second Name"));
        staff.setDate(JOptionPane.showInputDialog("Enter Date"));
        staff.setPosition(JOptionPane.showInputDialog("Enter Position"));
        staff.setSalary(JOptionPane.showInputDialog("Enter Salary"));
        try {
            Factory.getInstance().getStaffDAO().addStaff(staff);
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
        model.fireTableDataChanged();
    }
}

MyTableModel.java

public class MyTableModel extends AbstractTableModel {

    private List<Staff> staffs;

    public MyTableModel(List<Staff> staffs){
        this.staffs = staffs;
    }

    @Override
    public int getRowCount() {
        return staffs.size();
    }

    @Override
    public int getColumnCount() {
        return 5;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Staff staff = staffs.get(rowIndex);
        switch (columnIndex){
            case 0:
                return staff.getName();
            case 1:
                return staff.getSurname();
            case 2:
                return staff.getDate();
            case 3:
                return staff.getPosition();
            case 4:
                return staff.getSalary();
        }
        return "";
    }
}

4

6 に答える 6

12

あなたはそれを難し​​い方法でやりました。

まず第一に、あなたはから直接実装しTableModelました.第二に、リスナーの要件を実装できませんでした...

AbstractTableModel代わりに、リスナの登録と通知の実装がすでに含まれている代わりにから拡張してみてください。

テーブル モデルに行を追加できるメソッドを提供する必要があります。fireTableRowsInsertedこのメソッドでは、新しい行が追加されたことをモデルを使用してすべてのテーブルに通知するメソッドを使用する必要があります...

例で更新

これは非常に基本的な例です。の使用方法を示すことのみを目的としていますfireTableRowsInserted。SwingTimerを使用して、kill するまで 125 ミリ秒ごとに新しい行を追加します ;)

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;

public class DynamicTable {

    public static void main(String[] args) {
        new DynamicTable();
    }

    public DynamicTable() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
                
                final MyTableModel model = new MyTableModel();
                JTable table = new JTable(model);
                
                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                
                Timer timer = new Timer(125, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        model.addRow();
                    }
                });
                timer.start();
            }
        });
    }
    
    public class MyTableModel extends AbstractTableModel {

        private List<String[]> rows;

        public MyTableModel() {
            rows = new ArrayList<>(25);
        }
        
        @Override
        public int getRowCount() {
            return rows.size();
        }

        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            String[] row = rows.get(rowIndex);
            return row[columnIndex];
        }
        
        public void addRow() {
            int rowCount = getRowCount();
            String[] row = new String[getColumnCount()];
            for (int index = 0; index < getColumnCount(); index++) {
                row[index] = rowCount + "x" + index;
            }
            rows.add(row);
            fireTableRowsInserted(rowCount, rowCount);
        }            
    }                    
}

別の例で更新

テーブル モデルは独自の によってサポートされているListため、ファクトリには接続されていません。オブジェクトをいつ追加または削除するかはわかりません。これは、モデルの更新を担当することを意味します。

public class MyTableModel extends AbstractTableModel {

    private List<Staff> staffs;

    public MyTableModel(List<Staff> staffs){
        this.staffs = staffs;
    }

    @Override
    public int getRowCount() {
        return staffs.size();
    }

    @Override
    public int getColumnCount() {
        return 5;
    }
    
    public void add(Staff staff) {
        int size = getSize();
        staffs.add(staff);
        fireTableRowsInserted(size, size);
    }

    public void remove(Staff staff) {
        if (staffs.contains(staff) {
            int index = stafff.indexOf(staff);
            staffs.remove(staff);
            fireTableRowsDeleted(index, index);
        }
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Staff staff = staffs.get(rowIndex);
        switch (columnIndex){
            case 0:
                return staff.getName();
            case 1:
                return staff.getSurname();
            case 2:
                return staff.getDate();
            case 3:
                return staff.getPosition();
            case 4:
                return staff.getSalary();
        }
        return "";
    }
}

そしてあなたのactionPerformed

@Override
public void actionPerformed(ActionEvent e) {
    Staff staff = new Staff();
    staff.setName(JOptionPane.showInputDialog("Enter First Name"));
    staff.setSurname(JOptionPane.showInputDialog("Enter Second Name"));
    staff.setDate(JOptionPane.showInputDialog("Enter Date"));
    staff.setPosition(JOptionPane.showInputDialog("Enter Position"));
    staff.setSalary(JOptionPane.showInputDialog("Enter Salary"));
    try {
        Factory.getInstance().getStaffDAO().addStaff(staff);
        ((MyTableModel)model).add(staff);
    } catch (SQLException e1) {
        e1.printStackTrace();  
    }
}
于 2013-05-28T07:23:26.677 に答える
8

あなたのクラスは をMyTableModel実装TableModelしていますが、モデルをビューに接続するためのイベント処理メカニズムがありません。ここここAbstractTableModelに示すように、代わりに拡張します。これに必要なメソッドを提供します。AbstractTableModelfireTable*

public void setValueAt(Object value, int row, int col) {
    data[row][col] = value;
    fireTableCellUpdated(row, col);
}
于 2013-05-28T07:22:29.830 に答える
3

まず、Observer パターン( http://en.wikipedia.org/wiki/Observer_pattern ) について詳しく調べてください。

PropertyChangeListeners のリストを持つObservableModelクラスを作成することをお勧めします。StaffDAOは、このObservableModelを拡張する必要があります。新しいスタッフが追加されたとき (つまり、呼び出されたとき)、ObservableModel などを呼び出す必要があります。つまり、すべての propertyChangeListeners です。それらのリスナーの 1 つをテーブルに登録する必要があり、そのメソッドはテーブル (hd1) を更新して実装する必要があります。addStafffirePorpertyChangefirePropertyChange notifypropertyChanged

于 2013-05-28T07:33:58.270 に答える
2

myTableModel.fireTableDataChanged();テーブルを強制的に更新するのに十分なはずです。いつものように、さらに問題がある場合は、お気軽にコメントを残してください。

于 2013-05-28T07:22:15.880 に答える
2

より一般的な解決策として、Row Table Modelを使用して getValueAt() および setValueAt() メソッドを実装するだけです。

新しい行を追加した後にテーブルを起動するコードを次に示します。

モデルは、適切な fireXXX メソッドを呼び出す責任があります。

于 2013-05-28T16:08:04.520 に答える