1

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

单击预览按钮时,我AbstractTableModel使用新数据创建一个新模型并将该模型设置为新创建的 JTable 对象。完成后,我调用AbstractTableModel.fireTableDataChanged, JTable.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扩展的课程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);
    }
}
4

2 回答 2

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

现在我可以根据需要多次更新表格。

于 2013-06-13T19:17:21.643 回答
0

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

当您知道数据现在不同时,尝试fireTableDataChanged从模型或模型上调用(更糟糕的样式),或者更不情愿的事情,例如fireTableRowsUpdated有限范围的已知变化。

于 2013-06-13T19:26:13.707 回答