Hey there,
I built the following app;

A frame that with three sections inside it. Each section is actually a panel.

The first panel is a form I use for saving soccer matches on my database;

The second holds only one button that reads textfields from the form above and puts the content on the database table;

The third section/panel holds a JTable that shows the records on my database table matches.

I would like this table to be refreshed upon every time I click the button on the second section, but it is not doing so.

(My button works perfectly fine as far as putting records in the database goes. I also use it to reset to blank text fields in my form.)

I tried frame's update and repaint method, but they ain't worked. I also tried putting all these three panels on a bigger panel, which I then add on the frame, and calling the repaint method on this bigger panel, but that did not work either. Anyone please direct me to get this done.

Thank you.

Recommended Answers

All 25 Replies

@bibiki

my questions

1) what TableModel

2) how do you add/remove JTable contents,

3) by JButton_click you get data from database, where those ends,

4) are you using some Custom L&F

look for resultsettablemodel or better tablefromdatabase, then you'll never care about that, once defined, still works,

hey mKorbel,
how are you tonight?

This is my panel that constructs my JTable:

import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;

import javax.swing.*;
import javax.swing.table.JTableHeader;
//import java.awt.*;


public class MatchesTable extends JPanel{
	public MatchesDAO dao;//my Data Access Object
	public ArrayList<Match> matches;
	public Object[][] table;//rows
	public Object[] cols = {"Nr", "Nikoqiri", "Mysafiri", "Njish", "Barazim", "Dysh", "Fitues", "Befasi", "Data", "Liga"};
	public JTable tables;//this is my table including the header
	public MatchesTable()
	{
		dao = new MatchesDAO();
		matches = dao.getMatches();
		table = new Object[matches.size()][10];
		int i = 0;
		for(Match mat : matches)
		{
			for(int j = 0; j < 10; j++)
			{
				Object[] k = mat.toObjectArray();
				table[i][j] = k[j];
			}
			i++;
		}
		
		tables = new JTable(table, cols);
		//add(tables);
		JTableHeader header = tables.getTableHeader();
		header.setBackground(Color.GRAY);
		Dimension dim = new Dimension(5, 2);
		  tables.setIntercellSpacing(dim);
		add(new JScrollPane(tables));
	}
	
}

I tried constructing a new MatchesTable inside my frame's overridden update method, but it still did not work. Any ideas how to proceed?

this code nothing to do with OP's :-), another one ??? :-)

Hi bibiki.
What I'm not seeing here is any code to update the contents of the JTable when the database is updated. GUI methods like update or repaint won't achieve anything unless you change the data in the JTable first.

Hey James,

What I do is this:

I have a class that constructs my frame and add MatchesTable (the class above) onto another panel, which I add onto my Container in my frame. The way I do this is by reconstructing a

new MatchesTable()

and replacing the current one with it. I do this in my update method inside my frame, which I invoke every time a button is clicked. I expect this to work, it is not working. I tried removeAll() on the panel that actually holds my MatchesTable inside my update method, and it removed the contents of the panel that holds my MatchesTable, but I can't seem to add fresh content on this panel through update() method in the frame.

UPDATE:
Since I am actually declaring a new MatchesTable, the necessary steps for refreshing the contents of JTable are being processed. So, I don't think I need other steps for that. Or am I perhaps wrong?

Alright, this is how far I got:

After clicking my button, the panel that holds my button and my JTable disappears, only the form is left. When I resize the frame, it the panel reappears, and my table is updated.

This is my update method, which I invoke through the button that also inserts new matches in the database:

public void update()
	{
		
		table = new MatchesTable();//my matches table
		cc.removeAll();//cc is the panel that holds my button fub and my table
		
		cc.add(fub);
		cc.add(table);
		
		c.removeAll();//c is my container
		c.add(form, BorderLayout.NORTH);
		c.add(cc, BorderLayout.CENTER);
		
		c.repaint();
		repaint();
		System.out.println(s + " " + dao.countRecords());
	}

I hope this sounds like something you might have encountered earlier, and that you can direct me further.

what hells on the worlds is cc and c, forgot for all above that yu posted

job for 15 minutues

1) create JTable

2) create DefaultTableModel

3) add JTable to the JScrollPane

4) create all another JCOmponents

5) still everything above doesn't have any data

6) lay your JComponnents

7) set initial data, create new void for overrive default value for all JComponents (just in case, something sometimes things went wrong)

8) open conection to db

9) inside Resultset loop you have to always define new Vector

while {
Vector<Object> row = new Vector<Object>();
row.add(some_column_From_Resultset)

.
.
.
.
.
model.addRow(row)
}

