单击 JButton 时不会填充 JTable
Posted
技术标签:
【中文标题】单击 JButton 时不会填充 JTable【英文标题】:JTable Won't populate when clicking JButton 【发布时间】:2017-03-28 18:08:13 【问题描述】:我正在开发的系统是一个收银系统,JTable
充当orderList
。我试过Vector
,也试过使用DefaultTableModel
,但我不确定如何让按钮拉出数据并将其添加到表格中。我知道这很难理解,但谁能告诉我我应该如何为一个 JButton
做这件事,然后其余的应该是相似的,我可以自己做吗?
我需要从数据库中提取productID
、productName
和Price
并添加到表中。
然后我将合计价格并为订单付款。
Order
//Order class for setting up and managing an order
package classes;
import java.sql.*;
import java.util.ArrayList;
import java.util.Vector;
public class Order
// Instance Variables
private int productID;
private String productName;
private String productDescription;
private String type;
private String supplierName;
private double quantity;
private double price;
// Connection To DB
// JDBC Driver name and database URL
final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
final String USER_NAME = "root";
final String PASSWORD = "password";
// sql variables
ResultSet resultSet = null;
private String itemName;
private double itemPrice;
// Constructors
public Order()
public Order(int productID, String itemName, double itemPrice, double quantity)
this.itemName = itemName;
this.itemPrice = itemPrice;
this.quantity = quantity;
// Get the details of stock items and add them to the order
public Vector getOrderItems()
ResultSet rs = null;
Statement statement = null;
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
Statement stmt = conn.createStatement();
String sqlString= "select ProductID, ProductName, Price from product";
stmt.executeUpdate(sqlString);
Vector vector = new Vector();
Vector<String> orderItem = new Vector<String>();
int i=0;
while(rs.next())
Vector<String> items = new Vector<String>();
rs.getInt("ProductID");
rs.getString("ProductName");
rs.getDouble("Price");
return vector;
catch(Exception e)
e.printStackTrace();
return null;
// Getter Methods
public int getProductID()
return productID;
public String getProductName()
return productName;
public String getProductDesc()
return productDescription;
public String getType()
return type;
public String getSupplierName()
return supplierName;
public double getQuantity()
return quantity;
public double getPrice()
return price;
Stock
// Stock class
//Team Project
//Stock class for setting up and managing stock
package classes;
import java.sql.*;
import java.util.*;
public class Stock
// Instance Variables
private int productID;
private String productName;
private String productDescription;
private String type;
private String supplierName;
private double quantity;
private double price;
// JDBC Driver name and database URL
final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
final String USER_NAME = "root";
final String PASSWORD = "password";
// sql variables
Statement statement = null;
ResultSet resultSet = null;
public Stock()
productID=0;
productName=null;
productDescription = null;
type = null;
supplierName=null;
quantity = 0;
price=0;
// Initialisation Constructor that initializes everything in DB
public Stock(int productID, String productName, String productDescription, String type, String supplierName,
double quantity, double price)
this.productID = productID;
this.productName = productName;
this.productDescription = productDescription;
this.type = type;
this.supplierName = supplierName;
this.quantity = quantity;
this.price = price;
// Add a new product into the product table
public void addProduct(int prodID, int amt)
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
Statement stmt = conn.createStatement();
String sqlString="insert into product " + "(ProductID, ProductName, ProductDescrp, type, SupplierName, Quantity, Price)"
+ " values(30, 'Marmalade', 'Homestead', 'Extras', 'Bakersworld', 20, 0.20)";
stmt.executeUpdate(sqlString);
conn.close();
catch(Exception e)
e.printStackTrace();
// Delete a product from the product table
public void delete(int prodNumIn)
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
Statement stmt = conn.createStatement();
String sqlString= "delete from team_Project.product where ProductID=" + prodNumIn;
stmt.executeUpdate(sqlString);
catch(Exception e)
e.printStackTrace();
// Subtracts quantity in stock in the DB When a sale is made on an item
public int deductStock(int prodID)
int status =0;
String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID)-1) + " WHERE ProductID = " + prodID);
status = databaseUpdate(sql);
return status;
// Add quantity to particular product in the DB if required
public int addToQuantity(int prodID, int amt)
int status =0;
String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID)+ amt) + " WHERE ProductID = " + prodID);
status = databaseUpdate(sql);
return status;
// return quantity of a product in DB
public int getDBQuantity(int prodID)
int quantity=0;
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
statement = (Statement) conn.createStatement();
resultSet = statement.executeQuery("select Quantity from team_project.product WHERE ProductID = " + prodID);
while (resultSet.next())
quantity = (resultSet.getInt("Quantity"));
conn.close();
catch(Exception e)
e.printStackTrace();
return quantity;
// get price of a particular product
public int getItemPrice(int prodID)
int price = 0;
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
statement = (Statement) conn.createStatement();
resultSet = statement.executeQuery("select Price from team_project.product WHERE ProductID = " + prodID);
while (resultSet.next())
price = (resultSet.getInt("Price"));
conn.close();
catch(Exception e)
e.printStackTrace();
System.out.println("€"+price);
return price;
// Method that returns all products in product table
public ArrayList<Stock> getProducts()
ArrayList<Stock> allStock = new ArrayList<Stock>();
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
statement = (Statement) conn.createStatement();
resultSet = statement.executeQuery("select * from team_project.product");
while (resultSet.next())
Stock stock = new Stock(resultSet.getInt("ProductID"), resultSet.getString("ProductName"),
resultSet.getString("ProductDescrp"),resultSet.getString("Type"),resultSet.getString("SupplierName"),
resultSet.getInt("Quantity"), resultSet.getDouble("Price"));
allStock.add(stock);
conn.close();
catch(Exception e)
e.printStackTrace();
return allStock;
// update method to call
// database update method
private int databaseUpdate(String sqlUpdate)
int status = 0;
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
statement = conn.createStatement();
status = statement.executeUpdate(sqlUpdate);
conn.close();
catch (Exception e)
e.printStackTrace();
return status;
// toString method for stock items
public String toString()
return productName + "";
// Getter Methods
public int getProductID()
return productID;
public String getProductName()
return productName;
public String getProductDesc()
return productDescription;
public String getType()
return type;
public String getSupplierName()
return supplierName;
public double getQuantity()
return quantity;
public double getPrice()
return price;
// 小美式监听器
americanoSmall.addActionListener(
new ActionListener()
public void actionPerformed(ActionEvent e)
try
String query = "select ProductName, Price from product where ProductID = 24";
java.sql.PreparedStatement pst = connection.prepareStatement(query);
ResultSet rs = pst.executeQuery();
table.setModel(DbUtils.resultSetToTableModel(rs));
catch (Exception e1)
e1.printStackTrace();
);
【问题讨论】:
那么您是否收到此代码的任何错误?或者你真正的问题是什么? 没有错误,我只是想知道我做错了什么,因为它什么也没做。有什么我想念的吗? 【参考方案1】:您的代码有点倾斜,您有一个 Stock
对象,但该对象似乎也在管理数据库,作为更长期的解决方案,我建议将这些问题分开,但现在我们将离开暂时是这样。
我要做的第一件事是定义模型的期望,你期望它做什么,你期望它如何工作
public interface MutableStockModel
public void add(Stock item) throws ModelException;
public void remove(Stock item) throws ModelException;
所以这是一个简单的接口,它定义了任何实现类都应该提供的几个动作。但你为什么要问?这是一个很好的问题,我很快就会回答。
您可以从TableModel
扩展MutableStockModel
,但这会将您锁定在可能无法满足您的长期需求的特定实施渠道中,此外,使用它的人关心什么,他们只是希望能够添加和删除产品
一个示例实现...
public class DefaultStockTableModel extends AbstractTableModel implements MutableStockModel
private List<Stock> items;
public DefaultStockTableModel()
items = new ArrayList<>(25);
public DefaultStockTableModel(List<Stock> items)
this.items = items;
@Override
public int getRowCount()
return items.size();
@Override
public int getColumnCount()
return 7;
@Override
public Class<?> getColumnClass(int columnIndex)
switch (columnIndex)
case 1:
case 2:
case 3:
case 4: return String.class;
case 0:
case 5:
case 7: return int.class;
return Object.class;
@Override
public String getColumnName(int column)
switch (column)
case 0: return "ID";
case 1: return "Name";
case 2: return "Description";
case 3: return "Type";
case 4: return "Supplier Name";
case 5: return "Quanity";
case 6: return "Price";
return null;
@Override
public Object getValueAt(int rowIndex, int columnIndex)
Stock item = items.get(rowIndex);
switch (columnIndex)
case 0: return item.getProductID();
case 1: return item.getProductName();
case 2: return item.getProductDesc();
case 3: return item.getType();
case 4: return item.getSupplierName();
case 5: return item.getQuantity();
case 6: return item.getPrice();
return null;
@Override
public void add(Stock item) throws ModelException
// Add the item to the database if required
items.add(item);
int row = items.indexOf(item);
fireTableRowsInserted(row, row);
@Override
public void remove(Stock item) throws ModelException
if (items.contains(item))
// Delete theitem from the database if required
int row = items.indexOf(item);
items.remove(row);
fireTableRowsDeleted(row, row);
所以这是一个基本示例,您的任何代码都不关心它的实际管理方式,只关心它是否符合合同要求。
要添加或删除产品,只需调用特定方法即可。
现在,您可以扩展此概念以使其更易于使用,例如...
public interface MutableStockTableModel extends MutableStockModel, TableModel
public void removeAt(int row) throws ModelException;
这是一个特定的、有针对性的实现,它允许您在特定行中删除一行。这扩展了TableModel
,因为TableModel
具有“行”的概念,而MutableStockModel
没有。当然,您必须更新任何实现 implement
这个特定的 interface
;)
好的,但是“为什么”?
简短的回答是,根据数据库,ResultSet
实际上可以直接进行变异,也就是说,您可以通过ResultSet
直接添加/插入、删除和更新行,有关更多详细信息,请参阅Retrieving and Modifying Values from Result Sets .
这意味着您可以创建一个TableModel
的实现,它实现了MutableStockTableModel
或MutableStockModel
接口,但它引用了原始ResultSet
作为其内部结构。
听起来很简单,但是当您意识到您可以更改 TableModel
的任何实例来满足实现要求而不影响您的任何代码的任何实现时,它就会带来很多可能性。
因此,例如,您可以使用
private MutableStockTableModel tableModel;
//...
tableModel = new ResultSetMutableStockTableModel(resultSet);
table.setModel(tableModel);
//...
tableModel.add(stockItem);
但您可以简单地将 tableModel
更改为不同的实例...
tableModel = new DefaultStockTableModel(listOfItems);
没有什么需要改变的!
所以,这是“编码到接口,而不是实现”的基本示例,我可以进一步解耦代码,但我不想让你不知所措;)p>
回到我的第一条评论,OO 提倡Single Responsibility Principle,这意味着任何对象都应该有一个单一的职责(或工作)。
这可能表明,例如,您应该分离 Stock
类的功能。
我的,我会从一个 interface
开始,令人惊讶的是...
public interface Stock
public int getProductID();
public String getProductName();
public String getProductDesc();
public String getType();
public String getSupplierName();
public double getQuantity();
public double getPrice();
然后你会有某种实现......
public class DefaultStock implements Stock
// Instance Variables
private int productID;
private String productName;
private String productDescription;
private String type;
private String supplierName;
private double quantity;
private double price;
public DefaultStock()
productID = 0;
productName = null;
productDescription = null;
type = null;
supplierName = null;
quantity = 0;
price = 0;
// Initialisation Constructor that initializes everything in DB
public DefaultStock(int productID, String productName, String productDescription, String type, String supplierName,
double quantity, double price)
this.productID = productID;
this.productName = productName;
this.productDescription = productDescription;
this.type = type;
this.supplierName = supplierName;
this.quantity = quantity;
this.price = price;
// toString method for stock items
@Override
public String toString()
return productName + "";
// Getter Methods
@Override
public int getProductID()
return productID;
@Override
public String getProductName()
return productName;
@Override
public String getProductDesc()
return productDescription;
@Override
public String getType()
return type;
@Override
public String getSupplierName()
return supplierName;
@Override
public double getQuantity()
return quantity;
@Override
public double getPrice()
return price;
然后你可能会有某种经理/控制器/工厂...
(是的,我很想通过某种界面来描述这一点,但这已经是一篇很长的帖子了)
public class StockManager
// JDBC Driver name and database URL
final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
final String DB_URL = "jdbc:mysql://localhost/team_project?useSSL=false";
final String USER_NAME = "root";
final String PASSWORD = "password";
// sql variables
Statement statement = null;
ResultSet resultSet = null;
// Add a new product into the product table
public void addProduct(int prodID, int amt)
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
Statement stmt = conn.createStatement();
String sqlString = "insert into product " + "(ProductID, ProductName, ProductDescrp, type, SupplierName, Quantity, Price)"
+ " values(30, 'Marmalade', 'Homestead', 'Extras', 'Bakersworld', 20, 0.20)";
stmt.executeUpdate(sqlString);
conn.close();
catch (Exception e)
e.printStackTrace();
// Delete a product from the product table
public void delete(int prodNumIn)
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
Statement stmt = conn.createStatement();
String sqlString = "delete from team_Project.product where ProductID=" + prodNumIn;
stmt.executeUpdate(sqlString);
catch (Exception e)
e.printStackTrace();
// Subtracts quantity in stock in the DB When a sale is made on an item
public int deductStock(int prodID)
int status = 0;
String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID) - 1) + " WHERE ProductID = " + prodID);
status = databaseUpdate(sql);
return status;
// Add quantity to particular product in the DB if required
public int addToQuantity(int prodID, int amt)
int status = 0;
String sql = ("UPDATE product " + "SET Quantity = " + (getDBQuantity(prodID) + amt) + " WHERE ProductID = " + prodID);
status = databaseUpdate(sql);
return status;
// return quantity of a product in DB
public int getDBQuantity(int prodID)
int quantity = 0;
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
statement = (Statement) conn.createStatement();
resultSet = statement.executeQuery("select Quantity from team_project.product WHERE ProductID = " + prodID);
while (resultSet.next())
quantity = (resultSet.getInt("Quantity"));
conn.close();
catch (Exception e)
e.printStackTrace();
return quantity;
// get price of a particular product
public int getItemPrice(int prodID)
int price = 0;
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
statement = (Statement) conn.createStatement();
resultSet = statement.executeQuery("select Price from team_project.product WHERE ProductID = " + prodID);
while (resultSet.next())
price = (resultSet.getInt("Price"));
conn.close();
catch (Exception e)
e.printStackTrace();
System.out.println("€" + price);
return price;
// Method that returns all products in product table
public ArrayList<Stock> getProducts()
ArrayList<Stock> allStock = new ArrayList<Stock>();
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
statement = (Statement) conn.createStatement();
resultSet = statement.executeQuery("select * from team_project.product");
while (resultSet.next())
Stock stock = new DefaultStock(resultSet.getInt("ProductID"), resultSet.getString("ProductName"),
resultSet.getString("ProductDescrp"), resultSet.getString("Type"), resultSet.getString("SupplierName"),
resultSet.getInt("Quantity"), resultSet.getDouble("Price"));
allStock.add(stock);
conn.close();
catch (Exception e)
e.printStackTrace();
return allStock;
// update method to call
// database update method
private int databaseUpdate(String sqlUpdate)
int status = 0;
try
Class.forName("com.mysql.jdbc.Driver");
Connection conn = (Connection) DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD);
statement = conn.createStatement();
status = statement.executeUpdate(sqlUpdate);
conn.close();
catch (Exception e)
e.printStackTrace();
return status;
我还鼓励您查看Using Prepared Statements 以改进整体代码
【讨论】:
你的解决方案是完美的,它涵盖了所有问题,加 1 ;)【参考方案2】:第一部分
首先:当你想使用 SELECT 时,你必须使用 stmt.executeQuery(sqlString);
或 stmt.execute(sqlString);
而不是 executeUpdate
当你想要进行插入更新或删除时使用它: p>
stmt.executeQuery(sqlString);
第二:我认为您的 URL 中缺少某些内容,您缺少端口号:
"jdbc:mysql://localhost/team_project?useSSL=false";
//---------------------^--------------------------
应该是这样的,MySQL的默认端口是3306
:
"jdbc:mysql://localhost:3306/team_project?useSSL=false";
注意使用语句不安全,可能会导致语法错误或SQL注入,我建议使用PreparedStatement,它更安全,更有用
第二部分
为了填充您的 JTable,我通常使用这种方式:
//call this method to fill your Object in your JTable when you click to your button
private void fillData(List<MY_OBJECT> list) //method which take a list of objects
DefaultTableModel model = (DefaultTableModel) jTableName.getModel();
// empty your JTable
model.setRowCount(0);
//Fill your JTbale
for (MY_OBJECT obj : list)
model.addRow(new Object[]
obj.getAttribute1(),
obj.getAttribute2,
obj.getAttribute3
);
【讨论】:
好的,我会做出建议的更改,并告诉你它是如何工作的。 java.sql.SQLException:连接属性“useSSL”仅接受以下形式的值:“true”、“false”、“yes”或“no”。值'假;'不在这个集合中.. 从您的 URL @Movillian 中删除?useSSL=false
好的,连接错误已修复。谢谢
不,现在连接正常。谢谢你。我只是想试试下面@Timothy Truckle 的例子,看看我是否可以在我的系统中实现它。【参考方案3】:
这里是Minimal, Complete, and Verifiable example (MCVE)如何填充表格:
public class TableAddRowButton
public static class Order
static int idCounter = 0;
private int productID = ++idCounter;
private String productName = "Product" + productID;
private double quantity = new Random().nextInt(1000);
private double price = new Random().nextInt(1000);
public static void main(String[] args)
Vector<Order> orders = new Vector<>();
DefaultTableModel tableModel = createTableModel(orders);
JButton button = createAddRowButton(orders, tableModel);
JPanel panel = new JPanel(new BorderLayout());
panel.add(button, BorderLayout.NORTH);
panel.add(new JScrollPane(new JTable(tableModel)));
JOptionPane.showMessageDialog(null, panel);
private static JButton createAddRowButton(Vector<Order> orders, DefaultTableModel tableModel)
JButton button = new JButton(new AbstractAction("add row")
@Override
public void actionPerformed(ActionEvent arg0)
orders.add(new Order());
tableModel.fireTableRowsInserted(orders.size() - 2, orders.size() - 1);
);
return button;
private static DefaultTableModel createTableModel(Vector<Order> orders)
DefaultTableModel tableModel = new DefaultTableModel(
new Vector<>(Arrays.asList("ID", "Name", "quantity", "price")), orders.size())
@Override
public int getRowCount()
return orders.size();
@Override
public Object getValueAt(int row, int column)
switch (column)
case 0:
return orders.get(row).productID;
case 1:
return orders.get(row).productName;
case 2:
return orders.get(row).quantity;
case 3:
return orders.get(row).price;
default:
return "";
@Override
public boolean isCellEditable(int row, int column)
return false;
;
return tableModel;
【讨论】:
(1-) 数据更新应该通过 TableModel 完成,而不是 Vector。所以你需要添加一个像 addOrder(...) 这样的方法。然后由模型负责调用 fireTableRowsInserted(...) 方法。 “数据的更新应该通过 TableModel 完成”您能否发布您自己的答案,表明您的方法是:更短且更具可读性? 这不是关于更短或可读性,而是关于遵循 MVC 设计原则。 “它关于遵循 MVC 设计原则” 那么模式必须在过去 15 年内发生变化仅对象... 那么我现在如何将这个概念应用到我自己的问题中呢?记住我不能使用 Random,我需要尝试从数据库中提取所有需要的数据并添加到 JTable 中跨度>以上是关于单击 JButton 时不会填充 JTable的主要内容,如果未能解决你的问题,请参考以下文章