JScrollPane 没有正确更新
JScrollPane doesn't update properly
我必须在 JTable 中插入新产品,以便在按下 "Add product" 按钮后,table 应该自行更新所提供的新数据。所有产品都写入一个文件,并在打印 table 时从中读取。问题是我的 table 保持不变,只有在我退出 GUI 应用程序并再次进入后,我才能看到新更新的 JTable。
这是来自 GUI class 的相关代码:
private class ManageProductsListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
...
addProductBtn.addActionListener(new AddProductListener());
removeProductBtn.addActionListener(new RemoveProductListener());
manageProductsPanel.add(warehouse);
manageProductsPanel.setVisible(true);
finalPanel.add(manageProductsPanel, BorderLayout.CENTER);
}
}
private class AddProductListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
...
manageProductsPanel.remove(warehouse);
Product product = new Product(insertProductName.getText(), Integer.parseInt(insertPrice.getText()), Integer.parseInt(insertStock.getText()));
warehouse.addProduct(product);
warehouse.writeFile();
warehouse.printProducts();
manageProductsPanel.add(warehouse);
...
}
}
这是仓库中的一部分 class:
public class Warehouse extends JPanel {
...
private TreeSet<Product> products = new TreeSet<Product>();
private JTable productsTable;
private Object[][] data;
private String[] columns = {"Product name", "Price", "In stock", "Understock", "Overstock"};
public Warehouse() {
}
public void addProduct(Product newProduct) {
products.add(newProduct);
}
public void writeFile() {
try {
FileOutputStream fos = new FileOutputStream("products.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Iterator<Product> i = products.iterator();
while (i.hasNext()) {
oos.writeObject(i.next());
}
oos.close();
} catch (IOException i) {
i.printStackTrace();
}
}
public void readFile() {
...
}
public void printProducts() {
data = new Object[products.size()][5];
Iterator<Product> iterator = products.iterator();
int i = 0;
while (iterator.hasNext()) {
Product p = iterator.next();
data[i][0] = p.getProductName();
data[i][1] = p.getPrice();
data[i][2] = p.getStock();
data[i][3] = p.checkUnderstock();
data[i][4] = p.checkOverstock();
i++;
}
createTable();
}
public void createTable() {
productsTable = new JTable(data, columns);
productsTable.setPreferredScrollableViewportSize(new Dimension(600, 200));
productsTable.setFillsViewportHeight(true);
JScrollPane scroll = new JScrollPane(productsTable);
add(scroll);
}
如有任何帮助,我们将不胜感激。提前致谢!
无法添加评论,所以我必须 post 它作为答案。添加 table 后,您是否尝试过重新验证您的面板?
manageProductsPanel.revalidate()
products.add(newProduct);
您不应该更新产品 TreeSet。这不会更新 TableModel 中的数据,因此 table 当然不会更新。数据应仅包含在 TableModel 中,对数据的所有更新都应直接对 TableModel 进行。
因此您需要一个可以容纳 Product 对象的自定义 TableModel。
查看 Row Table Model 以获取允许您存储自定义对象的通用 TableModel。 JButtonTableModel.java
代码随后展示了如何扩展 RowTableModel 以支持您的自定义对象。
然后当您创建一个新产品时,您只需使用新创建的 ProductTableModel 的 addRow(...) 方法。
编辑:
上面的答案是正确的解决方案。您永远不应保留数据的两个副本。
I add another new product another new table appears and so on
那是因为您的 Warehouse class 是一个使用 FlowLayout 的 JPanel,因此当您不断向其中添加组件时,面板只会不断增长。
解决方案是不要继续创建新组件。然后在添加新产品时无需继续创建新的 JTable 和 JScrollPanse。
相反,当您创建 Warehouse class 时,您会创建 table 和 ScrollPane。 table 将为空。
然后当您将产品添加到产品列表时,您可以创建一个新的 DefaultTablModel。然后你只需使用 table.setModel(...)
方法来更新 table。现在 table 将使用新数据重绘自身。
另一种可能无痛的解决方案是在更新后重置 table 的模型:
productsTable.setModel(new DefaultTableModel(data, columns));
我必须在 JTable 中插入新产品,以便在按下 "Add product" 按钮后,table 应该自行更新所提供的新数据。所有产品都写入一个文件,并在打印 table 时从中读取。问题是我的 table 保持不变,只有在我退出 GUI 应用程序并再次进入后,我才能看到新更新的 JTable。
这是来自 GUI class 的相关代码:
private class ManageProductsListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
...
addProductBtn.addActionListener(new AddProductListener());
removeProductBtn.addActionListener(new RemoveProductListener());
manageProductsPanel.add(warehouse);
manageProductsPanel.setVisible(true);
finalPanel.add(manageProductsPanel, BorderLayout.CENTER);
}
}
private class AddProductListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
...
manageProductsPanel.remove(warehouse);
Product product = new Product(insertProductName.getText(), Integer.parseInt(insertPrice.getText()), Integer.parseInt(insertStock.getText()));
warehouse.addProduct(product);
warehouse.writeFile();
warehouse.printProducts();
manageProductsPanel.add(warehouse);
...
}
}
这是仓库中的一部分 class:
public class Warehouse extends JPanel {
...
private TreeSet<Product> products = new TreeSet<Product>();
private JTable productsTable;
private Object[][] data;
private String[] columns = {"Product name", "Price", "In stock", "Understock", "Overstock"};
public Warehouse() {
}
public void addProduct(Product newProduct) {
products.add(newProduct);
}
public void writeFile() {
try {
FileOutputStream fos = new FileOutputStream("products.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Iterator<Product> i = products.iterator();
while (i.hasNext()) {
oos.writeObject(i.next());
}
oos.close();
} catch (IOException i) {
i.printStackTrace();
}
}
public void readFile() {
...
}
public void printProducts() {
data = new Object[products.size()][5];
Iterator<Product> iterator = products.iterator();
int i = 0;
while (iterator.hasNext()) {
Product p = iterator.next();
data[i][0] = p.getProductName();
data[i][1] = p.getPrice();
data[i][2] = p.getStock();
data[i][3] = p.checkUnderstock();
data[i][4] = p.checkOverstock();
i++;
}
createTable();
}
public void createTable() {
productsTable = new JTable(data, columns);
productsTable.setPreferredScrollableViewportSize(new Dimension(600, 200));
productsTable.setFillsViewportHeight(true);
JScrollPane scroll = new JScrollPane(productsTable);
add(scroll);
}
如有任何帮助,我们将不胜感激。提前致谢!
无法添加评论,所以我必须 post 它作为答案。添加 table 后,您是否尝试过重新验证您的面板?
manageProductsPanel.revalidate()
products.add(newProduct);
您不应该更新产品 TreeSet。这不会更新 TableModel 中的数据,因此 table 当然不会更新。数据应仅包含在 TableModel 中,对数据的所有更新都应直接对 TableModel 进行。
因此您需要一个可以容纳 Product 对象的自定义 TableModel。
查看 Row Table Model 以获取允许您存储自定义对象的通用 TableModel。 JButtonTableModel.java
代码随后展示了如何扩展 RowTableModel 以支持您的自定义对象。
然后当您创建一个新产品时,您只需使用新创建的 ProductTableModel 的 addRow(...) 方法。
编辑:
上面的答案是正确的解决方案。您永远不应保留数据的两个副本。
I add another new product another new table appears and so on
那是因为您的 Warehouse class 是一个使用 FlowLayout 的 JPanel,因此当您不断向其中添加组件时,面板只会不断增长。
解决方案是不要继续创建新组件。然后在添加新产品时无需继续创建新的 JTable 和 JScrollPanse。
相反,当您创建 Warehouse class 时,您会创建 table 和 ScrollPane。 table 将为空。
然后当您将产品添加到产品列表时,您可以创建一个新的 DefaultTablModel。然后你只需使用 table.setModel(...)
方法来更新 table。现在 table 将使用新数据重绘自身。
另一种可能无痛的解决方案是在更新后重置 table 的模型:
productsTable.setModel(new DefaultTableModel(data, columns));