【问题标题】:Autoupdate Jtable from JPanel to Jframe eclipse从 JPanel 自动更新 Jtable 到 Jframe eclipse
【发布时间】:2018-12-12 10:22:11
【问题描述】:

我的 JPanel 类中有数据库 JTable,我想在我的 JFRame 类中使用它

我希望通过单击一些按钮来自动更新我的 JTable
它不是错误,但它不想自动更新,除非我将 Jframe 放在 Jpanel 类上,这将创建一个新的 Frame

这是我的 JPanel

 public class TUsers extends JPanel {

    private static final long serialVersionUID = 1L;  

    String [] header = {"Id","name","address"};
    JTable BTab = new JTable(); 
    JScrollPane scrPnl = new JScrollPane();
    public Object [][] table = null;

     TUsers(){
        Dbcon dc = new Dbcon();
        Connection psql = dc.getConnection();
        try 
        {
            Statement stmt = psql.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
            String sql = "SELECT * FROM public.patrons ORDER BY id ASC";
            ResultSet res = stmt.executeQuery(sql);
            ResultSetMetaData meta = res.getMetaData();
            int y  = meta.getColumnCount();
            int x = 0;
            while(res.next())
            {
                y = res.getRow();
            }
            table = new Object[x][y];
            int n = 0;
            res.beforeFirst();
            while(res.next())
            {
                table[n][0]=res.getString("Id");
                table[n][1]=res.getString("name");
                table[n][2]=res.getString("address");
                x++;
            }
            scrPnl.setViewportView(BTab);
            BTab.setModel(new DefaultTableModel(table, header));
            TableColumnModel table = BTab.getColumnModel();

            table.getColumn(0).setPreferredWidth(2);
            table.getColumn(1).setPreferredWidth(100);
            table.getColumn(2).setPreferredWidth(180);

            scrPnl.setPreferredSize(new Dimension(350, 120));

            add(scrPnl, BorderLayout.CENTER);
            revalidate();
            repaint();
            stmt.close();
            res.close();

来自我的 JFrame 类

  public class AddUser extends JFrame {
    TUsers t = new TUsers();


AddUser()
{
    setTitle("Admin");
    setLocation(400,400);
    setSize(400, 400);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

}

    void Layout()
  {
   getContentPane().add(t).setBounds(10, 225, 350, 150);
   //if i delete this it wont show the table

    setVisible(true);
  } 



    void EventHandle() 
   {
  b_crt.addActionListener(new ActionListener() 
    {
        public void actionPerformed(ActionEvent e)
        {
            Dbcon dc = new Dbcon();
            Connection psql = dc.getConnection();
            try
            {
                Statement stmt = psql.createStatement();
                String sql = "INSERT INTO public.patrons VALUES ('"
                            +t_id.getText()+"','"
                            +t_usrnm.getText()+"','"
                            +t_adrs.getText()+"');";
                int i = stmt.executeUpdate(sql);
                if(i == i) 
                {
                    JOptionPane.showMessageDialog(null, "Success");
                }
                Clear();
            }
            catch(Exception x)
            {
                JOptionPane.showMessageDialog(null, x.getMessage());
            }

            TUsers t = new TUsers();

         }
        });
   }
}   

我已经放了
我的 JPanel 上的 repaint() 和 revalidate() 但它不起作用

【问题讨论】:

  • 当您认为数据库中的数据已更改时,您需要重新加载TableModel
  • 我在 Create ActionListener 上调用 Table 类,但它不会更改我的 JFrame 上的表,除非我重新打开它
  • 为什么要这样?您正在创建该类的一个新实例,该实例未显示在屏幕上,或者与屏幕上实际显示的任何内容有任何关系
  • 所以我必须在我的 ActionListener 中重新加载 TableModel? t.fireTableDataChanged();?
  • 不,表数据没变,数据库有,需要重新从数据库中拉取结果,更新表模型

标签: java swing user-interface awt


【解决方案1】:

好的,让我们退后一步,重新考虑一下您的 TUsers 课程。

当前的实现具有在类初始化阶段加载数据库信息的副作用。这有几个问题,主要问题是您无法在不创建新实例的情况下更新表。

更好的方法可能是简单地在构造函数中构建基本 UI,然后提供一个单独的“加载”方法,从数据库中重新加载数据,可能类似于...

public class TUsers extends JPanel {

    private static final long serialVersionUID = 1L;

    String[] header = {"Id", "name", "address"};
    JTable BTab = new JTable();
    JScrollPane scrPnl = new JScrollPane();

    TUsers() {
        // Build the UI
        setLayout(new BorderLayout());
        DefaultTableModel model = new DefaultTableModel(header, 0);
        BTab = new JTable(model);
        scrPnl.setViewportView(BTab);
        add(scrPnl);
    }

    public void loadData() throws SQLException {
        Dbcon dc = new Dbcon();
        String sql = "SELECT * FROM public.patrons ORDER BY id ASC";
        try (Connection psql = dc.getConnection();
                Statement stmt = psql.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                ResultSet res = stmt.executeQuery(sql)) {
            DefaultTableModel model = new DefaultTableModel(header, 0);
            while (res.next()) {
                String[] rowData = new String[3];
                rowData[0] = res.getString("Id");
                rowData[1] = res.getString("name");
                rowData[2] = res.getString("address");
                model.addRow(rowData);
            }
            BTab.setModel(model);
            BTab.getColumn(0).setPreferredWidth(2);
            BTab.getColumn(1).setPreferredWidth(100);
            BTab.getColumn(2).setPreferredWidth(180);
        }
    }
}

只要确保你在某个时候调用loadData,否则它会显示一个空表。

现在,如果您愿意,可以致电 loadData 并刷新表格...

public class AddUser extends JFrame {

    TUsers t = new TUsers();

    AddUser() {
        setTitle("Admin");
        setLocation(400, 400);
        setSize(400, 400);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        // When does t get added??
    }

    void Layout() {
        getContentPane().add(t).setBounds(10, 225, 350, 150);
        //if i delete this it wont show the table
        // This is a symptom of a different problem
        setVisible(true);
    }

    void EventHandle() {
        b_crt.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Dbcon dc = new Dbcon();
                String sql = "INSERT INTO public.patrons VALUES ('"
                        + t_id.getText() + "','"
                        + t_usrnm.getText() + "','"
                        + t_adrs.getText() + "');";
                try (Connection psql = dc.getConnection();
                        Statement stmt = psql.createStatement()) {
                    int i = stmt.executeUpdate(sql);
                    if (i == i) {
                        JOptionPane.showMessageDialog(null, "Success");
                    }
                    t.loadData();
                } catch (Exception x) {
                    JOptionPane.showMessageDialog(null, x.getMessage());
                }

            }
        });
    }
}

