Java 仅当按下按钮时才将单元格更改保存在JTable中,而不是像以前一样保留

Java 仅当按下按钮时才将单元格更改保存在JTable中,而不是像以前一样保留,java,swing,jtable,Java,Swing,Jtable,如果我在上面的JTable中选择一行,那么与该数据对应的一行将出现在下面的JTable中。以下Jtable中的所有单元格都是可编辑的。我需要的是: 如果我按下按钮,下面Jtable中的更改将被保存。如果我不按下按钮,JTable单元格将保持应用程序的原始状态 PS:这是一个演示,真实案例包含更多参数,但目的是一样的 package guarreo; import java.awt.BorderLayout; import java.awt.EventQueue; import jav

如果我在上面的JTable中选择一行,那么与该数据对应的一行将出现在下面的JTable中。以下Jtable中的所有单元格都是可编辑的。我需要的是:

如果我按下按钮,下面Jtable中的更改将被保存。如果我不按下按钮,JTable单元格将保持应用程序的原始状态

PS:这是一个演示,真实案例包含更多参数,但目的是一样的

    package guarreo;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.JButton;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class demo extends JFrame {

    private JPanel contentPane;
    private JTable tablePATIENTS;
    private JTable tableREPORTS;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    demo frame = new demo();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public demo() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 571, 336);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        tablePATIENTS = new JTable();
        tablePATIENTS.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent arg0) {
                if(tablePATIENTS.getSelectedRow()!=-1){//If there is a patient selected with a report, enable the save changes button
                    DefaultTableModel dtm2 = (DefaultTableModel) tableREPORTS.getModel();
                    dtm2.addRow(new Object[]{"200$", "Pills", "Headache"});
                    tableREPORTS.setModel(dtm2);
                }
            }
        });
        tablePATIENTS.setModel(new DefaultTableModel(
            new Object[][] {
            },
            new String[] {
                "Name", "Surrname", "Doctor"
            }
        ));
        DefaultTableModel dtm = (DefaultTableModel) tablePATIENTS.getModel();
        dtm.addRow(new Object[]{"Jon", "Snow", "Jack"});

        JButton btnSaveChanges = new JButton("Save changes tableREPORTS");
        btnSaveChanges.setEnabled(false);
        btnSaveChanges.setBounds(155, 260, 212, 23);
        contentPane.add(btnSaveChanges);
        tablePATIENTS.setModel(dtm);
        tablePATIENTS.setBounds(20, 11, 486, 107);
        contentPane.add(tablePATIENTS);

        tableREPORTS = new JTable();
        tableREPORTS.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                btnSaveChanges.setEnabled(true); //Enabled only if something selected in this table
            }
        });
        tableREPORTS.setModel(new DefaultTableModel(
            new Object[][] {
            },
            new String[] {
                "Cost", "Treatment", "Disease"
            }
        ));
        tableREPORTS.setBounds(20, 144, 486, 105);
        contentPane.add(tableREPORTS);
    }
}

一般的解决方案是制作患者数据的深度副本,并使用此副本创建辅助JTable数据。然后,用户可以根据自己的意愿对JTable数据进行任何更改,而无需担心副作用。一旦按下按钮,它的ActionListener就会将JTable模型的数据转换回患者的数据,替换原始数据。因此,关键是在按下按钮之前不要进行更换

如果Patient类拥有一个信息类对象的ArrayList,那么该列表的获取者应该通过创建一个新的ArrayList来创建一个深度副本,并在for循环中,使用原始列表中所拥有对象的深度副本来填充它

例如:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

@SuppressWarnings("serial")
public class MyDemo extends JPanel {
    private static final int GAP = 3;
    private MyPatientTableModel patientModel = new MyPatientTableModel();
    private JTable patientTable = new JTable(patientModel);
    private JTable ptVisitTable = new JTable(new MyPtVisitTableModel(new ArrayList<MyPtVisit>()));

