当前位置: 首页 > 知识库问答 >
问题:

删除行后未更新JTable

蒙化
2023-03-14

我正在尝试更新JTable(或data?)的行在我对一行执行删除操作后,当选择另一行时,可以编辑所选行。当前删除该行将使已删除行下方的行上移,但如果选择了该行号并尝试进行编辑,则会返回(JOptionPane),就像未选择任何内容一样。它似乎没有“刷新”数据(?)。

这是一个SCCE,希望有人可以运行它并指出问题。我试着尽可能地缩小它,以便于复制/粘贴:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.table.*;
import java.util.*;

public class JTableTest4 extends JFrame implements ActionListener {
    private JPanel dbOutputPanel = new JPanel();
    private JTable dbOutputTable;
    private JScrollPane dbOutputTableSP = new JScrollPane(dbOutputTable);
    private JButton deleteButton = new JButton("Delete");
    private JButton editButton = new JButton("Edit");
    private JButton searchButton = new JButton("Search");
    private JPanel south = new JPanel();
    protected HashMap<Integer, Student> studentMap;
    protected int studentIndex;

    public JTableTest4() {
        super("Student Database");
        populateMap();
        south.add(deleteButton);
        south.add(editButton);
        south.add(searchButton);
        dbOutputTable = new JTable();
        dbOutputTable.setFillsViewportHeight(true);
        dbOutputTable.setPreferredScrollableViewportSize(new Dimension(450, 250));
        dbOutputTableSP = new JScrollPane(dbOutputTable);
        dbOutputPanel.add(dbOutputTableSP);
        searchButton.addActionListener(this);
        editButton.addActionListener(this);
        deleteButton.addActionListener(this);

        this.add(new JLabel("Welcome to " + getTitle(), JLabel.CENTER), BorderLayout.NORTH);
        this.add(dbOutputPanel, BorderLayout.CENTER);
        this.add(south, BorderLayout.SOUTH);
        this.setSize(600, 500);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        Object source = event.getSource();
        int selectedRow = dbOutputTable.getSelectedRow();
        if (source == searchButton) {
            displayTable();
        } else if (source == editButton) {
            Student student = studentMap.get(selectedRow);
            displayTable();
            if (student != null) {
                System.out.println("\n" + student.toString() + "\n");
            } else {
                JOptionPane.showMessageDialog(this, "Please select a student to edit",
                        getTitle(), JOptionPane.INFORMATION_MESSAGE);
            }
        }
        else if (source == deleteButton) {
            System.out.println("Row count: " + ((DefaultTableModel) dbOutputTable.getModel()).getRowCount());
            System.out.println("Selected Row: " + (selectedRow));
            String[] options = {"Yes", "No"};
            int result = JOptionPane.showOptionDialog(null, "Delete student from database?",
                    "Delete Student", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
                    null, options, options[1]);
            if (result == JOptionPane.YES_OPTION) {
                studentMap.remove(selectedRow);
                ((DefaultTableModel) dbOutputTable.getModel()).fireTableRowsDeleted(selectedRow, selectedRow);//not the issue
                displayTable();
            } else if (result == JOptionPane.NO_OPTION) {
            } 
        }
        displayTable();
    }

    public void populateMap() {
        studentMap = new HashMap<>();
        Student s1 = new Student("232", "john", "thomas", 22);
        Student s2 = new Student("56", "bob", "doe", 23);
        Student s3 = new Student("678", "sally", "smith", 24);
        Student s4 = new Student("32", "chris", "johnson", 21);
        Student s5 = new Student("12", "dsfg", "sgfsdg", 22);
        studentMap.put(0, s1);
        studentMap.put(1, s2);
        studentMap.put(2, s3);
        studentMap.put(3, s4);
        studentMap.put(4, s5);
    }
    
