You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JTable搜索后删除选中行异常:误删原始首行问题求助

JTable搜索后删除行异常问题解决

问题场景

JTable默认展示所有人员姓名,在文本框输入关键词搜索后,表格仅显示匹配的单条数据。点击该行并点击删除按钮时,并未删除该匹配数据,反而删除了搜索前表格的首行。

用户提供代码

删除按钮关联代码

private void officialsDelete() {
    DefaultTableModel RecordTable = (DefaultTableModel)officialTable.getModel();
    int SelectedRows = officialTable.getSelectedRow();
    
    try{
        if(officialTable.getSelectedRowCount() == 1){
            id = Integer.parseInt(RecordTable.getValueAt(SelectedRows, 0).toString());
            deleteItem = JOptionPane.showConfirmDialog(null, "Confirm if you want to delete item",
                    "Warning",JOptionPane.YES_NO_OPTION);
            if(deleteItem == JOptionPane.YES_OPTION){
                Class.forName("com.mysql.cj.jdbc.Driver");
                sqlConn = DriverManager.getConnection(dataConn,username,password);
                pst = sqlConn.prepareStatement("delete from officials where id =?");
                RecordTable.removeRow(officialTable.getSelectedRow());

                pst.setInt(1, id);
                pst.executeUpdate();
                JOptionPane.showMessageDialog(this,"Recorded Updated");
                upDateDBOfficials();

            }
            
        }else{
                if(officialTable.getRowCount()==0){
                    JOptionPane.showMessageDialog(this,"Table is Empty!");
                }else{
                    JOptionPane.showMessageDialog(this,"Please select Single row for Deleting");
                }
            }
        
    }catch(ClassNotFoundException ex){
        java.util.logging.Logger.getLogger(InformationSystem.class.getName()).log(java.util.logging.Level.SEVERE,
                null, ex);
    }catch(SQLException ex){
        java.util.logging.Logger.getLogger(InformationSystem.class.getName()).log(java.util.logging.Level.SEVERE,
                null, ex);
    }
    
}

搜索文本框keyReleased事件代码

private void officialsSearch() {
    String search = officialSearchTxt.getText();
    DefaultTableModel model = (DefaultTableModel)officialTable.getModel();
    TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<>(model);
    officialTable.setRowSorter(sorter);
    sorter.setRowFilter(RowFilter.regexFilter("(?i)" + search));
    
}

问题原因

当使用TableRowSorter做行过滤后,JTable的视图行号和模型行号不再一一对应。officialTable.getSelectedRow()返回的是当前视图中选中行的索引,而直接用这个索引去操作DefaultTableModel(比如getValueAt、removeRow),会访问到模型中对应原位置的行,而非过滤后视图里的选中行,这就导致删错了数据。

解决方法

使用JTable.convertRowIndexToModel(int viewRow)方法,将视图行号转换成对应的模型行号,再用模型行号操作数据模型。

修改后的删除按钮代码

private void officialsDelete() {
    DefaultTableModel RecordTable = (DefaultTableModel) officialTable.getModel();
    // 获取视图选中行号
    int viewSelectedRow = officialTable.getSelectedRow();
    
    try {
        if (officialTable.getSelectedRowCount() == 1) {
            // 转换为模型行号
            int modelSelectedRow = officialTable.convertRowIndexToModel(viewSelectedRow);
            // 用模型行号获取id
            id = Integer.parseInt(RecordTable.getValueAt(modelSelectedRow, 0).toString());
            
            int deleteItem = JOptionPane.showConfirmDialog(null, "确认是否删除该条目",
                    "警告", JOptionPane.YES_NO_OPTION);
            if (deleteItem == JOptionPane.YES_OPTION) {
                Class.forName("com.mysql.cj.jdbc.Driver");
                sqlConn = DriverManager.getConnection(dataConn, username, password);
                pst = sqlConn.prepareStatement("delete from officials where id =?");
                
                // 用模型行号删除模型中的行
                RecordTable.removeRow(modelSelectedRow);
                
                pst.setInt(1, id);
                pst.executeUpdate();
                JOptionPane.showMessageDialog(this, "记录已更新");
                upDateDBOfficials();
                
                // 关闭资源,避免连接泄漏
                pst.close();
                sqlConn.close();
            }
            
        } else {
            if (officialTable.getRowCount() == 0) {
                JOptionPane.showMessageDialog(this, "表格为空!");
            } else {
                JOptionPane.showMessageDialog(this, "请选择单行进行删除");
            }
        }
        
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(InformationSystem.class.getName()).log(java.util.logging.Level.SEVERE,
                null, ex);
    } catch (SQLException ex) {
        java.util.logging.Logger.getLogger(InformationSystem.class.getName()).log(java.util.logging.Level.SEVERE,
                null, ex);
    }
}

额外优化(搜索事件)

每次输入都创建新的TableRowSorter会造成不必要的开销,可以复用已有的RowSorter:

// 在类中定义成员变量保存sorter
private TableRowSorter<DefaultTableModel> officialTableSorter;

private void officialsSearch() {
    String search = officialSearchTxt.getText();
    DefaultTableModel model = (DefaultTableModel) officialTable.getModel();
    
    if (officialTableSorter == null) {
        officialTableSorter = new TableRowSorter<>(model);
        officialTable.setRowSorter(officialTableSorter);
    }
    
    if (search.trim().isEmpty()) {
        officialTableSorter.setRowFilter(null); // 清空过滤,显示所有行
    } else {
        officialTableSorter.setRowFilter(RowFilter.regexFilter("(?i)" + search));
    }
}

内容的提问来源于stack exchange,提问作者Ken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:24:32