    public MyDemo() {
        MyPatient pt0 = new MyPatient("001", "Johnson", "Michael");
        pt0.addVisit(new MyPtVisit(200, "Head Ache", "Narcotics"));
        pt0.addVisit(new MyPtVisit(300, "Body Ache", "Aspirin"));
        pt0.addVisit(new MyPtVisit(400, "Total Ache", "Nothing"));

        MyPatient pt1 = new MyPatient("002", "Smith", "John");
        pt1.addVisit(new MyPtVisit(220, "Head Ache", "Narcotics"));
        pt1.addVisit(new MyPtVisit(320, "Body Ache", "Aspirin"));
        pt1.addVisit(new MyPtVisit(420, "Total Ache", "Nothing"));

        MyPatient pt2 = new MyPatient("003", "Baker", "Betty");
        pt2.addVisit(new MyPtVisit(240, "Head Ache", "Narcotics"));
        pt2.addVisit(new MyPtVisit(340, "Body Ache", "Aspirin"));
        pt2.addVisit(new MyPtVisit(440, "Total Ache", "Nothing"));

        MyPatient pt3 = new MyPatient("004", "Duck", "Donald");
        pt3.addVisit(new MyPtVisit(260, "Head Ache", "Narcotics"));
        pt3.addVisit(new MyPtVisit(360, "Body Ache", "Aspirin"));
        pt3.addVisit(new MyPtVisit(460, "Total Ache", "Nothing"));

        MyPatient[] pts = { pt0, pt1, pt2, pt3 };

        for (MyPatient myPatient : pts) {
            patientModel.addRow(myPatient);
        }

        patientTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        patientTable.getSelectionModel().addListSelectionListener(new PatientTableListener());
        TableColumnModel tcm = patientTable.getColumnModel();
        tcm.removeColumn(tcm.getColumn(3)); // visits column should be invisible

        patientTable.setFillsViewportHeight(true);
        ptVisitTable.setFillsViewportHeight(true);
        Dimension size = patientTable.getPreferredScrollableViewportSize();
        size = new Dimension(size.width, size.height / 2);
        patientTable.setPreferredScrollableViewportSize(size);
        size = ptVisitTable.getPreferredScrollableViewportSize();
        size = new Dimension(size.width, size.height / 2);
        ptVisitTable.setPreferredScrollableViewportSize(size);
        JScrollPane ptTableScrollPane = new JScrollPane(patientTable);
        JScrollPane ptVisitScrollPane = new JScrollPane(ptVisitTable);

        JPanel btnPanel = new JPanel();
        btnPanel.add(new JButton(new SaveChangesAction("Save Changes")));

        setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        add(ptTableScrollPane);
        add(Box.createVerticalStrut(GAP));
        add(ptVisitScrollPane);
        add(Box.createVerticalStrut(GAP));
        add(btnPanel);
    }

    private class SaveChangesAction extends AbstractAction {
        public SaveChangesAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            int index = patientTable.getSelectedRow();
            if (index < 0) {
                return;
            }

            // to capture edits not yet complete
            if (ptVisitTable.isEditing()) {
                CellEditor cellEditor = ptVisitTable.getCellEditor();
                if (cellEditor != null) {
                    cellEditor.stopCellEditing();
                }
            }
            index = patientTable.convertRowIndexToModel(index);
            MyPatient selectedPatient = patientModel.getPatient(index);

            MyPtVisitTableModel visitsModel = (MyPtVisitTableModel) ptVisitTable.getModel();
            List<MyPtVisit> visits = visitsModel.getVisits();
            selectedPatient.setVisits(visits);

