无法使用新数据刷新我的JTable

时间:2013-06-13 17:10:32

标签: java swing jtable tablemodel abstracttablemodel

我在初始创建框架时创建JTable,但创建一个我扩展的空AbstractTableModel。然后,用户必须从JComboBox中选择一些内容,并且用户可以预览处理该指定选择的消息。

单击预览按钮时,我使用新数据创建一个新的AbstractTableModel,并将该模型设置为新创建的JTable对象。完成后,我致电AbstractTableModel.fireTableDataChangedJTable.repaint()JTable.validate() JFrame.repaint()JFrame.validate()

通过所有这些调用,我仍然无法使用新数据刷新JTable

我的JFrameJTable

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

我延长TableModel的{​​{1}}课程:

AbstractTableModel

2 个答案:

答案 0 :(得分:0)

所以我明白了。在setTableData()类的StudentMessageViewer方法中,我创建了一个全新的TableModel对象和一个全新的JTable对象,但是将这两个新对象分配给原始变量。所以我可能不得不做repaint()validate(),但我无法理解。

但要修复它,我所做的就是创建一个全新的TableModel对象,并使用JTable.setModel()替换旧的TableModel

以下是修改过的方法:

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

现在我可以多次更新表格了。

答案 1 :(得分:0)

AbstractTableModel支持表在其上注册自己的侦听器,以响应内容更改。但是AbstractTableModel它不知道基础数据何时实际上变得不同 - 这已经完全在您的代码中。

当您知道数据现在不同时,尝试从模型中调用fireTableDataChanged或模型(更糟糕的样式),或者对于有限范围的已知更改,更不愿意像fireTableRowsUpdated那样。