DefaultTableModel更新异常:点击JTable旧数据复现如何解决?
问题分析与解决方案
你的问题根源在于每次点击Search按钮时,都会创建新的JTable和JScrollPane并添加到面板中,导致多个表格组件叠加在一起。表面上看新数据显示在最上层,但点击时可能触发了底层旧表格的事件,从而显示旧模型的数据。
修复步骤
1. 将表格相关组件改为类成员变量
把JTable、JScrollPane和DefaultTableModel提升为类的成员,确保整个生命周期内只创建一次。
2. 在构造方法中初始化表格组件
在构造方法里完成表格、滚动面板的创建和布局添加,而不是每次搜索时重复添加。
3. 修改showTable方法,仅更新模型数据
不再新建组件,而是清空现有模型的行数据,重新查询数据库并填充新数据。
修改后的完整代码
import javax.swing.*; import javax.swing.GroupLayout.Alignment; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.sql.*; public class store extends JPanel{ int WIDTH = 1000; int HEIGHT = 600; String[] columnnames = new String[] {"id", "type", "cost"}; JComboBox jcb; JButton button; // 改为类成员变量 DefaultTableModel dtm; JTable t; JScrollPane pane; public store() { super(); this.setVisible(true); this.setPreferredSize(new Dimension(WIDTH, HEIGHT)); this.setBackground(new Color(224, 224, 224)); GroupLayout gLayout = new GroupLayout(this); gLayout.setAutoCreateGaps(true); gLayout.setAutoCreateContainerGaps(true); this.setLayout(gLayout); this.jcb = new JComboBox(); this.button=new JButton("Search"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { showTable(); } }); // 初始化表格组件 dtm = new DefaultTableModel(columnnames, 0); t = new JTable(dtm); pane = new JScrollPane(t); pane.setPreferredSize(new Dimension(850, 150)); // 加载下拉框数据 try { Class.forName("org.postgresql.Driver"); try(Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/Try", "postgres", "******")) { String sql = "select distinct type from try"; try(PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs2 = ps.executeQuery()) { while (rs2.next()) { String aS = rs2.getString(1); jcb.addItem(aS); } } } catch (SQLException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } // 调整布局,添加表格滚动面板 gLayout.setHorizontalGroup(gLayout.createSequentialGroup() .addGap(400) .addComponent(jcb) .addComponent(button) .addGap(400) ); gLayout.setVerticalGroup(gLayout.createSequentialGroup() .addGap(50) .addGroup(gLayout.createParallelGroup(Alignment.CENTER) .addComponent(jcb) .addComponent(button) ) .addGap(20) .addComponent(pane) .addGap(250) ); } public void showTable() { // 清空现有模型数据 dtm.setRowCount(0); String ta = jcb.getSelectedItem().toString(); try { Class.forName("org.postgresql.Driver"); // 使用try-with-resources自动关闭连接、语句、结果集 try(Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/Try", "postgres", "*****"); PreparedStatement pstm = conn.prepareStatement( "SELECT try.* FROM try WHERE type=?")) { pstm.setString(1, ta); try(ResultSet Rs = pstm.executeQuery()) { while (Rs.next()) { dtm.addRow(new Object[] { Rs.getString(1), Rs.getString(2), Rs.getString(3) }); } } } } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } }
关键修改说明
- 组件复用:表格和滚动面板只初始化一次,避免多次添加导致的组件叠加问题。
- 模型更新:通过
dtm.setRowCount(0)清空旧数据,再添加新行,确保模型始终是当前最新数据。 - 资源管理:使用
try-with-resources语法自动关闭数据库连接、PreparedStatement和ResultSet,避免资源泄漏。 - 布局优化:将表格滚动面板加入GroupLayout,替代原来的
setBounds硬编码位置,适配布局管理器的规则。
内容的提问来源于stack exchange,提问作者blink727_
相关产品推荐
相关产品推荐