10) before update value from db don'forget remove all rows from TableModel, and there you remove Rows from max number to 0 in the loop, otherwise you can get a few terrible errors

11) that is

hey mKorbel,

thank you for trying to help. Here is what c and cc are:

import javax.swing.*;

import java.awt.*;
import java.sql.Date;
import java.util.ArrayList;

public class MainFrame extends JFrame{
	public MatchesTable table;//custom JPanel, builds a JTable, populates it, and puts it on a panel
	public MatchesForm form;//custom JPanel, puts text fields and labels on a panel to build a form
	public FunctionButtons fub;//custom JPanel that holds a custom JButton that reads MatchesForm text fields, builds a String array, invokes a method for inserting data on database (data taken from form), refreshes the view (at least I want it to refresh it)
	public Container c;//getContentPane()
	public String s = "updated";//I use this string to see if update method's invocation from my button is taking place
	public MatchesDAO dao = new MatchesDAO();//My Data Access Object
	public JPanel cc = new JPanel(new GridLayout(2, 1));//for ease of design, I have two panels. One that holds form, and another that holds my button and my table. my button and table are added on this panel

	public MainFrame()
	{
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLayout(new BorderLayout());
		setTitle("Start");
		c = getContentPane();
		form = new MatchesForm();
		c.add(form, BorderLayout.NORTH);
		
		fub = new FunctionButtons(this);
		cc.add(fub);
		table = new MatchesTable();
		cc.add(table);
		c.add(cc, BorderLayout.CENTER);

		pack();
		
		setVisible(true);
	}
	
	public void update()
	{
		//removeAll();
		//c.add(form);
		table = new MatchesTable();
		cc.removeAll();
		//cc.setLayout(new GridLayout(2, 1));
		cc.add(fub);
		cc.add(table);
		cc.repaint();
		c.removeAll();
		c.add(form, BorderLayout.NORTH);
		c.add(cc, BorderLayout.CENTER);
		
		c.repaint();
		repaint();
		System.out.println(s + " " + dao.countRecords());
	}
	
	public static void main(String[] args)
	{
		new MainFrame();
	}
}

Hey friends,
I just wanted to let you know that I solved my problem. I added an invocation of validate() method, and everything works now. I'll mark this thread as solved, as I actually reached the effect I wanted, but I remain puzzled still. Maybe you guys have an answer for me: I tried invoking the frames validate method and it worked just as well as calling container's validate method? What does this mean. Perhaps, frames validate method invokes container's validate method or what?

anyways, I thank you guys for your patience.

don't recreate whole GUI, why????, and if required

revalidate();
repaint();

as this way I expecting to refresh JTable's body

hehehe
No mKorbel, I did not recreate the whole GUI. I have already designed my little app, and it will be too much to go back and redo my plan. Besides, I need something tangible (as tangible as software gets) to see for my work to keep myself motivated. :)

anyways, thank you again.

I believe he was referring to the removing and recreating all of your components each time instead of merely updating the data they contain. Update the data in your table model. You don't have to throw everything away.

Ooooo, ok. Thank you Ezzaral.I guess because you both are more experienced you guys understand each other better. I see how I'd do that in my current classes. Thank you!

Hey there,
I know I have marked this thread as solved but I just can't give up on this.

In attempt to more closely follow mKorbel's advice, and after borrowing some code from a short book, I built these two classes: a frame and a button:

import javax.swing.*;
import javax.swing.table.*;

import java.awt.*;

import org.w3c.dom.views.AbstractView;


public class TableFrame extends JFrame{
	public int in = 6;
	Object[][] data = new Object[in][4];//I intend to increment in variable through a button so that I can increase 
	//number of rows in my table and see table refreshing
	JTable table;
	String[] headers = {"One", "Two", "Three", "Four"};//columns
	AbstractTableModel model;
	JScrollPane scrollPane;
	
	public TableFrame()
	{
		setLayout(new GridLayout(2, 1));
		setBounds(50,50,320,400);
		setVisible(true);
		data = buildData();
		
		// make table model with this data..
		model = new MyTable(headers, data);
		table = new JTable(model);
		scrollPane = new JScrollPane(table);
		table.setFillsViewportHeight(true);
		add(scrollPane);
		scrollPane.setBounds(5,5,300,300);
		
		add(new RefreshingButon(this));
	}
	
	public Object[][] buildData()
	{
		Object[][] rez = new Object[in][10];
		
		for (int i=0; i<in; i++)
			for (int j=0; j<10; j++)
			rez[i][j]=i*j;
		
		return rez;
	}
	
	public void increase()
	{
		in++;
		data = buildData();
		model.fireTableDataChanged();
		//validate();
		System.out.println(in);
	}
	
