英文:
Why isn't JTable ModelListener working and how do you save JTabel cell edits to DB?
问题
public class InventoryFrame extends JFrame {
// ... (Other code)
public InventoryFrame() throws Exception {
// ... (Other code)
itm.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
actualizeTable(e);
}
});
}
public void actualizeTable(TableModelEvent e) {
System.out.println("进入编辑..." + e.getType() + ", " + TableModelEvent.UPDATE);
if ((int) e.getType() == TableModelEvent.UPDATE) {
System.out.println("正在编辑...");
InventoryTableModel model = (InventoryTableModel) ((TableModel) e.getSource());
int row = e.getFirstRow();
int column = e.getColumn();
String input = String.valueOf(model.getValueAt(jt.getSelectedRow(), jt.getSelectedColumn()));
dbman.update(column, input);
model.setValueAt(input, row, column);
pack();
setSize(800, 600);
doLayout();
}
}
}
public class InventoryTableModel extends AbstractTableModel {
// ... (Other code)
@Override
public int getColumnCount() {
return columnCnt;
}
@Override
public int getRowCount() {
return rowCount;
}
@Override
public Object getValueAt(int row, int col) {
// ... (Other code)
}
// ... (Other code)
}
public class DatabaseManager() throws Exception {
// ... (Other code)
public ResultSet getAllQuery() {
// ... (Other code)
}
public void update(int col, String input) {
// ... (Other code)
}
}
以上是您提供的代码的翻译。如果您需要更多帮助或解释,请随时问我。
英文:
My goal is to be able to edit a JTable cell that, once edited and saved, saves the value into the database and loads the value onto the JTable. Currently, once I try to edit a JTable cell and press enter, the data does not get saved. I have realized that the TableModelListener is not being called; the system.out code in the actualizeTable model is not working.
The following code is for the Frame; I have taken out some codes (namely the JButton ActionListeners) as they are deemed unnecessary for this topic.
public class InventoryFrame extends JFrame{
DatabaseManager dbman;
private JPanel p = new JPanel();
private final JButton getAll = new JButton("Get All");
private final JButton add = new JButton("Add");
private final JButton delete = new JButton("Delete");
private final JButton edit = new JButton("Edit");
private ResultSet rs;
private JTable jt;
public InventoryFrame() throws Exception {
// TODO Auto-generated constructor stub
super();
setTitle("Inventory");
setSize(800,600);
p.setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
isResizable();
getContentPane().add(p);
p.add(getAll, BorderLayout.NORTH);
dbman = new DatabaseManager();
if(null == rs) {
rs = dbman.getAllQuery();
}
InventoryTableModel itm = new InventoryTableModel(rs);
getAll.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
jt = new JTable(itm);
jt.setColumnSelectionAllowed(true);
jt.setRowSelectionAllowed(true);
/*if (jt.getCellEditor() != null) {
jt.getCellEditor().stopCellEditing();
}*/
JScrollPane sp = new JScrollPane(jt);
p.add(sp, BorderLayout.CENTER);
pack();
setSize(800,600);
doLayout();
}
});
itm.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
// TODO Auto-generated method stub
actualizeTable(e);
}
});
public void actualizeTable(TableModelEvent e) {
System.out.println("entering editing..."+e.getType()+", "+TableModelEvent.UPDATE);
if ((int) e.getType() == TableModelEvent.UPDATE) {
System.out.println("editing...");
InventoryTableModel model = (InventoryTableModel) ((TableModel) e.getSource());
int row = e.getFirstRow();
int column = e.getColumn();
String input = String.valueOf(model.getValueAt(jt.getSelectedRow(), jt.getSelectedColumn()));
dbman.update(column, input);
model.setValueAt(input, row, column);
pack();
setSize(800,600);
doLayout();
}
}
}
Here is my InventoryTableModel class:
public class InventoryTableModel extends AbstractTableModel {
private ResultSet rset;
private int rowCount = 0;
private int columnCnt=0;
private String columnName = "";
public InventoryTableModel(ResultSet rs){
// TODO Auto-generated constructor stub
rset = rs;
try {
if(rset.last()) {
rowCount = rset.getRow();
}
columnCnt = rset.getMetaData().getColumnCount();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public int getColumnCount() {
return columnCnt;
}
@Override
public int getRowCount() {
return rowCount;
}
@Override
public Object getValueAt(int row, int col) {
// TODO Auto-generated method stub
try {
if(!rset.absolute(row+1)) {
return null;
}
Object value = rset.getObject(col +1);
//System.out.println("value is: "+value);
return value;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public boolean isCellEditable(int row, int col) {
return true;
}
public String getColumnName(int col) {
try {
String colName = rset.getMetaData().getColumnName(col+1);
if (colName.equals("ProductID")) {
return "Product ID";
} else if (colName.equals("ProductName")){
return "Product Name";
} else if (colName.equals("DateAdded")) {
return "Date Added";
}
return colName;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
}
This is the update() method that is called and parts of the DatabaseManager class:
public DatabaseManager() throws Exception {
try {
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/inventory", username, password);
statement = connection.createStatement();
System.out.println("Successfully Connected");
} catch (Exception e) {
throw e;
}
}
public ResultSet getAllQuery() {
try {
resultSet = statement.executeQuery("select * from inventory");
} catch (Exception e){
e.printStackTrace();
}
return resultSet;
}
public void update(int col, String input) {
String colName = "";
if (col == 1) {
colName = "ProductID";
} else if (col == 2) {
colName = "ProductName";
} else if (col == 3) {
colName = "Price";
} else if (col == 4) {
colName = "Quantity";
} else if (col == 5) {
colName = "Description";
} else if (col == 6) {
colName = "Category";
} else if (col == 7) {
colName = "DateAdded";
}
try {
String query = "UPDATE INVENTORY "
+ "SET "+colName+ "= ?"
+ " WHERE PRODUCTID = ?";
pstatement = connection.prepareStatement(query);
pstatement.setString(1, input);
pstatement.setInt(2, col);
pstatement.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
Any help would be appreciated!
答案1
得分: 1
我的目标是能够编辑 JTable 单元格,一旦编辑并保存,将值保存到数据库并加载到 JTable 上。
你对 JTable
和/或 TableModelListener
的理解是错误的。
当你编辑 JTable
中的单元格时,数据将通过 setValueAt(...)
方法存储在 TableModel
中。然后,setValueAt()
方法将调用 TableModelListener
来指示 TableModel
发生了更改。
你没有收到 TableModelEvent
,是因为你的 TableModel
没有实现 setValueAt(...)
方法。
我建议你不需要创建自定义的 TableModel
。相反,将数据从你的 ResultSet
复制到 DefaultTableModel
,然后在你的 JTable
中使用 DefaultTableModel
。
DefaultTableModel
确实实现了 setValueAt(...)
。因此,当你编辑 JTable
时,数据将保存到 TableModel
中,并且将生成 TableModelEvent
。在 TableModelListener
中,你可以更新你的数据库。
参考:https://stackoverflow.com/questions/55627828/how-to-get-a-defaulttablemodel-objects-data-into-a-subclass-of-defaulttablemode/55635012#55635012,这个示例展示了如何将数据从 ResultSet
通用地加载到 DefaultTableModel
。
英文:
> My goal is to be able to edit a JTable cell that, once edited and saved, saves the value into the database and loads the value onto the JTable.
Your understanding of the JTable
and/or TableModelListener
is incorrect.
When you edit a cell in the JTable
, the data will be stored in the TableModel
via the setValueAt(...)
method. The setValueAt()
method will then invoke the TableModelListener
to indicate that a change to the TableModel
has occured.
You don't get the TableModelEvent
because your TableModel
doesn't implement the setValueAt(...)
method.
I would suggest there is no need for you to create a custom TableModel
. Instead, copy the data from your ResultSet
to the DefaultTableModel
and then use the DefaultTableModel
in your JTable
.
The DefaultTableModel
does implement setValueAt(...)
. So when you edit the JTable
, the data will be saved to the TableModel
and the TableModelEvent
will be generated. In the TableModelListener
you can then update your database.
Check out: https://stackoverflow.com/questions/55627828/how-to-get-a-defaulttablemodel-objects-data-into-a-subclass-of-defaulttablemode/55635012#55635012 for an example that shows how to generically load data from a ResultSet
to the DefaultTableModel
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论