Why isn't JTable ModelListener working and how do you save JTabel cell edits to DB?

huangapple go评论71阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2020年8月15日 02:36:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/63418352.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定