I've made a GUI in Java that connects with a MySQL server and inserts,deletes,updates data. I have a section on this GUI that you can write in a text area a MySQL query and the result is displayed on a Jtable. Everything works fine! I can print the data from the JTable or save them to a text file!
Now, I want to add another feature: When I double click on a specific cell, I would like to change the data of the JTable, and I want this data to be updated in the MySQL table with the click of a button as well.
I've searched all over the internet, but I can't find a good example or a good solution. The JTable I have is dynamic; that means that what ever query is inserted the data will be displayed with the quired column names and data
Here is the code:
ArrayList columnNames = new ArrayList();
ArrayList data = new ArrayList();
data_connector getdata1 = new data_connector();
host = getdata1.getHost();
username = getdata1.getUsername();
password1 = getdata1.getPassword();
mysql_command = getdata1.getMysql_command();
command_name = getdata1.getCommand_name();
setTitle(command_name);
// Connect to an MySQL Database, run query, get result set
String url = "jdbc:mysql://"+host+":3306/xxxxx";
String userid = username;
String password = password1;
String sql = mysql_command;
// Java SE 7 has try-with-resources
// This will ensure that the sql objects are closed when the program
// is finished with them
try (Connection connection = DriverManager.getConnection( url, userid, password );
Statement stmt = connection.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.add(md.getColumnName(i));
// Get row data
while (rs.next())
{
ArrayList row = new ArrayList(columns);
for (int i = 1; i <= columns; i++)
row.add(rs.getObject(i));
data.add(row);
}
}
catch (SQLException e)
{
System.out.println(e.getMessage());
JOptionPane.showMessageDialog(null, e.getMessage());
mysql_fail_flag = 1;
}
// Create Vectors and copy over elements from ArrayLists to them
// Vector is deprecated but I am using them in this example to keep
// things simple - the best practice would be to create a custom defined
// class which inherits from the AbstractTableModel class
Vector columnNamesVector = new Vector();
Vector dataVector = new Vector();
for (int i = 0; i < data.size(); i++)
{
ArrayList subArray = (ArrayList)data.get(i);
Vector subVector = new Vector();
for (int j = 0; j < subArray.size(); j++)
subVector.add(subArray.get(j));
dataVector.add(subVector);
}
for (int i = 0; i < columnNames.size(); i++ )
columnNamesVector.add(columnNames.get(i));
contentPane.setLayout(null);
// Create table with database data
table = new JTable(dataVector, columnNamesVector)
{
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;
}
};
// table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(5, 5, xframeWidth-20, yframeHeight-70);
getContentPane().add(scrollPane);
JPanel buttonPanel = new JPanel();
buttonPanel.setBounds(5, 856, 1574, 1);
getContentPane().add(buttonPanel);
buttonPanel.setLayout(null);
In the form you actually create your JTable, I don't think this is easy. What you want to do is subclassing AbstractTableModel, and overwrite the setValueAt() method. You subclass could look like this:
class MyModel extends AbstractTableModel
{
private ResultSet result;
private ResultSetMetaData metadata;
public MyModel (ResultSet rs)
{
super();
result = rs; // mustn't be null, maybe check and throw NPE
metadata = result.getMetaData();
}
public int getRowCount ()
{
result.last();
return result.getRow(); // See http://stackoverflow.com/questions/8292256/get-number-of-rows-returned-by-resultset-in-java
}
public int getColumnCount ()
{
return metadata.getColumnCount();
}
public Object getValueAt (int row, int col)
{
result.absolute(row);
return result.getString(col);
}
public String getColumnName (int col)
{
return metadata.getColumnName(col);
}
public void setValueAt (Object value, int row, int col)
{
result.absolute(row);
result.updateObject(col, value);
}
}
I haven't tested it, but your code must look like this. Note that you mustn't close the Statement, Connection or the ResultSet (or create a new ResultSet cause some db drivers like MySQL destroy the old one) to prevent any Exceptions.
OK!!! i managed to update every cell separately by just editing the cell and then pressing enter!
This works only for 1 table but its ok for my project! Here is the code...
private class RowColumnListSelectionListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
rowIndexStart = table.getSelectedRow();
rowIndexEnd = table.getSelectionModel().getMaxSelectionIndex();
colIndexStart = table.getSelectedColumn();
colIndexEnd = table.getColumnModel().getSelectionModel().getMaxSelectionIndex();
for ( i = rowIndexStart; i <= rowIndexEnd; i++) {
for ( j = colIndexStart; j <= colIndexEnd; j++) {
Object cell_value = table.getValueAt(i,j);
Cell_value_string_before = (String) cell_value;
}
}
}
}
public test_table() {
setIconImage(Toolkit.getDefaultToolkit().getImage(test_table.class.getResource("/com/sun/java/swing/plaf/windows/icons/Computer.gif")));
//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//setBounds(100, 100, 688, 589);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
xframeWidth = screenSize.width; //dynamic size for frame x-axes
yframeHeight = screenSize.height; //dynamic size for frame y-axes
int xlocation = xframeWidth*2; //dynamic location x-axes
int ylocation = yframeHeight*2; //dynamic location y-axes
setBounds(0,0, xframeWidth, yframeHeight);
setResizable(false);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu mnNewMenu = new JMenu("Αρχείο");
menuBar.add(mnNewMenu);
JMenuItem mntmNewMenuItem_1 = new JMenuItem("Εξαγωγή σε .txt αρχείο");
mntmNewMenuItem_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser =new JFileChooser();
fileChooser.setDialogTitle("Δημιουργία αρχείου .txt");
FileNameExtensionFilter filter = new FileNameExtensionFilter(".txt", "text");
fileChooser.setFileFilter(filter);
int returnVal = fileChooser.showSaveDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
try {
File file = fileChooser.getSelectedFile();
File newfile = new File(file.getPath()+".txt");
// PrintWriter os = new PrintWriter(file);
FileWriter fw = new FileWriter(newfile,true); //filewriter
BufferedWriter bw = new BufferedWriter(fw); //buffered writer
PrintWriter os = new PrintWriter(bw, true);
os.print("");
for (int col = 0; col < table.getColumnCount(); col++) {
os.print(table.getColumnName(col) + "\t");
os.print(";");
}
os.println("");
os.println("");
for (int row = 0; row < table.getRowCount(); row++) {
for (int col = 0; col < table.getColumnCount(); col++) {
//os.print(table.getColumnName(col) + "\t");
// os.print(": ");
os.print(table.getValueAt(row, col) + "\t");
os.print(";");
// os.print(table.getRowCount() + "\t");
}
os.println("");
}
os.close();
System.out.println("Done!");
}
catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
mnNewMenu.add(mntmNewMenuItem_1);
JMenuItem mntmNewMenuItem_2 = new JMenuItem("Εκτύπωση");
mntmNewMenuItem_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
if (! table.print()) {
System.err.println("User cancelled printing");
}
} catch (java.awt.print.PrinterException e1) {
System.err.format("Cannot print %s%n", e1.getMessage());
}
}
});
mnNewMenu.add(mntmNewMenuItem_2);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
ArrayList columnNames = new ArrayList();
ArrayList data = new ArrayList();
// data_connector getdata1 = new data_connector();
// host = getdata1.getHost();
// username = getdata1.getUsername();
// password1 = getdata1.getPassword();
// mysql_command = getdata1.getMysql_command();
// command_name = getdata1.getCommand_name();
//setTitle(command_name);
// Connect to an MySQL Database, run query, get result set
String url = "jdbc:mysql://localhost:3306/υπαλληλοι απε-μπε";
String userid = "ziorange";
String password = "120736";
String sql = "SELECT * FROM `ΥΠΑΛΛΗΛΟΙ 2 test`";
//String sql = "SELECT `ΚΩΔΙΚΟΣ`,`ΕΠΩΝΥΜΟ`,`ΟΝΟΜΑ`,`ΟΝΟΜΑ ΠΑΤΡΟΣ`,`ΑΜΚΑ`,`ΑΡΙΘΜΟΣ ΜΗΤΡΩΟΥ ΙΚΑ (αν υπάρχει)` FROM `ΥΠΑΛΛΗΛΟΙ 2` WHERE `ΚΩΔΙΚΟΣ`>'0' AND `ΗΜΕΡΟΜΗΝΙΑ ΑΠΟΧΩΡΗΣΗΣ`>'2009-12-31 00:00:00' OR `ΕΙΔΙΚΟΤΗΤΑ` !='ΑΝΤΑΠΟΚΡΙΤΗΣ ΕΞ' AND `ΛΟΓΟΣ ΑΠΟΧΩΡΗΣΗΣ`='-' ORDER BY `ΕΠΩΝΥΜΟ`";
// Java SE 7 has try-with-resources
// This will ensure that the sql objects are closed when the program
// is finished with them
try
{
connection = DriverManager.getConnection( url, userid, password );
Statement stmt = connection.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.add( md.getColumnName(i) );
}
// Get row data
while (rs.next())
{
ArrayList row = new ArrayList(columns);
for (int i = 1; i <= columns; i++)
{
row.add( rs.getObject(i) );
}
data.add( row );
}
}
catch (SQLException e)
{
//
System.out.println( e.getMessage() );
JOptionPane.showMessageDialog(null, e.getMessage() );
mysql_fail_flag=1;
}
// Create Vectors and copy over elements from ArrayLists to them
// Vector is deprecated but I am using them in this example to keep
// things simple - the best practice would be to create a custom defined
// class which inherits from the AbstractTableModel class
Vector columnNamesVector = new Vector();
Vector dataVector = new Vector();
for (int i = 0; i < data.size(); i++)
{
ArrayList subArray = (ArrayList)data.get(i);
Vector subVector = new Vector();
for (int j = 0; j < subArray.size(); j++)
{
subVector.add(subArray.get(j));
}
dataVector.add(subVector);
}
for (int i = 0; i < columnNames.size(); i++ )
columnNamesVector.add(columnNames.get(i));
contentPane.setLayout(null);
// Create table with database data
table = new JTable(dataVector, columnNamesVector)
{
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;
}
};
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setColumnSelectionAllowed(true); //epilegei to kathe keli ksexwrista
table.getSelectionModel().addListSelectionListener(
new RowColumnListSelectionListener());
table.getDefaultEditor(String.class).addCellEditorListener(
new CellEditorListener() {
public void editingCanceled(ChangeEvent e) {
System.out.println("editingCanceled");
}
public void editingStopped(ChangeEvent e) {
System.out.println("editingStopped: apply additional action");
rowIndexStart = table.getSelectedRow();
rowIndexEnd = table.getSelectionModel().getMaxSelectionIndex();
colIndexStart = table.getSelectedColumn();
colIndexEnd = table.getColumnModel().getSelectionModel().getMaxSelectionIndex();
for ( i = rowIndexStart; i <= rowIndexEnd; i++) {
for ( j = colIndexStart; j <= colIndexEnd; j++) {
Object cell_value = table.getValueAt(i,j);
Cell_value_string_after = (String) cell_value;
ia=i+1;
ja=j+1;
column_name_selected2 = table.getColumnName(ja-1);
}
}
if(Cell_value_string_before.equals(Cell_value_string_after)){
System.out.println("Do nothing");
}
else{
System.out.println("UPDATE DATABASE");
update_database();
}
}
});
JScrollPane scrollPane = new JScrollPane( table );
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(5, 5, xframeWidth-20, yframeHeight-70);
getContentPane().add( scrollPane );
JPanel buttonPanel = new JPanel();
buttonPanel.setBounds(5, 856, 1574, 1);
getContentPane().add( buttonPanel );
buttonPanel.setLayout(null);
}
public void update_database(){
Object get_lastname = table.getValueAt(ia-1, 5);
String get_lastname_string = (String) get_lastname;
Object get_name = table.getValueAt(ia-1, 6);
String get_name_string=(String) get_name;
System.out.println("RESULT= "+ column_name_selected2 + " - "+Cell_value_string_after+ " - " + get_lastname_string+ " - " + get_name_string );
if(column_name_selected2.equals("ΕΠΩΝΥΜΟ") || column_name_selected2.equals("ΟΝΟΜΑ")){
JOptionPane.showMessageDialog(null, "To επώνυμο και το όνομα δεν μπορεί να αλλάξει","Μήνυμα:",JOptionPane.WARNING_MESSAGE);
}
else{
try {
PreparedStatement update = (PreparedStatement) connection.prepareStatement
("UPDATE `ΥΠΑΛΛΗΛΟΙ 2 TEST` SET `" +column_name_selected2+"` = ? WHERE ΕΠΩΝΥΜΟ= ? AND ΟΝΟΜΑ =? ");
update.setString(1,Cell_value_string_after);
update.setString(2,get_lastname_string);
update.setString(3,get_name_string);
int all_edit_query_status=update.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
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;
}
}
I need to change the column's names in the JTable. Now names are automatically taken from the database. I want to change names of columns like "country" and "sum" for example to "Name of the country" and "Sum of the netamount". I use Vector to create my JTable, so it's a problem to change the names.
My code:
public class App extends JFrame{
public App() {
Vector<Object> columnNames = new Vector<Object>();
Vector<Object> data = new Vector<Object>();
...
stmt = c.createStatement();
query = "select * from country";
rs = stmt.executeQuery(query);
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
for (int i = 1; i <= columns; i++)
{
columnNames.addElement(md.getColumnName(i));
}
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();
c.close();
}
catch(Exception e)
{
System.out.println(e);
}
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;
}
};
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)
{
App frame = new App();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
}
If you want to manually control the column names you can do something like:
String[] columnNames = {"Column1", "Column2", "Column3", "Column4"};
DefaultTableModel model = new DefaultTableModel(columnNames, 0)
You will no longer need the meta data for the column names.
Then when you loop through the ResultSet you just do:
while (rs.next())
{
Vector<Object> row = new Vector<Object>(columns);
for (int i = 1; i <= columns; i++)
{
row.addElement(rs.getObject(i) );
}
model.addRow( row )
}
JTable table = new JTable( model );
I wrote the following code that I thought would work, I wanted to open a new JFrame on a button click that shows a progress bar that gets updated:
b3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int numOfRows = getRows();//function that returns number of rows
int numOfColumns = getColumns();//function that returns number of columns
String myquery = "select * from foo_table";
rs = null;
try {
rs = st.executeQuery(myquery);
// extract column information
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
columnData = new ArrayList<String>(columnCount);
for (int i = 1; i <= columnCount; i++) {
columnData.add(rsmd.getColumnName(i));
}
// sql result data
table_ResQues.setModel(new ListTableModel(Collections.<List<Object>>emptyList(), Collections.<String>emptyList()));
rowData = new ArrayList<List<Object>>();
final JFrame progFrame = new JFrame("Processing...");
JPanel mainPPanel = new JPanel(new BorderLayout());
JProgressBar progBar = new JProgressBar(0,100);
progFrame.setBounds(850,300,400,100);
progFrame.setVisible(true);
progBar = new JProgressBar(0,100);
mainPPanel.add(progBar, BorderLayout.NORTH);
progFrame.add(mainPPanel);
progFrame.setVisible(true);
int countRows = 0;
int area = numOfRows*numOfColumns;
int totalTime = area % 200000;
int xPerSec = totalTime/100;
while (rs.next()) {
row = new ArrayList<Object>(columnCount);
for (int i = 0; i < columnCount; i++) {
row.add(rs.getObject(i + 1));
}
rowData.add(row);
countRows++;
if(countRows*numOfColumns == 200000){
progBar.setValue(xPerSec++);
countRows = 0;
}
}
table_ResQues.setModel(new ListTableModel(rowData, columnData));
}catch (SQLException e1) {
JOptionPane.showMessageDialog(frame, e1.getMessage(), "SQL Exception", JOptionPane.ERROR_MESSAGE);
e1.printStackTrace();
}
});
But when googling my problem I realized it is a threading issue, and I never had any experience with threading or SwingWorker, can anyone help me implement what I want using SwingWorker? Should my while-loop be the one that's running in the background? should it be a class by itself? Sorry, i'm really confused.
I have solved it by creating a new class that extends SwingWorker and overriding it's methods. Thanks for the help in the comments.
This is a followup question to Display database table with swing
I wrapped my table to a JScrollPane but the columns' headers are still not showing up!
Can anyone tell me what is wrong?
try {
con = (Connection) DriverManager.getConnection(DATABASE_URL , USERNAME, PASSWORD);
stmt = (Statement) con.createStatement();
ResultSet rs = stmt.executeQuery(QUERY_FIND_ITEMS);
{
ResultSetMetaData md = (ResultSetMetaData) rs.getMetaData();
int columns = md.getColumnCount();
// Get column names
for (int i = 1; i <= columns; i++)
{
columnNames.add( md.getColumnName(i) );
}
// Get row data
while (rs.next())
{
ArrayList row = new ArrayList(columns);
for (int i = 1; i <= columns; i++)
{
row.add( rs.getObject(i) );
}
data.add( row );
}
}
}
catch (SQLException e)
{
System.out.println( e.getMessage() );
}
Vector<String> columnNamesVector = new Vector();
Vector dataVector = new Vector();
for (int i = 0; i < data.size(); i++)
{
ArrayList subArray = (ArrayList)data.get(i);
Vector subVector = new Vector();
for (int j = 0; j < subArray.size(); j++)
{
subVector.add(subArray.get(j));
}
dataVector.add(subVector);
}
for (int i = 0; i < columnNames.size(); i++ ) {
columnNamesVector.add(columnNames.get(i));
}
// Create table with database data
JTable table = new JTable(dataVector, columnNamesVector)
{
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;
}
};
JScrollPane scrollPane =new JScrollPane(table);
getContentPane().add( scrollPane, BorderLayout.WEST );
JPanel buttonPanel = new JPanel();
getContentPane().add( buttonPanel, BorderLayout.SOUTH );
table.setForeground(Color.BLUE);
catch (SQLException e)
{
System.out.println( e.getMessage() );
}
The code after the end of the catch block will not work correctly if the DB query fails. Best to include that code within the try block.
And a tip: change
System.out.println( e.getMessage() );
to
e.printStackTrace();
Both shorter & more informative.
This is a last resort. I'm studying development of Information Systems and even my teachers can't solve this... this is a nut for you to crack!!
This is the problem: My jTable in GUI gives me this:
This is what Microsoft Management Studio shows me:
As you can tell the jTable (GUI) has got 2 main problems:
The columnname "Name" does not contain any information. And it should? Why isn't it showing?
Since as you can tell, the table contains several columns, too many to even show. I therefore want to "add a restriction" that changes so that the jTable only shows the first 6 columns.
This is the code for the "creation of the table", in the DataAccessLayer:
private TableModel getResultSetAsDefaultTableModel(ResultSet rs) {
try {
String[] columnHeadings = new String[0];
Object[][] dataArray = new Object[0][0];
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
String columnName = md.getColumnName(i);
columnHeadings = Arrays.copyOf(columnHeadings, columnHeadings.length + 1);
columnHeadings[i - 1] = columnName;
}
int r = 0;
while (rs.next()) {
Object[] row = new Object[columnCount];
for (int i = 1; i <= columnCount; i++) {
row[i - 1] = rs.getObject(i);
}
dataArray = Arrays.copyOf(dataArray, dataArray.length + 1);
dataArray[r] = row;
r++;
}
DefaultTableModel dtm = new DefaultTableModel(dataArray, columnHeadings) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
return dtm;
} catch (SQLException ex) {
Logger.getLogger(Dataaccesslayer.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
If you want me to show you the path of the code (frame, controller) just say so and I'll post it.
I would be so thankful if anyone can solve this...
Regards,
Christian
I think it is because in your for loop it should say i = 0; and not i = 1; since the first information (the name) is at index 0 right ?
In your case it could be enough to just leave the for-loop as it is and change this line to:row[i - 1] = rs.getObject(i-1);
To hide or show columns you could call setMin setMax and setPreferredWidth on your TableColumn.
Change your method like next, I think it helps you:
private TableModel getResultSetAsDefaultTableModel(ResultSet rs) {
try {
List<String> columnHeadings = new ArrayList<String>();
Object[][] dataArray = new Object[0][0];
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
columnHeadings.add(md.getColumnName(i));
}
int r = 0;
while (rs.next()) {
Object[] row = new Object[columnCount];
for (int i = 1; i <= columnCount; i++) {
row[i-1] = rs.getObject(i);
}
dataArray = Arrays.copyOf(dataArray, dataArray.length + 1);
dataArray[r] = row;
r++;
}
DefaultTableModel dtm = new DefaultTableModel(dataArray,columnHeadings.toArray(new Object[columnHeadings.size()])) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
return dtm;
} catch (SQLException ex) {
Logger.getLogger(Dataaccesslayer.class.getName()).log(Level.SEVERE,null, ex);
}
return null;
}
For showing not all columns use dtm.setColumnCount(2);. Here 2 is column count to show.