    public TableModel toTableModel() {
        System.out.println("Using toTableModel");
        ArrayList<Student> studentList = new ArrayList<>();
        for (Integer key : studentMap.keySet()) {
            Student newStudent = (Student) studentMap.get(key);
            studentList.add(newStudent);
        }
        DefaultTableModel tmodel = new DefaultTableModel(
                new Object[]{"Id", "First", "Last", "Age"}, 0);
        for (int i = 0; i < studentList.size(); i++) {
            Student newStudent = studentList.get(i);
            tmodel.addRow(new Object[] {newStudent.getStudentId(),
            newStudent.getStudentFirstName(), 
            newStudent.getStudentLastName(), 
            newStudent.getStudentAge()});
        }
        return tmodel;
    }

    public void displayTable() {
        dbOutputTable.setModel(toTableModel());
//        dbOutputTable.revalidate();
    }

    public static void main(String[] args) throws Exception {
        JTableTest4 test = new JTableTest4();
        UIManager.setLookAndFeel(new NimbusLookAndFeel());
    }
}

class Student {
    private String studentId;
    private String studentFirstName;
    private String studentLastName;
    private int studentAge;
    public Student(String id, String first, String last, int age) {
        this.studentId = id;
        this.studentFirstName = first;
        this.studentLastName = last;
        this.studentAge = age;
    }
    public String getStudentId() {return studentId;}
    public void setStudentId(String studentId) {this.studentId = studentId;}
    public String getStudentFirstName() {return studentFirstName;}
    public void setStudentFirstName(String studentFirstName) {this.studentFirstName = studentFirstName;}
    public String getStudentLastName() {return studentLastName;}
    public void setStudentLastName(String studentLastName) {this.studentLastName = studentLastName;}
    public int getStudentAge() {return studentAge;}
    public void setStudentAge(int studentAge) {this.studentAge = studentAge;}
    @Override
    public String toString() {
        String st = "_id : " + this.studentId + "\n";
        st += "First Name : " + this.studentFirstName + "\n";
        st += "Last Name : " + this.studentLastName + "\n";
        st += "Age : " + this.studentAge + "\n";
        return st;
    }
}

我在这里看到这个问题的各种形式都有一些不同,通常都是相同的建议,我也尝试了一些。如果您能提供任何帮助,我们将不胜感激。谢谢

共有1个答案

程招
2023-03-14

您的“数据模型”和表模型需要保持更紧密的同步。您的displayTable方法令人担忧,它表明您对模型、视图和数据应该如何管理的基本错误理解。

就我个人而言,我会使用一个更好地将现有的学生列表与表格模型结合起来的抽象表,而不是使用两个不同的模型,但这可能超出了问题的范围。

