AbstractTableModel GUI显示问题

时间:2016-01-12 08:34:06

标签: java swing jdbc jtable abstracttablemodel

我正在为数据库创建一个GUI项目,有两个类用于GUI's。连接器类用于连接用户凭据。如果凭据正确,则获取AbstractTableModel中的所有数据。当程序首先运行时GUI有一个按钮,我们在其中单击它并获取基础TableModel中的所有数据。但我面临两个问题。首先在GUI2课程中,有时它会像这样打开。

enter image description here

有时会显示如下

http://imageshack.com/i/p3gBDt9Ej

我不知道为什么会这样。第二个问题是当我们从表中选择任何行并单击DeleteSelectedRow按钮时它会删除该行。此按钮在ActionListener课程中有GUI2。但我想要的是我删除行时自动更新表。我怎么能这样做?

第一个GUI

的课程
public class Gui extends JFrame {
    private static Connector conni;
    private Connection conn = null;
    private JButton bt;
    private JPanel panel;

    public Gui() {
        super("Frame");
        panel = new JPanel();
        bt = new JButton("Connect to Database 'World'");
        panel.add(bt);
        bt.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                conn = conni.Connector();

                if (conn != null) {
                    dispose();
                    new Gui2(conn);

                } else {
                    System.out.println("Return false");

                }

            }

        });
        add(panel);

        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);

    }

}

连接器类

public class Connector {

    private static Connection conn = null;

    public static Connection Connector() {
        String data = "jdbc:mysql://localhost/world";
        String user = "root";
        String pass = "toot";
        try {
            conn = DriverManager.getConnection(data, user, pass);

        } catch (Exception e) {

            JOptionPane.showMessageDialog(null, e.getMessage());

        }
        if (conn != null) {

            System.out.println("Connection Suceess");
            return conn;

        } else {

            return conn;

        }

    }

}

第二个GUI2

的课程
public class Gui2 extends JFrame {
    private Statement state = null;
    private ResultSet rs = null;

    private JButton bt, delete;
    private JTextField text;
    private JPanel panel;
    private GridBagLayout layout;
    private GridBagConstraints constraints;

    public Gui2(Connection conn) {
        layout = new GridBagLayout();
        constraints = new GridBagConstraints();
        panel = new JPanel();
        panel.setLayout(layout);

        text = new JTextField(15);
        bt = new JButton("Submit Query");
        delete = new JButton("Delete Selected Row");
        constraints.insets = new Insets(5, 2, 5, 10);
        constraints.gridy = 0;// row 0
        constraints.gridx = 0;// column 0
        // TextField add on JPanel with given constraints
        panel.add(text, constraints);
        constraints.gridx++;
        panel.add(delete, constraints);
        constraints.gridx++;
        panel.add(bt, constraints);

        // North BorderLayout
        add(panel, BorderLayout.NORTH);

        try {
            state = conn.createStatement();
            rs = state.executeQuery("select * from city");
        } catch (SQLException e) {

            JOptionPane.showMessageDialog(null, e.getMessage());
        }

        JTable table = new JTable();
        JScrollPane spane = new JScrollPane(table);

        add(spane, BorderLayout.CENTER);

        table.setModel(new TableModel(rs));

        delete.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                int rowIndex = table.getSelectedRow();

                Object columnIndexValue = table.getModel().getValueAt(rowIndex, 0);

                String columnName = table.getModel().getColumnName(0);

                String query = "delete from world.city" + " where " + columnName + "=" + columnIndexValue;

                try {

                    PreparedStatement pre = conn.prepareStatement(query);

                    pre.executeUpdate();

                    JOptionPane.showMessageDialog(null, "Row Deleted Successfully");
                } catch (Exception e1) {
                    JOptionPane.showMessageDialog(null, e1.getMessage());
                }

            }

        });

        setSize(817, 538);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);

    }

}

Tablemodel班级

public class TableModel extends AbstractTableModel {

    private List ColumnHeader;
    private List tableData;
    private List rowData;

    private int totalcolumn;

    public TableModel(ResultSet rs) {

        try {

            ResultSetMetaData meta = rs.getMetaData();

            totalcolumn = meta.getColumnCount();

            ColumnHeader = new ArrayList(totalcolumn);

            tableData = new ArrayList();

            for (int i = 1; i <= totalcolumn; i++) {
                ColumnHeader.add(meta.getColumnName(i));

            }
        } catch (Exception e) {

            JOptionPane.showMessageDialog(null, e.getMessage());
        }

        SwingWorker<Boolean, List<Object>> worker = new SwingWorker<Boolean, List<Object>>() {

            @Override
            protected Boolean doInBackground() throws Exception {

                while (rs.next()) {

                    rowData = new ArrayList(totalcolumn);
                    for (int i = 1; i <= totalcolumn; i++) {
                        rowData.add(rs.getObject(i));
                    }
                    publish(rowData);


                }

                return true;

            }

            @Override
            protected void process(List chunks) {
                tableData.add(chunks);

            }

            @Override
            protected void done() {
                try {
                    Boolean status = get();
                    JOptionPane.showMessageDialog(null, "Task is DONE");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }

        };

        worker.execute();
    }// constructor end



    @Override
    public int getColumnCount() {

        return ColumnHeader.size();
    }

    public String getColumnName(int columnIndex) {
        return (String) ColumnHeader.get(columnIndex);

    }

    @Override
    public int getRowCount() {

        return tableData.size();
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {

        List rowData2 = (List) tableData.get(rowIndex);

        return rowData2.get(columnIndex);
    }

}

1 个答案:

答案 0 :(得分:6)

由于数据库访问本质上是异步的,因此您肯定希望在后台检索行以避免阻止event dispatch thread; SwingWorker使这相对容易。在doInBackground()publish()中间结果的实现中获取行,并将它们添加到process()实现中的表模型中。显示了一个完整的示例,概述了随之而来的好处here。该示例循环遍历文件,但您可以替换ResultSet操作。

while (rs.next()) {
    //collect row data
    publish(rowData);
}

tableData.add()推迟到process()

的实施

关注自定义TableModel及其包含的SwingWorker之间的互动,以下complete example会创建一个包含N行的测试数据库并显示JTable显示该表的查询结果。特别是,

  • JDBCModel扩展AbstractTableModel。为简单起见,模型data存储在List<Row>中,ResultSetMetaData用于列名称。作为一个更抽象的替代方案,请参阅Apache Commons DbUtils,它使用Class Literals as Runtime-Type TokensResultSetMetaData来安全地创建行数据的实例。

  • JDBCModel将行检索委托给私人JDBCWorker;它在从publish()检索到的每一行上调用ResultSet;因为process()在EDT上运行,所以工作人员可以使用fireTableRowsInserted()优化代表父模型触发的表模型事件的数量。

  • 同样,delete()的实现应该位于JDBCModel,而不是GUI;从数据库中成功删除行并从fireTableRowsDeleted()中删除后,它应data

  • Thread.sleep()添加到工作人员的后台循环中,以查看人为增加延迟的效果。

  • 使用setProgress()和显示herePropertyChangeListener来显示进度; <{1}},JOptionPane可能是多余的。

  • 覆盖done()以自定义包含getPreferredScrollableViewportSize()的表格的大小。

  • 避免使用类名,例如JScrollPane,与常见的API名称冲突。

  • 系统会检查在视图中实施实时filtering的变体here

image

TableModel