I have a JTable with DefaultTableModel. I want to refresh the JTable whenever I click on the JTable. Below is my code using modelTarget.fireTableDataChanged(); to refresh the JTable.
but the values shown within the JTable does not change when click action is performed.
Initializing component and inserting values into table:
final TestClass test = new TestClass();
String sql = "SELECT * FROM student";
ResultSet rs = test.stmt.executeQuery(sql);
JTable table = new JTable();
DefaultTableModel model = new DefaultTableModel(0, 0);
String header[] = new String[] { "ID", "Name"};
model.setColumnIdentifiers(header);
table.setModel(model); //set model into table object
while (rs.next())
{
int id = rs.getInt("id");
String name = rs.getString("name");
//Add rows into table
model.addRow(new Object[] { id, name});
}
Listener for JTable:
table.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e) {
String sql = "UPDATE student " + "SET name='Alice' " + "WHERE id=7";
JTable target = (JTable)e.getSource();
int row = target.getSelectedRow();
try{test.stmt.executeUpdate(sql);}
catch(SQLException err){System.out.println("SQL Error!");};
System.out.println(target.getModel().getValueAt(row, 0)); //get row value
DefaultTableModel modelTarget = (DefaultTableModel) target.getModel();
modelTarget.fireTableDataChanged(); //JTable did not refresh with this code
}
});
Que: Do I need to do anything else to the table model before using .fireTableDataChanged() ? If not, what else can I do to let the JTable refresh?
EDIT: I am suspecting that the table model did not receive the changes which I made to the sql tables. So is there any way I can "refresh" or "update" the table model?
EDIT: I managed to let it work now by writing a method to empty all rows in current model and re-add all the rows according to the updated database. I did not use fireTableDataChanged() at all. Anyone in human history managed to let fireTableDataChanged() work?
Related
I am trying to display the records on JTable when the frame is loaded, but the records didn't display. This is what I've tried so far:
public void load()
{
try {
Connection con1;
PreparedStatement insert;
Class.forName("com.mysql.jdbc.Driver");
con1 = DriverManager.getConnection("jdbc:mysql://localhost/javapos","root","");
insert = con1.prepareStatement("SELECT name,status FROM category");
ResultSet Rs = insert.executeQuery();
while(Rs.next()){
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
String name = Rs.getString("name");
String status = Rs.getString("status");
model.addRow(new Object[]{name,status });
}
jTable1.setModel(model);
} catch (Exception e) {
System.out.println("Failed " + e);
}
}
My guess since your code should not compile but seems to (you are seing an empty JTable after all).
You have declare a DefaultTableModel model before the snippet.
How do I know that? With the code you proposed jTable1.setModel(model); can't compile because model doesn't exist in the scope (outside of the loop).
while(Rs.next()){
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
String name = Rs.getString("name");
String status = Rs.getString("status");
model.addRow(new Object[]{name,status });
}
jTable1.setModel(model);
Compile error :
"model" cannot be resolved to a variable.
I would guess you have declare it somewhere before. In the loop you declare a new one in a different scope, hiding the original one. In this last model instance, you insert your rows.
But after the loop, you set the first model that have no row in the jtable.
A basic example of what is happening, here I will rename both instance but in your code, model1 and model2 are named model.
model1 = new Model();
while(rs.next()){
model2 = new Model();
model2.addRow(...);
}
table.setModel(model1);
Quick correction, remove the declaration in the loop.
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
while(Rs.next()){
//DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
String name = Rs.getString("name");
String status = Rs.getString("status");
model.addRow(new Object[]{name,status });
}
jtable1.setModel(model);
Declare one TableModel
I would suggest you to make a separate two dimensional array and after retrieving data from Database save that data into that two dimensional array and after that you can assign that two dimensional array to the Jtable Model.
I can't reproduce exactly what you're trying to do, but I've tryed this:
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
model.addRow(new Object[]{"name1","status1" });
model.addRow(new Object[]{"name2","status2" });
model.addRow(new Object[]{"name3","status3" });
and the three rows are indeed added at the end of the table. Are you sure you have any data in your database table? could an exception being thrown?
UPDATE
I suspect that you have not defined the columns in the model:
UPDATE 2: Reset model before adding rows
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
int r = model.getRowCount();
while (r > 0) {
model.removeRow(--r);
}
ResultSet Rs = insert.executeQuery();
while(Rs.next()){
String name = Rs.getString("name");
String status = Rs.getString("status");
model.addRow(new Object[]{name,status });
}
I am having trouble showing my database filled JTable within my GUI application.
My code below runs through and creates a GUI with a panel, I then create my JTable and add it onto my application. I then run through a method that supposedly populates the table. After the populating has finished, nothing shows.
Dissecting my code, I'm led to believe somewhere is causing the data not to parse into my table, for some unknown reason, which is why I have come here.
At the click of a button, this code entails:
JTable tigerTable = new JTable();
JPanel centerPanel = new JPanel();
centerPanel.add(tigerTable, new GridBagConstraints());
FillTable(tigerTable, "SELECT * FROM TIGER_INFO");
The FillTable method as follows:
//Add buildTableModel method
public void FillTable(JTable table, String Query)
{
try
{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
Connection conn = DriverManager.getConnection("jdbc:derby:STOCK_CONTROL");
Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stat.executeQuery(Query);
System.out.println("Connected");
//Remove previously added rows
while (table.getRowCount() > 0)
{
((DefaultTableModel) table.getModel()).removeRow(0);
}
int columns = rs.getMetaData().getColumnCount();
while (rs.next())
{
Object[] row = new Object[columns];
for (int i = 1; i <= columns; i++)
{
row[i - 1] = rs.getObject(i);
}
((DefaultTableModel) table.getModel()).insertRow(rs.getRow() - 1, row);
}
rs.close();
stat.close();
conn.close();
}
catch (InstantiationException |
IllegalAccessException |
ClassNotFoundException |
SQLException e)
{
System.out.println(e);
e.printStackTrace();
}
}
Doing so creates the application, but does not show any table with data. My database contains 3 columns and 3 rows, but I do not see my data displayed inside a JTable.
My question is, how can I populate my JTable with my database and display it correctly on my GUI application?
If you need anything else, please let me know and I will provide as much as I can.
Thank you in advance.
I think you mix the operation, i suggest to use this instruction :
Create a Bean, or Entity to store the information of your Object
Get the List of your data,
Display your data in your JTable,
So you can use this to display your data in your JTable :
....
List<TIGER_INFO> list = new ArrayList<>();//create a List of data
while (rs.next()){
//fill data in your List
list.add(new TIGER_INFO(rs.getTYPExxx("att1"), rs.getTYPExxx("att2"), rs.getTYPExxx("att3"));
}
//when you finish call your function which display your data :
fillData(list);
....
Fill date method can look like this :
private void fillData(List<TIGER_INFO> list) {
DefaultTableModel model = (DefaultTableModel) jTableName.getModel();
while (model.getRowCount() > 0) {
for (int i = 0; i < model.getRowCount(); i++) {
model.removeRow(i);
}
}
for (TIGER_INFO obj : list) {
model.addRow(new Object[]{
obj.getAttribute1(),
obj.getAttribute2,
obj.getAttribute3
});
}
}
I recommend to write a class extending AbstractTableModel. Add a function to this class filling the content based on a SQL-Statement. Then it will look something like:
TigerTableModel tigerModel = new TigerTableModel(dbConnection);
tigerModel.executeQuery("select * FROM TIGER_INFO");
JTable tigerTable = new JTable(tigerModel);
or you create a generic TableModel that is able to run every SQL-statement, so you are very flexible in your project.
I have found the solution - I've been trying to wrap my head around the problem for way too long, and I finally fixed it.
Try setting the table model manually first.
JTable tigerTable = new JTable();
tigerTable.setModel(new DefaultTableModel(0, numberOfColumns));
When you don't specify a model, the JTable creates an anonymous inner class and generally doesn't behave how you want it to.
I have a JTable that retrieves information from a MySQL database table. The column headers are named just like how they are in the database.
Here is the code to create the JTable:
JScrollPane spBlockViewSchedule = new JScrollPane();
spBlockViewSchedule.setBounds(10, 285, 763, 185);
pnlBlockSched.add(spBlockViewSchedule);
tblBlockViewSchedule = new JTable();
spBlockViewSchedule.setViewportView(tblBlockViewSchedule);
Here is the code that populates the JTable:
private void populateTable(String sql, JTable table) {
try {
pst = DbConnection.conn.prepareStatement(sql);
rs = pst.executeQuery();
} catch(Exception ex) {
ex.printStackTrace();
}
table.setModel(DbUtils.resultSetToTableModel(rs));
}
How do I change the column names displayed in the JTable without changing the column names of the database table itself?
Create an empty DefaultTableModel with code like:
String[] columnNames = {"Course Code", "Subject Code", "Year Level", ...};
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
Then in the code where you read the data from the ResultSet you add the data to the TableMOdel using the addRow(....) method. Something like:
while (rs.next())
{
Vector row = new Vector();
for (int i = 1; i <= columns; i++)
{
row.addElement( rs.getObject(i) );
}
model.addRow( row );
}
Finaly you create the table using:
JTable table = new JTable( model );
Edit:
Since you are using 3rd party code you either need to change the way you add data to the model. I gave you basic code above. You can see the Table From Database Example source code from Table From Database for a complete example.
Or, you can modify the column headers after the table is created with code like:
table.getColumn("course_code").setHeaderValue("Course Code");
...
table.repaint();
Edit 2:
You can get the TableColumn from the TableColumnModel:
TableColumnModel tcm = table.getTableColumnModel();
tcm.getColumn(0).setHeaderValue("Course Code");
...
table.repaint();
I am currently facing the same problem as you did.
This line:
table.setModel(DbUtils.resultSetToTableModel(rs));
provided by r2xml.jar is pretty handy :)
I overcame the problem by setting alias to my sql SELECT statement.
For example,
SELECT
EngagementMethodID AS [ID],
EngagementMethodDescription AS [Engagement Method Description]
FROM [STUDENT].[EngagementMethod]
This will populate the column header as ID and Engagement Method Description as wanted.
Hope it helps.. Despite the age of this question? haha... Just sharing
try this
int colCount = 0;
ResultSetMetaData rsMetaData = null;
colCount = rsMetaData.getColumnCount();
for (int k = 1; k <= colCount; k++) {
{ String columnName = null;
columnName = rsMetaData.getColumnName(k);
System.out.println(columnName);
}
use this code simultaneously with your fetching code.
Each JTable has a TableModel. This TableModel defines the columns(Names and data types)
so find your table model and change it accordingly.
guys? help me with my problem. I want to have a one jtable that populates data using two table from database. i have two methods inside my class Apple..
Class Apple;
public void table(){
try{
String id = num.getText();
rs = stat.executeQuery("SELECT * FROM payments;");
Vector<String> header = new Vector<String>();
header.add("PAYMENT");
header.add("AMOUNT");
header.add("MODIFIER");
header.add("DATE MODIFIED");
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while(rs.next()) {
Vector<Object> row = new Vector<Object>();
row.add(rs.getString("description"));
row.add(rs.getString("amount"));
row.add(rs.getString("remarks"));
row.add(rs.getString("date"));
data.add(row);
} // loop
dtm.setDataVector(data , header);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setBounds(0,0,490,250);
panel.add(scrollPane);
validate();
}catch(Exception e){
System.out.println("Error in table: "+e);
}//try and catch
}//tble
that's the first method inside class Apple, and rs = stat.executeQuery("SELECT * FROM payments;"); is the first database table i want to retrieve the data and insert inside my jtable.. after it insert inside my jtable i have another method that will retrieve data from another database table..
public void table(){
try{
String id = num.getText();
rs = stat.executeQuery("SELECT * FROM record where idNum ='"+id+"';");
while(rs.next()){
Vector<Object> row = new Vector<Object>();
row.add(rs.getString("description"));
row.add(rs.getString("amount"));
row.add(rs.getString("remarks"));
row.add(rs.getString("date"));
data.add(row);
} // while
dtm.setDataVector(data , header);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setBounds(0,0,490,250);
panel.add(scrollPane);
validate();
}catch(Exception e){
System.out.println("Error in table: "+e);
}//try and catch
}//tble
this is the second methd inside the class apple.. i want its data to be added into my jtable and not deleting the previous data inserted inside the jtable..sorry for my poor english grammar..hope you understand what i mean..
Do join operation in single query between payments and record table and retrieve result on JTable.
He I am noob to Java (Thats not new) and I can't find a good tutorial for this. I use jTable to display a table filled with data from a MySQL database.
So far so good, I get the table:
Standard you can click a table cell and it changes to a text-field with can be filled with something new. You all know that, but how can I use this to also update the value in my database?
My code:
import [...];
public class table extends JPanel {
public String table;
private Database db;
public table(String tablename, Database db){
try {
table = tablename;
this.db = db;
//Get table with and height
ResultSet res = db.query("SELECT COUNT( * ) FROM `"+table+"`");
ResultSet res2 = db.query("SELECT COUNT( * ) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '"+table+"'");
int rows = 0;
int collums = 0;
res.next();
res2.next();
rows = res.getInt(1);
collums = res2.getInt(1);
//Get table column names and set then in array
ResultSet clom = db.query("DESCRIBE `"+table+"`");
String[] columnNames = new String[collums];
int s = 0;
while(clom.next()){
columnNames[s] = clom.getString(1);
s++;
}
//get table data and put in array
Object[][] data = new Object[rows][collums];
ResultSet result = db.query("SELECT * FROM `"+table+"`");
int q = 0;
while(result.next()){
for(int a=0; a<= (collums - 1); a++){
data[q][a] = result.getString(a + 1);
//System.out.println(q + " - " + a);
}
q++;
}
//Make Jtable of the db result form the two array's
final JTable table = new JTable(data, columnNames);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
// do some event listening for cell change
JScrollPane scrollPane = new JScrollPane(table);
JFrame frame = new JFrame("table editor");
scrollPane.setOpaque(true);
frame.setContentPane(scrollPane);
frame.pack();
frame.setSize(600, 800);
frame.setVisible(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
I guess I need to bind some kind of table listener and when something changes I take all the values of the table and update them with a query.
How can I do this?
This is my pseudo code:
table.bindCellEventListner(callback(t){
Array row = t.getAllValuesAsArrayOfRow();
String data = "";
int f = 0
while(row.next()){
data .= "`"+clom[f]+"` = '"+row[f]+"',"
f++;
}
data.delLastChar();
db.query("UPDATE `"+table+"` SET "+data+" WHERE `id` ="+row[0]+";");
});
A deleted answer plagiarised Rachel Swailes' answer from 14 years ago, found here. For completeness and because the answer is correct and useful, I have quoted the relevant text here:
Step 1: It's going to be way easier for the whole thing if you make your table extend a TableModel from now (if you haven't already). So if you need help with that just ask.
Step 2: In the table model you need to enable the cells to be editable. In the TableModel class that you make, you need to add these methods
public boolean isCellEditable(int row, int col) {
return true;
}
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = value;
fireTableCellUpdated(row, col);
}
Step 3: You will see in the second method that we fire a method called fireTableCellUpdated. So here we can catch what the use it changing. You need to add a TableModelListener to your table to catch this.
mytable.getModel().addTableModelListener(yourClass);
And in the class that you decide will implement the TableModelListener you need this
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel model = (TableModel)e.getSource();
Object data = model.getValueAt(row, column);
...
}
now you have the data in the cell and the place in the grid where the
cell is so you can use the data as you want