下面是您的代码的略微修改版本,它使用DefaultTableModel#removeow更新JTable

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class JTableTest4 extends JFrame implements ActionListener {

    private JPanel dbOutputPanel = new JPanel();
    private JTable dbOutputTable;
    private JScrollPane dbOutputTableSP = new JScrollPane(dbOutputTable);
    private JButton deleteButton = new JButton("Delete");
    private JButton editButton = new JButton("Edit");
    private JButton searchButton = new JButton("Search");
    private JPanel south = new JPanel();
    protected HashMap<Integer, Student> studentMap;
    protected int studentIndex;

    public JTableTest4() {
        super("Student Database");
        populateMap();
        south.add(deleteButton);
        south.add(editButton);
        south.add(searchButton);
        dbOutputTable = new JTable();
        dbOutputTable.setModel(toTableModel());
        dbOutputTable.setFillsViewportHeight(true);
        dbOutputTable.setPreferredScrollableViewportSize(new Dimension(450, 250));
        dbOutputTableSP = new JScrollPane(dbOutputTable);
        dbOutputPanel.add(dbOutputTableSP);
        searchButton.addActionListener(this);
        editButton.addActionListener(this);
        deleteButton.addActionListener(this);

        this.add(new JLabel("Welcome to " + getTitle(), JLabel.CENTER), BorderLayout.NORTH);
        this.add(dbOutputPanel, BorderLayout.CENTER);
        this.add(south, BorderLayout.SOUTH);
        this.setSize(600, 500);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        Object source = event.getSource();
        int selectedRow = dbOutputTable.getSelectedRow();
        if (source == searchButton) {
            //displayTable();
        } else if (source == editButton) {
            Student student = studentMap.get(selectedRow);
            //displayTable();
            if (student != null) {
                System.out.println("\n" + student.toString() + "\n");
            } else {
                JOptionPane.showMessageDialog(this, "Please select a student to edit",
                        getTitle(), JOptionPane.INFORMATION_MESSAGE);
            }
        } else if (source == deleteButton) {
            System.out.println("Row count: " + ((DefaultTableModel) dbOutputTable.getModel()).getRowCount());
            System.out.println("Selected Row: " + (selectedRow));
            String[] options = {"Yes", "No"};
            int result = JOptionPane.showOptionDialog(null, "Delete student from database?",
                    "Delete Student", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
                    null, options, options[1]);
            if (result == JOptionPane.YES_OPTION) {
                studentMap.remove(selectedRow);
                ((DefaultTableModel)dbOutputTable.getModel()).removeRow(selectedRow);
//                ((DefaultTableModel) dbOutputTable.getModel()).fireTableRowsDeleted(selectedRow, selectedRow);//not the issue
//                displayTable();
            } else if (result == JOptionPane.NO_OPTION) {
            }
        }
        //displayTable();
    }

    public void populateMap() {
        studentMap = new HashMap<>();
        Student s1 = new Student("232", "john", "thomas", 22);
        Student s2 = new Student("56", "bob", "doe", 23);
        Student s3 = new Student("678", "sally", "smith", 24);
        Student s4 = new Student("32", "chris", "johnson", 21);
        Student s5 = new Student("12", "dsfg", "sgfsdg", 22);
        studentMap.put(0, s1);
        studentMap.put(1, s2);
        studentMap.put(2, s3);
        studentMap.put(3, s4);
        studentMap.put(4, s5);
    }

    public TableModel toTableModel() {
        System.out.println("Using toTableModel");
        ArrayList<Student> studentList = new ArrayList<>();
        for (Integer key : studentMap.keySet()) {
            Student newStudent = (Student) studentMap.get(key);
            studentList.add(newStudent);
        }
        DefaultTableModel tmodel = new DefaultTableModel(
                new Object[]{"Id", "First", "Last", "Age"}, 0);
        for (int i = 0; i < studentList.size(); i++) {
            Student newStudent = studentList.get(i);
            tmodel.addRow(new Object[]{newStudent.getStudentId(),
                newStudent.getStudentFirstName(),
                newStudent.getStudentLastName(),
                newStudent.getStudentAge()});
        }
        return tmodel;
    }

    public void displayTable() {
        dbOutputTable.setModel(toTableModel());
//        dbOutputTable.revalidate();
    }

    public static void main(String[] args) throws Exception {
        JTableTest4 test = new JTableTest4();
        UIManager.setLookAndFeel(new NimbusLookAndFeel());
    }
}

class Student {

    private String studentId;
    private String studentFirstName;
    private String studentLastName;
    private int studentAge;

    public Student(String id, String first, String last, int age) {
        this.studentId = id;
        this.studentFirstName = first;
        this.studentLastName = last;
        this.studentAge = age;
    }

    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }

    public String getStudentFirstName() {
        return studentFirstName;
    }

    public void setStudentFirstName(String studentFirstName) {
        this.studentFirstName = studentFirstName;
    }

    public String getStudentLastName() {
        return studentLastName;
    }

    public void setStudentLastName(String studentLastName) {
        this.studentLastName = studentLastName;
    }

    public int getStudentAge() {
        return studentAge;
    }

    public void setStudentAge(int studentAge) {
        this.studentAge = studentAge;
    }

    @Override
    public String toString() {
        String st = "_id : " + this.studentId + "\n";
        st += "First Name : " + this.studentFirstName + "\n";
        st += "Last Name : " + this.studentLastName + "\n";
        st += "Age : " + this.studentAge + "\n";
        return st;
    }
}

此示例使用了一个自定义的表模型(名为StudentTableModel),它将表模型包装在基础数据模型周围,并协调更新。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.table.AbstractTableModel;

