Can't refresh my JTable with new data

痞子三分冷 提交于 2019-12-11 04:42:58

问题


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);
    }
}

回答1:


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.




回答2:


AbstractTableModel supports listeners that the table registers itself on it to react to the content changes. However AbstractTableModel it is not aware when the underlying data actually become different - this is already fully in your code.

Try to call fireTableDataChanged from the model or (worse style) on the model when you know the data are now different, or something more reluctant like fireTableRowsUpdated for the known change of the limited scope.



来源:https://stackoverflow.com/questions/17093053/cant-refresh-my-jtable-with-new-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!