Search code examples
javaswingjtabletablemodelabstracttablemodel

Can't refresh my JTable with new data


I create a JTable when the frame is intially created, but create an empty AbstractTableModel which I extended. Then the user has to select something from a JComboBox and the user can preview the messages dealing with that specified selection.

When the preview button is clicked, I create a new AbstractTableModel with the new data and set that model to a newly created JTable object. Once that is done, I call AbstractTableModel.fireTableDataChanged, JTable.repaint(), JTable.validate() JFrame.repaint(), JFrame.validate().

With all those calls, I still can't get the JTable to refresh with the new data.

My JFrame with the JTable:

public class StudentMessageViewer extends JFrame implements ActionListener {
    final String CMD_DELETE = "CMD_DELETE";
    final String CMD_DUMP = "CMD_DUMP";
    final String CMD_MOVE = "CMD_MOVE";
    final String CMD_PREVIEW = "CMD_PREVIEW";
    private Students students;
    private JComboBox<String> Names;
    private TableModel Model;

    public Selector(Students students) {
        super("Main");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(new Dimension(700, 800));
        setContentPane(getMainPanel());
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private JPanel getMainPanel() {
        JPanel main = new JPanel();
        main.add(getSelectorPanel());
        main.add(getTablePanel());
        main.add(getButtonPanel());

        return main;
    }

    private JPanel getSelectorPanel() {
        JPanel main = new JPanel();
        main.setLayout(new BoxLayout(main, BoxLayout.PAGE_AXIS));

        FlowLayout flowLayout = new FlowLayout(FlowLayout.RIGHT);
        main.setMaximumSize(new Dimension(450, 180));
        Names = new JComboBox<String>(students.getNames());

        JPanel NamesPanel = new JPanel();
        NamesPanel.add(new JLabel("Name: "));
        NamesPanel.add(Names);

        main.add(NamesPanel);

        return main;
    }

    private JPanel getTablePanel() {
        JPanel main = new JPanel();    

        this.Model = new Model(new Object[0][4]);
        this.MessagesTable = new JTable(this.Model);

        TableColumn column = this.MessagesTable.getColumnModel().getColumn(0);
        column.setPreferredWidth(20);
        this.MessagesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        this.MessagesTable.setSelectionBackground(getBackground());
        this.MessagesTable.setSelectionForeground(getForeground());

        main.add(new JScrollPane(this.MessagesTable));

        return main;
    }

    private JPanel getButtonPanel() {
        JPanel main = new JPanel(new FlowLayout(FlowLayout.RIGHT));

        JButton btnDelete = new JButton("Delete");
        JButton btnDump = new JButton("Dump");
        JButton btnMove = new JButton("Move");
        JButton btnPreview = new JButton("Preview");

        btnDelete.setActionCommand(CMD_DELETE);
        btnDump.setActionCommand(CMD_DUMP);
        btnMove.setActionCommand(CMD_MOVE);
        btnPreview.setActionCommand(CMD_PREVIEW);

        btnDelete.addActionListener(this);
        btnDump.addActionListener(this);
        btnMove.addActionListener(this);
        btnPreview.addActionListener(this);

        main.add(btnDelete);
        main.add(btnDump);
        main.add(btnMove);
        main.add(btnPreview);

        this.getRootPane().setDefaultButton(btnPreview);

        return main;
    }

    private void setTableData() {        
        Object data[][] = students.Select(Names.getSelectedItem().toString());

        this.Model = new Model(data);
        this.MessagesTable = new JTable(this.Model);

        TableColumn column = this.MessagesTable.getColumnModel().getColumn(0);
        column.setPreferredWidth(20);
        this.MessagesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        this.MessagesTable.setSelectionBackground(getBackground());
        this.MessagesTable.setSelectionForeground(getForeground());

        ((AbstractTableModel) this.MessagesTable.getModel()).fireTableDataChanged();
        this.MessagesTable.repaint();
        this.repaint();
        this.validate();
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        String actionCmd = event.getActionCommand();

        if(actionCmd.equals(CMD_DELETE))
            System.out.println("DELETE");
        else if(actionCmd.equals(CMD_DUMP))
            System.out.println("DUMP");
        else if(actionCmd.equals(CMD_MOVE))
            System.out.println("MOVE");
        else if(actionCmd.equals(CMD_PREVIEW))
            setTableData();
    }
}

My TableModel class which I extended AbstractTableModel:

public class Model extends AbstractTableModel {
    Object data[][];
    String columnNames[] = { "", "Message ID", "Group ID", "DateSent", "Message"};

    public Model(Object[][] data) {
        this.data = new Object[data.length][columnNames.length];
        for (int i = 0; i < data.length; i++) {
            this.data[i][0] = Boolean.TRUE;
            for (int j = 0; j < columnNames.length - 1; j++)
                this.data[i][j + 1] = data[i][j];
        }
    }

    public int getColumnCount() {
        return (columnNames == null ? 0 : columnNames.length);
    }

    public String getColumnName(int column) {
        return (columnNames == null ? "" : columnNames[column]);
    }

    public int getRowCount() {
        return (data == null ? 0 : data.length);
    }

    public Object getValueAt(int row, int column) {
        return (columnNames == null ? new Object() : data[row][column]);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public Class getColumnClass(int column) {
        return (getValueAt(0, column).getClass());
    }

    public void setValueAt(Object value, int row, int column) {
        data[row][column] = value;
    }

    public boolean isCellEditable(int row, int column) {
        return (column == 0);
    }
}

Solution

  • So I figured it out. In the setTableData() method of StudentMessageViewer class, I was creating a brand new TableModel object and a brand new JTable object, but assign these two new objects to the original variable. So I might have had to do a repaint() or a validate() but I couldn't figure that out.

    But to fix it, what I did was create a brand new TableModel object and use the JTable.setModel() to replace the old TableModel.

    Here's the modified method:

    private void setTableData() {        
        Object data[][] = students.Select(Names.getSelectedItem().toString());
    
        this.Model = new Model(data);
    
        TableColumn column = this.MessagesTable.getColumnModel().getColumn(0);
        column.setPreferredWidth(20);
        this.MessagesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        this.MessagesTable.setSelectionBackground(getBackground());
        this.MessagesTable.setSelectionForeground(getForeground());
    
        this.MessagesTable.setModel(this.MyModel);
    }
    

    Now I'm able update the table as many times I want.