public class JTableTest4 extends JFrame implements ActionListener {

    private JPanel dbOutputPanel = new JPanel();
    private JTable dbOutputTable;
    private JScrollPane dbOutputTableSP = new JScrollPane(dbOutputTable);
    private JButton deleteButton = new JButton("Delete");
    private JButton editButton = new JButton("Edit");
    private JButton searchButton = new JButton("Search");
    private JPanel south = new JPanel();

    public JTableTest4() {
        super("Student Database");
        south.add(deleteButton);
        south.add(editButton);
        south.add(searchButton);
        dbOutputTable = new JTable();
        dbOutputTable.setModel(makeModel());
        dbOutputTable.setFillsViewportHeight(true);
        dbOutputTable.setPreferredScrollableViewportSize(new Dimension(450, 250));
        dbOutputTableSP = new JScrollPane(dbOutputTable);
        dbOutputPanel.add(dbOutputTableSP);
        searchButton.addActionListener(this);
        editButton.addActionListener(this);
        deleteButton.addActionListener(this);

        this.add(new JLabel("Welcome to " + getTitle(), JLabel.CENTER), BorderLayout.NORTH);
        this.add(dbOutputPanel, BorderLayout.CENTER);
        this.add(south, BorderLayout.SOUTH);
        this.setSize(600, 500);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        Object source = event.getSource();
        int selectedRow = dbOutputTable.convertRowIndexToModel(dbOutputTable.getSelectedRow());

        if (selectedRow < 0) {
            return;
        }

        if (source == searchButton) {
            //displayTable();
        } else if (source == editButton) {
//            Student student = studentMap.get(selectedRow);
//            //displayTable();
//            if (student != null) {
//                System.out.println("\n" + student.toString() + "\n");
//            } else {
//                JOptionPane.showMessageDialog(this, "Please select a student to edit",
//                        getTitle(), JOptionPane.INFORMATION_MESSAGE);
//            }
        } else if (source == deleteButton) {
            StudentTableModel model = (StudentTableModel)dbOutputTable.getModel();
            model.removeRow(selectedRow);
//            System.out.println("Row count: " + ((DefaultTableModel) dbOutputTable.getModel()).getRowCount());
//            System.out.println("Selected Row: " + (selectedRow));
//            String[] options = {"Yes", "No"};
//            int result = JOptionPane.showOptionDialog(null, "Delete student from database?",
//                    "Delete Student", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
//                    null, options, options[1]);
//            if (result == JOptionPane.YES_OPTION) {
//                studentMap.remove(selectedRow);
//                ((DefaultTableModel) dbOutputTable.getModel()).removeRow(selectedRow);
//                //                ((DefaultTableModel) dbOutputTable.getModel()).fireTableRowsDeleted(selectedRow, selectedRow);//not the issue
//                //                displayTable();
//            } else if (result == JOptionPane.NO_OPTION) {
//            }
        }
        //displayTable();
    }

    public StudentTableModel makeModel() {
        System.out.println("Using toTableModel");
        ArrayList<Student> studentList = new ArrayList<>();
        studentList.add(new Student("232", "john", "thomas", 22));
        studentList.add(new Student("56", "bob", "doe", 23));
        studentList.add(new Student("678", "sally", "smith", 24));
        studentList.add(new Student("32", "chris", "johnson", 21));
        studentList.add(new Student("12", "dsfg", "sgfsdg", 22));
        return new StudentTableModel(studentList);
    }

    public static void main(String[] args) throws Exception {
        JTableTest4 test = new JTableTest4();
        UIManager.setLookAndFeel(new NimbusLookAndFeel());
    }

    class Student {

        private String studentId;
        private String studentFirstName;
        private String studentLastName;
        private int studentAge;

        public Student(String id, String first, String last, int age) {
            this.studentId = id;
            this.studentFirstName = first;
            this.studentLastName = last;
            this.studentAge = age;
        }

        public String getStudentId() {
            return studentId;
        }

        public void setStudentId(String studentId) {
            this.studentId = studentId;
        }