趁我有你的注意,让我给你介绍几个小朋友......

PreapredStatement

PreparedStatement 保护您免受可能的 SQL 注入问题的影响,并支持多种不同的数据类型,让您不必尝试弄清楚如何为不同的数据库转换它们

详情请见How to use PreparedStatement

void EventHandle() {
    b_crt.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Dbcon dc = new Dbcon();
            String sql = "INSERT INTO public.patrons VALUES (?, ?, ?)";
            try (Connection psql = dc.getConnection();
                    PreparedStatement stmt = psql.prepareStatement(sql)) {
                stmt.setString(1, t_id.getText());
                stmt.setString(2, t_usrnm.getText());
                stmt.setString(3, t_adrs.getText());
                int i = stmt.executeUpdate(sql);
                if (i == i) {
                    JOptionPane.showMessageDialog(null, "Success");
                }
                t.loadData();
            } catch (Exception x) {
                JOptionPane.showMessageDialog(null, x.getMessage());
            }

        }
    });
}

尝试资源

资源管理是一项非常重要的任务,而且可能很复杂。如果许多操作中的任何一个失败,您编写的代码可能会导致资源处于打开状态。更好的解决方案是利用可用的“自动关闭”支持

你会在上面的代码中看到它,但你也可以阅读The try-with-resources Statement

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多