jtable 只用链表中的值填充一行

jtable only populates one row with value from the linkedlist

所以我有这个 class,其中包含员工的姓名、地址和城市。之后 class 被存储在链表中,当用户在文本字段中输入姓名、地址和城市时,这些值将被插入到链表中,然后填充到 jtable 中。到目前为止,我已经能够获取用户详细信息并将其添加到喜欢的列表中,但是当我单击添加按钮时,如果我在文本字段中插入一些其他值,它只会向 table 添加一行然后再次单击添加按钮,它只是删除了先前添加的行并添加了仍然只显示一行的新行,我希望 jtable 显示所有值。这是我的代码。

public class EmployeeDetails extends javax.swing.JFrame {
String [] str = {"NAME", "ADDRESS", "CITY", "ZICODE"};
LinkedList<EmployeeDetails> linkedlist;
String name;
String address;
String city;
String zipcode;


public EmployeeDetails(String name, String address, String city, String zipcode) {
   this.name = name;
   this.address = address;
   this.city = city;
   this.zipcode = zipcode;
}

public void setName(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

public void setAddres(String address) {
    this.address = address;
}

public String getAddress() {
    return address;
}

public void setCity(String city) {
    this.city = city;
}

public String getCity() {
    return city;
}

public void setZip(String zipcode) {
    this.zipcode = zipcode;
}

public String getZip() {
    return zipcode;
}

public String toString() {
    return name + " " + address + " " + city + " " + zipcode;
}

public EmployeeDetails() {
    initComponents();
}

//this is the method that does the adding
public void add() {
    name = nametxt.getText().trim();
    address = addresstxt.getText().trim();
    city = citytxt.getText().trim();
    zipcode = zipcodetxt.getText().trim();

    linkedlist = new LinkedList<>();
    linkedlist.add(new EmployeeDetails(name, address, city, zipcode));
    DefaultTableModel model = new DefaultTableModel(str, linkedlist.size());

    for(EmployeeDetails details : linkedlist) {
        System.out.println(details);
        model.addRow(new Object[]{details.getName()details.getAddress(), details.getCity(), details.getZip()});
    }

    employeeTable.setModel(model);
}
}

看看你的add方法。它创建一个新的 LinkedList 添加一个 EmployeeDetails(从 JFrame 扩展!!这不会很好地结束),创建一个新的 TableModel 并添加(单个) EmployeeDetails 然后应用到 employeeTable ...你为什么感到惊讶?

没有理由 EmployeeDetails 应该从基于 UI 的组件扩展,它为您提供零收益。 EmployeeDetails class 也不负责管理任何形状或形式的 UI。

OO 开发的一个关键方面是职责分离。 EmployeeDetails 应该管理员工详细信息,没有别的...

public class EmployeeDetails {

    String name;
    String address;
    String city;
    String zipcode;