        public String getStudentFirstName() {
            return studentFirstName;
        }

        public void setStudentFirstName(String studentFirstName) {
            this.studentFirstName = studentFirstName;
        }

        public String getStudentLastName() {
            return studentLastName;
        }

        public void setStudentLastName(String studentLastName) {
            this.studentLastName = studentLastName;
        }

        public int getStudentAge() {
            return studentAge;
        }

        public void setStudentAge(int studentAge) {
            this.studentAge = studentAge;
        }

        @Override
        public String toString() {
            String st = "_id : " + this.studentId + "\n";
            st += "First Name : " + this.studentFirstName + "\n";
            st += "Last Name : " + this.studentLastName + "\n";
            st += "Age : " + this.studentAge + "\n";
            return st;
        }
    }

    class StudentTableModel extends AbstractTableModel {

        List<Student> studentList;

        public StudentTableModel(List<Student> studentList) {
            this.studentList = studentList;
        }

        @Override
        public int getRowCount() {
            return studentList.size();
        }

        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public String getColumnName(int column) {
            switch (column) {
                case 0: return "ID";
                case 1: return "First Name";
                case 2: return "Last Name";
                case 3: return "Age";
            }
            return "??";
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Student student = studentList.get(rowIndex);
            switch (columnIndex) {
                case 0: return student.studentId;
                case 1: return student.studentFirstName;
                case 2: return student.studentLastName;
                case 3: return student.studentAge;
            }
            return null;
        }

        // This is a more advance topic then I want to get into here
        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return false;
        }

        public Student studentAt(int row) {
            return studentList.get(row);
        }

        public void removeRow(int index) {
            studentList.remove(index);
            fireTableRowsDeleted(index, index);
        }

    }
}

详细了解如何使用表

 类似资料:
  • 但是建议的解决方案对我来说都不起作用。我从sqlite数据库中的RecycerView列表项,当我向左滑动时,相应的数据将成功地从数据库中删除。由于某些原因,昨天一切都工作得很好,删除的项从列表中消失了,但从今天开始,该项在RecycerView中仍然可见。下面是我的代码:

  • 我有recyclerview,每行包含一个项目列表和一个按钮。单击按钮时,我希望删除整行并自动更新列表。 下面是我的适配器类代码: 此代码有效,项目将被删除。但是,列表不会更新,直到我再次访问该活动。如何立即更新视图?

  • 我有一个由Access DB使用ResultSet&填充的JTable。我有一个方法可以正确地从数据库中删除记录,但在刷新表模型的当前视图时遇到了困难。我看过类似的帖子,并尝试使用和,但没有成功。我还注意到其他帖子提到了的使用,因为它有add/remove行方法,但我使用的代码来自我去年使用的Java教科书(教授从未达到这一点,所以我试图自己学习)... 以下是定制JFrame的类: 下面是Abs

  • 删除项目后,“我的回收器”视图未更新。此recyclerView位于片段内部。我试过各种方法,但都不管用。 片段类中的适配器声明 回收服务适配器: } 调试项目时,我可以看到该项实际上正在从ArrayList中删除。但不在循环视图中更新。 删除后,如果滚动回收站视图,则从回收站视图中删除已删除的项。但不是没有滚动。

  • 关于这个问题有好几篇帖子,但仍然没有找到答案。这是父类Userr。在@OneToMany关系中,我想删除一个特定的子帐户。 现在,当我通过“删除”查询执行此操作时,我得到以下异常。 组织。springframework。刀。InvalidDataAccessApiUsageException:执行更新/删除查询;嵌套的异常是javax。坚持不懈TransactionRequiredExceptio

  • 我试图创建一个带有关键监听器的JTextField,它将仅在文本长度正好为4时启用按钮。 它的工作,但如果长度达到4,我删除一个字符(使用退格或删除按钮)文本长度不更新,并保持4,直到我删除另一个字符,但这将使它实际上2个字符。 你能帮我修改代码让它更新长度吗?提前谢谢。 我已经试过了,但没有成功: 和