	class MyTable extends AbstractTableModel
	{
		String[] headers;
		Object[][] data;
		
		MyTable(String[] headers, Object[][] data)
		{
			super();
			this.headers=headers;
			this.data=data;
		}
		public int getColumnCount() {
		return headers.length;
		}
		public int getRowCount() {
		return data.length;
		}
		public String getColumnName(int col) {
		return headers[col];
		}
		public Object getValueAt(int row, int col) {
		return data[row][col];
		}
		public Class<?> getColumnClass(int c) {
		return data[0][c].getClass();
		}
		public boolean isCellEditable(int row, int col) {
		return true;
		}
	}
	
	public static void main(String[] args)
	{
		new TableFrame();
	}
}
-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;


public class RefreshingButon extends JButton implements ActionListener{
	public TableFrame frame;
	public RefreshingButon(TableFrame f)
	{
		frame = f;
		addActionListener(this);
	}

	public void actionPerformed(ActionEvent e)
	{
		frame.increase();
	}
}

What I am trying to do is to have a simple multiplication table with six rows when I first launch the app, and a button beneath it. Then, every time a click the button, I expect a new row to be added and showed on the frame. It is not working. Can you please give me some insight on what is going on?

You are updating your local 'data' array in the frame - not the one in your table model.

1) main method must be wrapped into invokeLater()

2) I can see reason for usage AbstractTableModel there, there no reason to restrict something

3) don't call fireXxxXxx outside AbstractTableModel, aren't (never) you get arrayindex exeption, not never do that

4) don't call super inside AbstractTableModel,

5) don't create/recreate JTable inside Model,

6) there is lots of LayoutManagers, why setBound(), that childish

7) why you extract ActionListener to the separated void, clas, whatever, use javax.swing.Action instead

Thank you Ezzaral.

I replaced my 50th row with data.model = buildData() as well as line 15 to MyTable model, and it now works. However, I am wondering, is this what mKorbel meant or is there perhaps some better, different way to reach this effect?

mKorbel already mentioned a few changes above. If you don't understand some of them, just ask for some clarification.

Personally I would also move the methods that build or update your model data into the model class itself and expose a method like addRow() for your GUI to call when the button is clicked.

hey mKorbel,
I was writing my last reply when you wrote your last reply. please accept my apology.

I understand if this is too much and you refuse, but I would greatly appreciate it if you would rewrite my code in accordance with your advice above so that I can see more clearly how to do this.

thank you for all your help.

Well Ezzaral,I don'tunderstand parts 1, 3 and 5.

Alright, maybe this will clarify a bit:

1) main method must be wrapped into invokeLater()

For concurrency reasons, GUIs should be created on the event dispatch thread. In your main method, you should create your GUI instance in a small Runnable that can be executed on the dispatch thread

javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TableFrame();
            }
        });

3) don't call fireXxxXxx outside AbstractTableModel

Your model should fire those events itself as needed when the data changes.

5) don't create/recreate JTable inside Model,

I don't see where your latest code is doing this, so I'm not sure why that was mentioned.

1)

public static void main(String[] args){
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
         new TableFrame();
      }
    });
  }

add 3)

fireXxxXxx methods must be inside AbstractTableModel, btw your model is 'useless', because there isn't methods addRow, removeRow, setValueAt .... and inside this methods must be fireXxxXxx()


add 5)

class MyTable extends AbstractTableModel
{
String[] headers;
Object[][] data;
 
MyTable(String[] headers, Object[][] data)
{
super();
this.headers=headers;
this.data=data;
}....

move these codelines out of AbstractTableModel, because is not confortable update something inside inner class,

that for your confort not about my ego here, otherwise you'll wrote 1Mio codelines for override basic methods

just joke where is there TableModel

Hey mKorbel,
thank you for your explanations. I guess there is no table model for your TableWithTimer example. It is using a DefaultTableModel, I believe.

So, if I want to call fireXXXX methods, I should do them inside other methods of TableModel as in, for example:

public void  addRow(){
             //some code that adds row
             fireXXXXX();
}

is that right? So, basically: with a button, I invoke addRow, which then invokes fireXXX, right?

One more thing. One my actual app, I have data on an SQLite database. For populating my table, I usually retrieve all lines. I guess I should specify in my button to only add the last row when a row is inserted in db, also done through the same button...

1) some method overrode in AbstractTableModel

2) better would be serch for TableFromDatabase or ResultsetTableModel, there are overrode required blablabla for connection, take data from db_table and tablemodel too, then you never will be care about these three areas

alright mKorbel,
thank you very much. In case I have other questions, I will start a new thread. This got quite long already. See you around.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.