    public EmployeeDetails(String name, String address, String city, String zipcode) {
        this.name = name;
        this.address = address;
        this.city = city;
        this.zipcode = zipcode;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAddres(String address) {
        this.address = address;
    }

    public String getAddress() {
        return address;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setZip(String zipcode) {
        this.zipcode = zipcode;
    }

    public String getZip() {
        return zipcode;
    }

    public String toString() {
        return name + " " + address + " " + city + " " + zipcode;
    }

}

虽然 DefaultTableModel 是一个强大而灵活的模型,但它也...有点基础。对我来说,我更喜欢可以管理它显示的对象并更好地决定它们应该如何显示的东西。当涉及模型 mutable 状态时,这一点更为关键(是否应该允许添加、删除甚至编辑单个行?)

在您的情况下,您希望至少能够添加新的 EmployeeDetails 个对象...

public static class EmployeeTableModel extends AbstractTableModel {
    
    protected static String [] COLUMN_NAMES = {"NAME", "ADDRESS", "CITY", "ZICODE"};
    
    private List<EmployeeDetails> rows = new ArrayList<>(25);

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

    @Override
    public int getColumnCount() {
        return COLUMN_NAMES.length;
    }

    @Override
    public String getColumnName(int column) {
        return COLUMN_NAMES[column];
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        EmployeeDetails ed = rows.get(rowIndex);
        switch (columnIndex) {
            case 0: return ed.getName();
            case 1: return ed.getAddress();
            case 2: return ed.getCity();
            case 3: return ed.getZip();
        }
        return null;
    }
    
    public void add(EmployeeDetails ed) {
        rows.add(ed);
        int row = rows.size() - 1;
        fireTableRowsInserted(row, row);
    }
    
    public void remove(EmployeeDetails ed) {
        int row = rows.indexOf(ed);
        if (row < 0) {
            return;
        }
    }
    
    public void remove(int row) {
        if (row < 0 || row > rows.size()) {
            return;
        }
        rows.remove(row);
        fireTableRowsInserted(row, row);
    }
}

除了管理模型的状态之外,该模型不做任何其他事情。我更复杂的解决方案可能有一个额外的 model/controller 来管理新对象的创建方式以及现有对象的更新或删除方式,但我会把它留给你来添加。

最后,我们可以将它们拼接在一起...

public class TestPane extends JPanel {

    private EmployeeTableModel model = new EmployeeTableModel();
    
    public TestPane() {
        setLayout(new BorderLayout());
        add(new JScrollPane(new JTable(model)));
        
        JButton add = new JButton("Add");
        add.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int row = model.getRowCount();
                EmployeeDetails ed = new EmployeeDetails("Employee " + row, "@ " + row, "Metro" + row, Integer.toString(row));
                model.add(ed);
            }
        });
        add(add, BorderLayout.SOUTH);
    }
    
}

一个带有一个按钮和一个 table 的简单面板,现在您可以混合添加按钮并观察您的员工列表增长...希望您有足够的资金 ;)

确保您花时间通读 How to Use Tables,其中包含许多重要且相关的信息以及您可以使用的可运行示例

可运行示例...

import java.awt.BorderLayout;
import java.awt.EventQueue;
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.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private EmployeeTableModel model = new EmployeeTableModel();

        public TestPane() {
            setLayout(new BorderLayout());
            add(new JScrollPane(new JTable(model)));

            JButton add = new JButton("Add");
            add.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int row = model.getRowCount();
                    EmployeeDetails ed = new EmployeeDetails("Employee " + row, "@ " + row, "Metro" + row, Integer.toString(row));
                    model.add(ed);
                }
            });
            add(add, BorderLayout.SOUTH);
        }

    }

    public static class EmployeeTableModel extends AbstractTableModel {

        protected static String [] COLUMN_NAMES = {"NAME", "ADDRESS", "CITY", "ZICODE"};

        private List<EmployeeDetails> rows = new ArrayList<>(25);

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

        @Override
        public int getColumnCount() {
            return COLUMN_NAMES.length;
        }

        @Override
        public String getColumnName(int column) {
            return COLUMN_NAMES[column];
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            EmployeeDetails ed = rows.get(rowIndex);
            switch (columnIndex) {
                case 0: return ed.getName();
                case 1: return ed.getAddress();
                case 2: return ed.getCity();
                case 3: return ed.getZip();
            }
            return null;
        }

        public void add(EmployeeDetails ed) {
            rows.add(ed);
            int row = rows.size() - 1;
            fireTableRowsInserted(row, row);
        }

        public void remove(EmployeeDetails ed) {
            int row = rows.indexOf(ed);
            if (row < 0) {
                return;
            }
        }

        public void remove(int row) {
            if (row < 0 || row > rows.size()) {
                return;
            }
            rows.remove(row);
            fireTableRowsInserted(row, row);
        }
    }

    public class EmployeeDetails {

        String name;
        String address;
        String city;
        String zipcode;

        public EmployeeDetails(String name, String address, String city, String zipcode) {
            this.name = name;
            this.address = address;
            this.city = city;
            this.zipcode = zipcode;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setAddres(String address) {
            this.address = address;
        }

        public String getAddress() {
            return address;
        }

        public void setCity(String city) {
            this.city = city;
        }

        public String getCity() {
            return city;
        }

        public void setZip(String zipcode) {
            this.zipcode = zipcode;
        }

        public String getZip() {
            return zipcode;
        }

        public String toString() {
            return name + " " + address + " " + city + " " + zipcode;
        }

    }

}