            patientModel.setPatientAt(index, selectedPatient);
        }
    }

    private class PatientTableListener implements ListSelectionListener {
        @Override
        public void valueChanged(ListSelectionEvent e) {
            if (e.getValueIsAdjusting()) {
                return;
            }
            int index = patientTable.getSelectedRow();
            if (index < 0) {
                return;
            }
            index = patientTable.convertRowIndexToModel(index);
            MyPatient selectedPatient = patientModel.getPatient(index);
            List<MyPtVisit> visits = selectedPatient.getVisits();
            MyPtVisitTableModel visitsModel = new MyPtVisitTableModel(visits);
            ptVisitTable.setModel(visitsModel);
        }
    }

    private static void createAndShowGui() {
        MyDemo mainPanel = new MyDemo();

        JFrame frame = new JFrame("My Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

@SuppressWarnings("serial")
class MyPatientTableModel extends DefaultTableModel {
    public MyPatientTableModel() {
        super(MyPatient.HEADINGS, 0);
    }

    @SuppressWarnings("unchecked")
    public MyPatient getPatient(int index) {
        String patientId = (String) getValueAt(index, 0);
        String lastName = (String) getValueAt(index, 1);
        String firstName = (String) getValueAt(index, 2);

        // non-displayed data
        List<MyPtVisit> visits = (List<MyPtVisit>) getValueAt(index, 3);
        MyPatient patient = new MyPatient(patientId, lastName, firstName);
        patient.setVisits(visits);
        return patient;
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        if (getRowCount() != 0 && getValueAt(0, columnIndex) != null) {
            return getValueAt(0, columnIndex).getClass();
        } else {
            return super.getColumnClass(columnIndex);
        }
    }

    public void addRow(MyPatient patient) {
        Vector<Object> rowData = new Vector<>();
        rowData.add(patient.getPatientId());
        rowData.add(patient.getLastName());
        rowData.add(patient.getFirstName());
        rowData.add(patient.getVisits()); // not displayed!
        addRow(rowData);

    }

    public void setPatientAt(int row, MyPatient patient) {
        setValueAt(patient.getPatientId(), row, 0);
        setValueAt(patient.getLastName(), row, 1);
        setValueAt(patient.getFirstName(), row, 2);
        setValueAt(patient.getVisits(), row, 3);
    }
}

@SuppressWarnings("serial")
class MyPtVisitTableModel extends DefaultTableModel {
    public MyPtVisitTableModel(List<MyPtVisit> visits) {
        super(MyPtVisit.HEADINGS, 0);
        for (MyPtVisit myPtVisit : visits) {
            addRow(myPtVisit);
        }
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        if (getRowCount() != 0 && getValueAt(0, columnIndex) != null) {
            return getValueAt(0, columnIndex).getClass();
        } else {
            return super.getColumnClass(columnIndex);
        }
    }

    public void addRow(MyPtVisit myPtVisit) {
        Vector<Object> rowData = new Vector<>();
        rowData.add(myPtVisit.getCost());
        rowData.add(myPtVisit.getSymptom());
        rowData.add(myPtVisit.getTreatment());
        addRow(rowData);
    }

    // extract data from table model
    public List<MyPtVisit> getVisits() {
        List<MyPtVisit> visits = new ArrayList<>();
        for (int i = 0; i < getRowCount(); i++) {
            double cost = (double) getValueAt(i, 0);
            String symptom = (String) getValueAt(i, 1);
            String treatment = (String) getValueAt(i, 2);
            visits.add(new MyPtVisit(cost, symptom, treatment));
        }
        return visits;
    }
}

// class that represents each patient
class MyPatient {
    public static final String[] HEADINGS = { "Patient ID", "Last Name", "First Name", "Visits" };
    private String patientId;
    private String lastName;
    private String firstName;
    private List<MyPtVisit> visits = new ArrayList<>();

    public MyPatient(String patientId, String lastName, String firstName) {
        this.patientId = patientId;
        this.lastName = lastName;
        this.firstName = firstName;
    }

    public String getPatientId() {
        return patientId;
    }

    public void setPatientId(String patientId) {
        this.patientId = patientId;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void addVisit(MyPtVisit ptVisit) {
        visits.add(ptVisit);
    }

    public List<MyPtVisit> getVisits() {
        // create new ArrayList to hold copy
        List<MyPtVisit> copyVisits = new ArrayList<>();
        for (MyPtVisit myPtVisit : visits) {
            // use MyPtVisit's copy constructor to create a new MyPtVisit
            copyVisits.add(new MyPtVisit(myPtVisit));
        }
        return copyVisits;
    }

    public void setVisits(List<MyPtVisit> visits) {
        this.visits = visits;
    }

    @Override
    public String toString() {
        return "MyPatient [patientId=" + patientId + ", lastName=" + lastName + ", firstName="
                + firstName + ", visits=" + visits + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
        result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
        result = prime * result + ((patientId == null) ? 0 : patientId.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MyPatient other = (MyPatient) obj;
        if (firstName == null) {
            if (other.firstName != null)
                return false;
        } else if (!firstName.equals(other.firstName))
            return false;
        if (lastName == null) {
            if (other.lastName != null)
                return false;
        } else if (!lastName.equals(other.lastName))
            return false;
        if (patientId == null) {
            if (other.patientId != null)
                return false;
        } else if (!patientId.equals(other.patientId))
            return false;
        return true;
    }

}

// my patient visit
// holds information for each patient's visit to the doctor
class MyPtVisit {
    public static final String[] HEADINGS = { "Cost", "Chief Symptom", "Treatment" };
    private double cost;
    private String symptom;
    private String treatment;

    public MyPtVisit(double cost, String symptom, String treatment) {
        this.cost = cost;
        this.symptom = symptom;
        this.treatment = treatment;
    }

    // copy constructor
    public MyPtVisit(MyPtVisit original) {
        this.cost = original.cost;
        this.symptom = original.symptom;
        this.treatment = original.treatment;
    }

    public double getCost() {
        return cost;
    }

    public void setCost(double cost) {
        this.cost = cost;
    }

    public String getSymptom() {
        return symptom;
    }

    public void setSymptom(String symptom) {
        this.symptom = symptom;
    }

    public String getTreatment() {
        return treatment;
    }

    public void setTreatment(String treatment) {
        this.treatment = treatment;
    }

    @Override
    public String toString() {
        return "MyPtVisit [cost=" + cost + ", symptom=" + symptom + ", treatment=" + treatment
                + "]";
    }

}
导入java.awt.Dimension;
导入java.awt.event.ActionEvent;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.Vector;
导入javax.swing.*;
导入javax.swing.event.ListSelectionEvent;
导入javax.swing.event.ListSelectionListener;
导入javax.swing.table.DefaultTableModel;
导入javax.swing.table.TableColumnModel;
@抑制警告(“串行”)
公共类MyDemo扩展了JPanel{
专用静态最终内部间隙=3;
私有MyPatientTableModel patientModel=新MyPatientTableModel();
私有JTable patientTable=新JTable(patientModel);
私有JTable ptVisitTable=newjtable(newmyptvisittablemodel(newarraylist());
公共MyDemo(){
MyPatient pt0=新的MyPatient(“001”、“约翰逊”、“迈克尔”);
pt0.addVisit(新的MyPtVisit(200,“头痛”、“麻醉品”);
pt0.addVisit(新的MyPtVisit(300,“身体疼痛”、“阿司匹林”);
pt0.addVisit(新的MyPtVisit(400,“总疼痛”,“无”);
MyPatient pt1=新的MyPatient(“002”、“Smith”、“John”);
pt1.AddVisite(新的MyPTVisite(220,“头痛”、“麻醉品”);
pt1.AddVisite(新MyPtVisite(320,“身体疼痛”、“阿司匹林”);
pt1.addVisit(新的MyPtVisit(420,“总疼痛”,“无”);
MyPatient pt2=新的MyPatient(“003”、“Baker”、“Betty”);
pt2.AddVisite(新的MyPTVisite(240,“头痛”、“麻醉品”);
pt2.addVisit(新的MyPtVisit(340,“身体疼痛”、“阿司匹林”);
pt2.addVisit(新的MyPtVisit(440,“总疼痛”,“无”);
MyPatient pt3=新MyPatient(“004”、“Duck”、“Donald”);
pt3.addVisit(新的MyPtVisit(260,“头痛”、“麻醉品”);
pt3.addVisit(新MyPtVisit(360,“身体疼痛”、“阿司匹林”);
pt3.addVisit(新的MyPtVisit(460,“总疼痛”,“无”);
MyPatient[]pts={pt0,pt1,pt2,pt3};
用于(我的患者我的患者:pts){
patientModel.addRow(我的患者);
}
patientTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
patientTable.getSelectionModel().addListSelectionListener(新的PatientTableListener());
TableColumnModel tcm=patientTable.getColumnModel();
tcm.removeColumn(tcm.getColumn(3));//访问列应不可见
可耐心等待。设置FillsViewPerthweight(真);
ptVisitTable.setFillsViewPerthight(true);
维度大小=patientTable.getPreferredScrollableViewportSize();
尺寸=新尺寸(尺寸.宽度,尺寸.高度/2);
patientTable.setPreferredScrollableViewportSize(大小);
size=ptVisitTable.getPreferredScrollableViewportSize();
尺寸=新尺寸(尺寸.宽度,尺寸.高度/2);
ptVisitTable.setPreferredScrollableViewportSize(大小);
JScrollPane ptTableScrollPane=新的JScrollPane(patientTable);
JScrollPane ptVisitScrollPane=新的JScrollPane(ptVisitTable);
JPanel btnPanel=新的JPanel();
添加(newjbutton(newsavechangesaction(“savechanges”));
setBorder(BorderFactory.createEmptyByOrder(间隙,间隙,间隙));
setLayout(新的BoxLayout(这是BoxLayout.PAGE_轴));
添加(ptTableScrollPane);
增加(垂直支柱盒(间隙));
添加(ptVisitScrollPane);
增加(垂直支柱盒(间隙));
添加(btnPanel);
}
私有类SaveChangesAction扩展了AbstractAction{
公共存储更改操作(字符串名称){
超级(姓名);
int助记符=(int)name.charAt(0);
putValue(助记符键,助记符);
}
@凌驾
已执行的公共无效操作(操作事件e){
int index=patientTable.getSelectedRow();
如果(指数<0){
返回;
}
//捕获尚未完成的编辑
if(ptVisitTable.isEditing()){
CellEditor CellEditor=ptVisitTable.getCellEditor();
如果(cellEditor!=null){
stopCellEditing();
}
}
索引=patientTable.convertRowIndexToModel(索引);
MyPatient selectedPatient=patientModel.getPatient(索引);
MyPtVisitTableModel visitsModel=(MyPtVisitTableModel)ptVisitTable.getModel();
列表访问=visitsModel.getvisions();
选择患者。设置就诊次数(就诊次数);
patientModel.SetPatientTat(索引,selectedPatient);
}
}
私有类PatientTableListener实现ListSelectionListener{
@凌驾
public void值已更改(ListSelectionEvent e){
如果(如getValueIsAdjusting()){
返回;
}
int index=patientTable.getSelectedRow();