Every time I implement a database viewer I have some functions that populate the table and adjust the column size. I would like to find ready component that can view the query result, also to sort, edit the entries in the table and automaticaly adjust the size of the column with respect to data. I want to use metadata to define the type of the entities automaticaly. The only thing that I will pass will be the ResultSet of the query and the component will do the rest. Any idea?
What I have done so far:
private static DefaultTableModel buildTableModel(ResultSet rs) throws SQLException {
ResultSetMetaData metaData = rs.getMetaData();
// names of columns
Vector<String> columnNames = new Vector<String>();
int columnCount = metaData.getColumnCount();
for (int column = 1; column <= columnCount; column++) {
columnNames.add(metaData.getColumnName(column));
}
// data of the table
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while (rs.next()) {
Vector<Object> vector = new Vector<Object>();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
vector.add(rs.getObject(columnIndex));
}
data.add(vector);
}
return new DefaultTableModel(data, columnNames);
}
public static void showResult(ResultSet rs) throws SQLException{
//creates the table
JTable table = new JTable(buildTableModel(rs));
table.setEnabled(false);
//abjust table size
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumnAdjuster tca = new TableColumnAdjuster(table);//the class for adjusting the column size
tca.adjustColumns();
//JFrame
JFrame view = new JFrame("View");
view.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//add to frame
JScrollPane pane = new JScrollPane(table);
view.add(pane);
//settings
view.setVisible(true);
view.setSize(table.getWidth(), 400);
}
And also I have a class that adjust the column size.
To sort records use order by Clause to query you fire to get all records.
Use TableColumnModel to set column size.
Here is the code
//Your Edit Code
rs=st.executeQuery("select * from ManageVendor order by SName");
table.setModel(buildTableModel(rs));
TableColumnModel tcm=table.getColumnModel();
tcm.getColumn(0).setPreferredWidth(50);
tcm.getColumn(1).setPreferredWidth(200);
tcm.getColumn(2).setPreferredWidth(150);
tcm.getColumn(3).setPreferredWidth(60);
tcm.getColumn(4).setPreferredWidth(50);
tcm.getColumn(5).setPreferredWidth(250);
Related
I'm trying to figure out how to make a table window update once the model has changed using an example from another site. Everything works but I can't figure how to refresh the window once the table model has changed.
EDIT: I used the suggestion from Bell and re-arranged some things so that the constructor calls my getmodel3 method to populate the table. I thought I could use the setmodel method to change the model and update the table but it isn't working as I thought. Here's what I thought would, but doesn't happen:
The main method creates a new instance of the table using the model passed from the getmodel3 method.
After the table is constructed I call the setmodel method to load different data into a new model using the returned model from getmodel4.
The instance from step 1 is updated with new model data and the new data is shown in the table.
What actually happens is, a new instance is created and uses the model returned from getmodel3, then the setmodel method runs and updates the model variable from a different set of data, but the table doesn't show the change.
public class myTable extends JFrame
{
public volatile DefaultTableModel model = (DefaultTableModel) myTable.getmodel3();
public void setmodel(DefaultTableModel newModel)
{
this.model = newModel;
}
public myTable()
{
JTable table = new JTable( model );
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
JPanel buttonPanel = new JPanel();
getContentPane().add( buttonPanel, BorderLayout.SOUTH );
}
public static void main(String[] args)
{
myTable frame = new myTable();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
frame.setmodel(getmodel4());
}
Here is getmodel3 which is identical to getmodel4 except they point to different database files for different data.
public static DefaultTableModel getmodel3(){
Vector<Object> columnNames = new Vector<Object>();
Vector<Object> data = new Vector<Object>();
try
{
// Connect to an Access Database
String url = "jdbc:sqlite:c:\\sqlite3\\test.db";
Connection conn = DriverManager.getConnection(url);
// Read data from a table
String sql = "Select * from Tasks";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery( sql );
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
// Get column names
for (int i = 1; i <= columns; i++)
{
columnNames.addElement( md.getColumnName(i) );
}
// Get row data
while (rs.next())
{
Vector<Object> row = new Vector<Object>(columns);
for (int i = 1; i <= columns; i++)
{
row.addElement( rs.getObject(i) );
}
data.addElement( row );
}
rs.close();
stmt.close();
conn.close();
}
catch(Exception e)
{
System.out.println( e );
}
// Create table with database data
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
#Override
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
{
return o.getClass();
}
}
return Object.class;
}
};
System.out.println("got model");
return model;
}
You can use existing model by using table.getModel() and set new/existing model using table.setModel(yourModel)
DefaultTableModel model = (DefaultTableModel) table.getModel();
// do modification here
table.setModel(model);
Well, with some of your help I finally figured it out. setModel wasn't working because 1, it wasn't accessible from the scope of the method where I tried to use it, and 2 I tried to make my own setter setmodel but I had no idea what I was doing :).
In the end, I initialized in an easier to reach place so I didn't mess with objects in other methods. Here is the working result that loads a table when main is called and later I can call the update method to reload it. Thanks for the help folks.
public class able extends JFrame
{
//initialize here for easy access. getmodel3() is the model getter method and
//returns the defaultTableModel object
private static able frame = new able();
private static JTable table = new JTable( getmodel3() );
//Start all main stuff here using the previously initialized objects.
public static void main(String[] args)
{
JScrollPane scrollPane = new JScrollPane( table );
frame.getContentPane().add( scrollPane );
JPanel buttonPanel = new JPanel();
frame.getContentPane().add( buttonPanel, BorderLayout.SOUTH );
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
public static void update()
{
table.setModel(getmodel3());
}
//This method makes the table model from sql result set and returns it.
//(found online somewhere thanks to whoever wrote it)
public static DefaultTableModel getmodel3(){
Vector<Object> columnNames = new Vector<Object>();
Vector<Object> data = new Vector<Object>();
try
{
// Connect to an Access Database
String url = "jdbc:sqlite:c:\\sqlite3\\test.db";
Connection conn = DriverManager.getConnection(url);
// Read data from a table
String sql = "Select * from Tasks";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery( sql );
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
// Get column names
for (int i = 1; i <= columns; i++)
{
columnNames.addElement( md.getColumnName(i) );
}
// Get row data
while (rs.next())
{
Vector<Object> row = new Vector<Object>(columns);
for (int i = 1; i <= columns; i++)
{
row.addElement( rs.getObject(i) );
}
data.addElement( row );
}
rs.close();
stmt.close();
conn.close();
}
catch(Exception e)
{
System.out.println( e );
}
// Create table with database data
DefaultTableModel model3 = new DefaultTableModel(data, columnNames)
{
#Override
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
{
return o.getClass();
}
}
return Object.class;
}
};
System.out.println("got model");
return model3;
}
public static DefaultTableModel getmodel4(){
Vector<Object> columnNames = new Vector<Object>();
Vector<Object> data = new Vector<Object>();
try
{
// Connect to an Access Database
String url = "jdbc:sqlite:c:\\sqlite3\\test2.db";
Connection conn = DriverManager.getConnection(url);
// Read data from a table
String sql = "Select * from Tasks";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery( sql );
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
// Get column names
for (int i = 1; i <= columns; i++)
{
columnNames.addElement( md.getColumnName(i) );
}
// Get row data
while (rs.next())
{
Vector<Object> row = new Vector<Object>(columns);
for (int i = 1; i <= columns; i++)
{
row.addElement( rs.getObject(i) );
}
data.addElement( row );
}
rs.close();
stmt.close();
conn.close();
}
catch(Exception e)
{
System.out.println( e );
}
// Create table with database data
DefaultTableModel model3 = new DefaultTableModel(data, columnNames)
{
#Override
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
{
return o.getClass();
}
}
return Object.class;
}
};
System.out.println("got model");
return model3;
}
}
public void populateJTable() {
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
Object[] rowData = new Object[4];
TrackService ts = new TrackService();
ArrayList<Track> tracks = ts.jsonToTracks();
for (int i = 0; i < tracks.size(); i++) {
rowData[0] = tracks.get(i).getTrackName();
rowData[1] = tracks.get(i).getArtist();
model.addRow(rowData);
}
jTable1 = new JTable(model);
}
In my json file I have stored metadata of an mp3 file which stores 5 values. My 'jsonToTracks' method stores them in an ArrayList.
I'm trying to get 2 of the values (trackName and artist) from inside my ArrayList and display them in my JTable.
My JTable has 4 columns - Name, Artist, Key, Mood. I'm trying to store the trackName and Artist in their corresponding columns. The Key and Mood column should be blank and the Name and Artist fields should be populated.
I can't see what I'm doing wrong, can anyone help?
Maybe you should try, moving your rowData initialization inside for loop.
public void populateJTable() {
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
TrackService ts = new TrackService();
ArrayList<Track> tracks = ts.jsonToTracks();
for (int i = 0; i < tracks.size(); i++) {
Object[] rowData = new Object[4];
rowData[0] = tracks.get(i).getTrackName();
rowData[1] = tracks.get(i).getArtist();
model.addRow(rowData);
}
jTable1 = new JTable(model);
}
jTable1 = new JTable(model);
I suspect the problem is that you are creating a new JTable but you never add the table to the frame.
Instead you should use:
jTable1.setModel( model );
This will replace the data in the existing JTable was I assume you have already added to a JScrollpane that has been added to the frame.
I'm showing the method were the JTable is constructed, the error is when adding the rows inside the for (int i = 1; i <= numero_columnas; i++) loop, or the way the DefaultTableModel model = new DefaultTableModel(); is declared, I can't find the error.
public void verTablaTable (Connection db, String nombre) throws Exception{
Statement stmt=db.createStatement();
ResultSet sst_ResultSet = stmt.executeQuery("SELECT * FROM "+nombre);
ResultSetMetaData md = sst_ResultSet.getMetaData();
int numero_columnas = md.getColumnCount();
DefaultTableModel model = new DefaultTableModel();
for (int i=1;i<=numero_columnas; i++){
model.addColumn(md.getColumnName(i));
}
JTable tabla =new JTable(model);
DefaultTableModel model1 = (DefaultTableModel) tabla.getModel();
Vector row = new Vector();
row.setSize(numero_columnas);
while (sst_ResultSet.next()){
for (int i = 1; i <= numero_columnas; i++){
row.set(i-1,sst_ResultSet.getString(i));
}
model1.addRow(row);
}
tabla.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane sp_vertabla = new JScrollPane(tabla);
sp_vertabla.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
sp_vertabla.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
sp_vertabla.setBounds(50,30,700,500);
JPanel cont_vertabla = new JPanel(null);
cont_vertabla.setPreferredSize(new Dimension(750,600));
cont_vertabla.add(sp_vertabla);
f_vertabla.setContentPane(cont_vertabla);
f_vertabla.pack();
f_vertabla.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//f_vertabla.setResizable(false);
f_vertabla.setVisible(true);
f_vertabla.addWindowListener(this);
}
this is the way the JTable looks
The row listed in the above pic, is the last one in the mysql table
Try adding the line
Vector row = new Vector();
inside the while loop.
is there any way to retrieve database rows using component other than jTable where unique jButtons for each row can added and made to perform specific task?
Currently I'm using the following code... jTable appears in a dialog box
public static DefaultTableModel buildTableModel(ResultSet rs)
throws SQLException {
ResultSetMetaData metaData = rs.getMetaData();
// names of columns
Vector<String> columnNames = new Vector<String>();
int columnCount = metaData.getColumnCount();
System.out.println("7");
for (int column = 1; column <= columnCount; column++) {
columnNames.add(metaData.getColumnName(column));
}
// data of the table
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while (rs.next()) {
Vector<Object> vector = new Vector<Object>();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
vector.add(rs.getObject(columnIndex));
}
data.add(vector);
}
return new DefaultTableModel(data, columnNames);
}
public void searchb2() throws SQLException {
this.be_cgpa = be_cg.getText();
this.maj_proj = Major.getText();
this.h_percent = hss_percent.getText();
this.s_percent = sss_percent1.getText();
preparedStatement = con.prepareStatement("select name,age,gender,email_id,phone_num,state from resume1 where qualification='be' and be_cgpa>='" + be_cgpa + "'" + "and maj_proj_tech='" + maj_proj + "'" + "and hss_percent>='" + h_percent + "'" + "and sss_percent='" + s_percent + "'");
ResultSet rs;
rs = preparedStatement.executeQuery();
JTable table = new JTable(buildTableModel(rs));
JOptionPane.showMessageDialog(null, new JScrollPane(table));
}
Can this code be modified to add jButton in each row?
There is no reason you can't use JTable and add a column containing buttons to the table.
See Table Button Column for one way to do this. This class expects you to provide an Action that is invoked when the button is clicked. All you need to do is add another String of text to the "vector" after you have finished looping through the column data.
Also, use a PreparedStatement for your SQL. It is easier to code and understand and less error prone than your current code.
table button column is definitely the best way of achieving particular cell's value on clicking the corresponding button but seems to be 1 of the hardest thing in jtable.
another approach for implementing the above is enabling cell selection and using list selection model and list selection listener.
On clicking any cell you can get cell's data in a variable.
you can even fix a column and make an ordinary column with text as "button i" where i=row number. and on clicking this cell, you'll get only particular column's data of corresponding row and can even open a new frame or dialog box depending on your coding, this will make it work like a jbutton! (Actually due to fixed column, clicking any cell in that row will perform that task with column number same as fixed column)
Here is a sample code :
final JTable table;
table = new JTable(data, columnNames)
{
public boolean isCellEditable(int rowIndex, int colIndex) {
return false; //Disallow the editing of any cell
}
};
table.setCellSelectionEnabled(true);
ListSelectionModel cellSelectionModel = table.getSelectionModel();
cellSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cellSelectionModel.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
int[] selectedRow = table.getSelectedRows();
for (int i = 0; i < selectedRow.length; i++) {
selectedData = (String) table.getValueAt(selectedRow[i],2);
}
new NewJFrame().setVisible(true);
System.out.println("Selected: " + selectedData);
}
Hi I have problems with populating a TableModel, I cannot understand what the problem is
here is my method
private TableModel buildTableModel(List<Player> result) {
// build the columns
Vector<String> columnNames = new Vector<String>();
//int columnCount = metaData.getColumnCount();
//for (int column = 1; column <= columnCount; column++) {
// columnNames.add(metaData.getColumnName(column));
//}
columnNames.add("playerid");
columnNames.add("squeezePlay");
columnNames.add("weakShowdown");
columnNames.add("numberOfPlays");
columnNames.add("playsWithFriends");
columnNames.add("suspend");
columnNames.add("grade");
// data of the table
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while (result.iterator().hasNext()) {
Player player = result.iterator().next();
Vector<Object> vector = new Vector<Object>();
vector.add((Object) player.GetId());
vector.add((Object) player.GetSqueezePlay());
vector.add((Object) player.GetWeakShowdown());
vector.add((Object) player.GetNumberOfPlays());
vector.add((Object) player.GetPlaysWithFriends());
vector.add((Object) player.GetSuspended());
vector.add((Object) player.GetGrade());
data.add(vector);
}
return new DefaultTableModel(data, columnNames);
}
Note: with or without the Object casting, the table still doesn't work..
Please suggest any alternative solution to populate a TableModel.
Thanks!!
Every time you call result.iterator() you are reading the beginning of your List. Instead, use this:
for (Player player : result)