This Code is in a While Loop, and each time I run a new Query it will go through this block after I have chosen what to filter it by, the problem is when I run it a second time and click on a cell in my table it will revert to cells in my previous table/query. I attached an image to show what I mean(I need 10 reputation for that so nevermind on the picture), I filtered the table by procsessState = -1 and when I clicked on some cells it reverted to what the previous table had. Help would be greatly appreciated. The program is around 1000 lines long and I did a terrible job of splitting it into different classes So I just posted where I am almost certain the issue arises.
I declared
final String columnNamesForTable[] = {"Error Message", "ID", "Locked By", "Message Id", "Process State",
"Row Date", "Sender", "Sent Date", "Subject" };
At The top, then I have this a bit later on.
else if (checkBoxCounter != 0)
{
DefaultTableModel tableModel = new DefaultTableModel(columnNamesForTable, 0);
tableModel.fireTableDataChanged();
try
{
Connection conn = DatabaseConnection.getConnection();
System.out.println("Connected");
PreparedStatement statement = conn.prepareStatement(sb.toString(),
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
// Change CONCUR_READ_ONLY to CONCUR_UPDATABLE
ResultSet resultSet = statement.executeQuery();
int errorMessageIndex = resultSet.findColumn("ErrorMessage");
int idIndex = resultSet.findColumn("Id");
int lockedByIndex = resultSet.findColumn("LockedBy");
int messageIdIndex = resultSet.findColumn("MessageId");
int processStateIndex = resultSet.findColumn("ProcessState");
int rowDateIndex = resultSet.findColumn("RowDate");
int senderIndex = resultSet.findColumn("Sender");
int sentDateIndex = resultSet.findColumn("SentDate");
int subjectIndex = resultSet.findColumn("Subject");
while (resultSet.next()) {
Object[] rowsForTable = { resultSet.getString(errorMessageIndex),
resultSet.getString(idIndex), resultSet.getString(lockedByIndex),
resultSet.getString(messageIdIndex), resultSet.getString(processStateIndex),
resultSet.getString(rowDateIndex), resultSet.getString(senderIndex),
resultSet.getString(sentDateIndex), resultSet.getString(subjectIndex)};
tableModel.addRow(rowsForTable);
}
resultSet.close();
statement.close();
conn.close();
filterFrame.setVisible(false);
JTable resultsTable = new JTable(tableModel);
JScrollPane pane = new JScrollPane(resultsTable);
displayPnl.add(pane);
pack();
resultsTable.repaint();
isDone= true;
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Database error");
ex.printStackTrace();
isDone = true;
} catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null, "Error loading database driver");
ex.printStackTrace();
isDone = true;
}
}
This Code is in a While Loop
Why would it be in a while loop. Swing is event driven. Code should only be executed when the uses generates some kind of event like clicking on a button, typing text, editing a cell.
I have chosen what to filter it by,
Don't create a whole new table and scroll pane. Just update the TableModel of the existing JTable.
pack();
Why would you pack the frame. The query could have 100's of rows of data. Pick a reasonable size for the table when the frame is created and there is no need to use pack() or repaint(). When you invoke the setModel(...) method of the JTable to replace the current model the table will be repainted automatically.
So all the code you need should be:
//filterFrame.setVisible(false);
//JTable resultsTable = new JTable(tableModel);
//JScrollPane pane = new JScrollPane(resultsTable);
//displayPnl.add(pane);
//pack();
//resultsTable.repaint();
existingTable.setModel( tableModel );
I cant comment I do not have enough reputation.
You fire tabledatachanged before changing data.
TableDataChanged does not always properly update rows , it seems better to fire update rows.
If your table is editable , if you clicked the table you need to release the editor.
Related
Question Now once the data is fetched from the database and shown in the JTable object "table" embedded in the scrollPane, how do we create a print job that makes it possible to print the displayed table as such in A3 sized paper ?
My code to fetch the data from the database is shown below:
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost/newb","root","pass");
Statement stat=con.createStatement();
ResultSet res=stat.executeQuery("select * from table where name = '"+name+"'");
ResultSetMetaData rsmd = res.getMetaData();
int colcount = rsmd.getColumnCount();
Vector columns = new Vector(colcount);
for(int i=3; i<=colcount; i++)
{
columns.add(rsmd.getColumnName(i));
}
Vector data = new Vector();
Vector row;
// Store row data
while(res.next())
{
row = new Vector(colcount);
for(int i=3; i<=colcount; i++)
{
row.add(res.getString(i));
}
data.add(row);
}
table = new JTable(data, columns);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
scrollPane.setViewportView(table);
}
catch(Exception ex)
{
System.out.println(ex);
}
I am using vector class to fetch the data from the table. How do we print the data shown in the displayed table to a paper?
just use JTable.print() method. here is an article about sending JTable into printer and another one with more parameters
You obviously didn't read the links provided in your previous question.
From the Printing section of How to use Tables
Printing
JTable provides a simple API for printing tables. The easiest way to
print out a table is to invoke JTable.print with no arguments:
try {
if (! table.print()) {
System.err.println("User cancelled printing");
}
} catch (java.awt.print.PrinterException e) {
System.err.format("Cannot print %s%n", e.getMessage());
}
Invoking print on a normal Swing application brings up a standard printing
dialog box. (On a headless application, the table is simply printed.)
The return value indicates whether the user went ahead with the print
job or cancelled it. JTable.print can throw
java.awt.print.PrinterException, which is a checked exception; that's
why the above example uses a try ... catch.
JTable provides several overloads of print with various options. The
following code from TablePrintDemo.java shows how to define a page
header:
MessageFormat header = new MessageFormat("Page {0,number,integer}");
try {
table.print(JTable.PrintMode.FIT_WIDTH, header, null);
} catch (java.awt.print.PrinterException e) {
System.err.format("Cannot print %s%n", e.getMessage());
}
For more sophisticated printing applications, use JTable.getPrintable to obtain
a Printable object for the table. For more on Printable, refer to the
Printing lesson in the 2D Graphics trail.
i hope help you with this code try it its for How to print JTable in Java netbeans
private void btn_printActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
MessageFormat header = new MessageFormat("Print Report");
MessageFormat footer = new MessageFormat("Page{0,number,integer}");
try {
table_employee.print(JTable.PrintMode.FIT_WIDTH, header, footer);
} catch (java.awt.print.PrinterAbortException e) {
} catch (PrinterException ex) {
Logger.getLogger(employee_info.class.getName()).log(Level.SEVERE, null, ex);
}
}
i want to add or insert column from different methods into one table.. cant explain it clearly but i show my codes to you to understand..for example.
(....)
DefaultTableModel dtm = new DefaultTableModel();
JTable table = new JTable();
Constructor(){
table.setModel(dtm);
(.....)
}
public void methodOne(){
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();
}
public void methodTwo(){
(.....)
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
}
those value inside row are the value i want to add on my table, i dont have any idea on how to id.. i want it to be like this:
first when you run the java it will autoumatically create a table
http://i1023.photobucket.com/albums/af355/guiacustodio/javaaaaaaaaaaaaaaaaaaaaaaa_zpse9a22225.jpg
i have a button and textfield i enter number on the textfield i.e
[PAY BUTTON] TextField:[__100]
i clicked the button and this is what will happen:
http://i1023.photobucket.com/albums/af355/guiacustodio/javaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_zps43879eab.jpg
First of all, the data Vector you are using is defined inside methodOne so the same data is not accesible via methodTwo.
Secondly it is not because there is data being added to data in a tablemodel that the table will refresh, you have to call one of the methods that trigger an refresh event in the gui, normally one calls the method fireTableChanged on the tablemodel after you added data.
Thridly: there is an interesting library called GlazedLists that handles a lot of these things automatically !
I want to add rows in JTable, but it didn't work well. Could someone help me? Table is displaying normal but not dynamically
//displays all data in Jtable
void refresh()
{
Vector<Vector<String>> data = new Vector<>();
ResultSet rs = st.executeQuery("SELECT * FROM tblInfo");
while(rs.next())
{
Vector<String> d = new Vector<>();
d.add(rs.getString("ID"));
d.add(rs.getString("Name"));
d.add(rs.getString("User"));
d.add(rs.getString("Pass"));
data.add(d);
}
Vector<String> header = new Vector<>();
header.add("ID");
header.add("Name");
header.add("Username");
header.add("Password");
model = new DefaultTableModel(data, header);
table = new JTable(model);
st.close();
rs.close();
table.setBackground(Color.LIGHT_GRAY);
table.setForeground(Color.white);
scroll = new JScrollPane(table);
getContentPane().add(scroll);
st.close();
rs.close();
}
//adding data to database
void addDoctor()
{
st.executeUpdate("INSERT INTO tblInfo(Name) VALUES ('Name')");
st.close();
}
public void actionPerformed(ActionEvent e){
Object source = e.getSource();
else if(btnAdd == source)
{
addDoctor();
refresh();
}
Thanks for any response. :)
I have edited this code before i've posted.
1) Don't create any Objects inside try - catch - finally block; for Swing GUI, prepare these Objects before, better as local variables.
2) You created a new
model = new DefaultTableModel(data, header);
table = new JTable(model);
and those Object maybe never added to the already visible GUI. Swing GUI doesn't care somehow, and the container doesn't know that you changed (reset, reinitialize) the underlaying model and with JTable. You have to notify Swing GUI for changes, but this isn't the proper of way.
3) Don't to recreate this Object on runtime, reuse Objects that already exist, create JTable and DefaultTableModel only one time.
4) Reset DefaultTableModel by using model.setRowCount(0); and then to add a new rows from JDBC
5) Don't to reinvent the wheel, search for ResultSetTableModel or TableFromDatabase.
6) Move code lines st.close(); & rs.close(); to the finally block.
Use DefaultTableModel.setDataVector() to add a new Vector with the new Data to the existing TableModel/JTable. Or use the insertRow/removeRow methods. Or implement your own AbstractTableModel.
I have the following method which creates a JTable then prints it out by its appearing as a rectangle no the page with the header and footer.
public void printModules(){
MessageFormat header = new MessageFormat("Modules " + new Date());
MessageFormat footer = new MessageFormat("Created by Assignments Database");
try {
JTable jtModules = new JTable(new ModulesTableModel(Controller.getInstance().getModules()));
jtModules.setShowHorizontalLines(true);
jtModules.setShowVerticalLines(true);
jtModules.setShowGrid(true);
boolean complete = jtModules.print(JTable.PrintMode.NORMAL, header, footer, true, null, false, null);
if(complete){
System.out.println("Printed");
} else{
System.out.println("Printing Cancelled");
}
} catch (PrinterException e) {
e.printStackTrace();
}
}
What else is wrong? There is data in the table as one that is created from the same data is showing in one of the panels.
In my abstract table model I have implemented the following methods:
Constructor
getRowCount
getColumnCount
getValueAt
getColumnNames
Is there any other methods that need to be created?
JTable has very reduced support for printing, there are some descriptions about printing in the tutorials about JTable (inc. code example) and Printing
You need to display the table in order to print it, so add it to a JFrame, then frame.setVisible(true); then frame.setVisible(false);
This will make it print.
I'm writing a program using jdbc that will be an interface to database(smth like CRUD aplication). I assume that I have to write a class(e.g. DBCLass) that will do all the operations with database(select, update, insert, delete and maybe some other logic that will be reduced to these operations). User interface consists of a set of tables and a few buttons. To use a Jtable I need to implement a class(e.g Model) which is a subclass of AbstractTableModel. So this class will display my data to the user. I need to implement such model for all tables in my database schema. I don't want to write the logic in that classes that display data to the user and I think it is not very good thing to write the logic code in such classes. But it is also incorrect to load all the data from the db table to memory(e.g. ArrayList) and then display it in Model.
So, I want an advise which is the best way to solve such problem.
edit:
A small example:
Statement stmt = ....;
ResaultSet rs = stmt.executeQuery("SELECT * FROM table1");
javadoc says that executeQuery method returns a ResultSet object that contains the data produced by the given query. So If we have a lot of data(which size is more than permited size to our virtual machine), our program will fail.
So my question is still relevant
Download the source for SQuirreL SQl and have a look at the table implementation.
Some things to note:
Database tables aren't Java JTables. A table in a database is in fact a set (curse the fool who used the wrong term) with items and each item has properties (usually called "columns" which isn't a JColumn which explains why it's so hard to map the two).
A set can grow to any size. It has no intrinsic order. You can do lots of set operations on it like: union, difference, sub set.
Therefore, it's not a table, especially not a UI table.
There is no easy UI paradigm which maps "set" to "table". You can
Load N records and page through the results.
You can load more as the user scrolls down
You can count the size of the set and adjust the scrollbar accordingly. As the user scrolls through the data, it is fetched from the DB and displayed.
Pros + cons:
Solution 1 is most simple to implement and the one which users hate most. Why do they need to wait to see data again when the go backwards? This is especially frustrating if each fetch takes 15 seconds. Page ... wait ... page ... oops! There it was! Damn! Wait wait wait ... back ... wait ... aaargh.
Also databases often have a hard time to page data. For some queries, performance can be disastrous.
Solution 2 is simple to implement, especially if you can keep the ResultSet open forever. But 100% of the time, you can't. It will start to fail if you keep it open for a couple of hours or a day. After that time, the DB will think "oh, it's dead, Jim" and close the connection and your user will get a nice error message and you will get an angry user.
So you need to page here, too, but not as often. On the positive side, users need not wait again for data they already have. One huge point: If the set contains millions of rows, users intuitively understand that they need to attack the problem from a different angle as they scroll down. Eventually, they will get tired and ask for a better solution (instead of being angry at you because your stupid program can't display 15 million rows in less than 0.0000000001s).
Solution 3 is worse than #2, again. If the table grows, the UI will become unusable: Even looking at the scroll know will move you to a random place in the table. So it makes your mouse useless. And your users angry.
So I usually try a solution which:
Reads 1000 rows, max. Plus I stop after 100 rows (so the user has at least some data) if reading the rows takes more than 1 second. Usually, the query is slow and reading the result set takes virtually no time, but I like being defensive here.
On top of each column is a filter and an "order by" which can be mapped directly to SQL. That way, I can make sure that if you want the data sorted by a column, it's sorted by all values (and not only those which you can see on the screen).
This allows users to chop huge amounts of data into meaningful sub sets.
Table From Database has a couple of ideas.
Maks,
Here is another example on generic sql to table implementation:
http://www.oreillynet.com/pub/a/oreilly/java/news/javaex_1000.html
It may be a good place to look for your answer.
Also, this local question/answer may help you with ResultSet size: Java JDBC Lazy-Loaded ResultSet
Hope this helps,
Robert
This blog post explains how to lazy load data into a table model: JTable Bound to a Database With Lazy Loading
You want to use the DBTable component from the QuickTable project.
Check this SO answer with sample code usage.
Here's a class that extract data rows and columns from database.
Look at table = new JTable(rows(), columns());
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.print.PrinterException;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import com.swtdesigner.SwingResourceManager;
import java.util.*;
import java.sql.*;
import javax.swing.*;
public class listing extends JDialog {
private JTable table;
public static Vector rows() {
Vector data = new Vector();
String sql= null;
Connection C;
try {
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
C = (Connection) DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:XE",
"system", "manager");
Statement stmt = C.createStatement();
ResultSet rset = stmt.executeQuery("SELECT * FROM site ");
ResultSetMetaData md = rset.getMetaData();
int columns = md.getColumnCount();
while (rset.next()) {
Vector row = new Vector(columns);
for (int i = 1; i <= columns; i++) {
row.addElement(rset.getObject(i));
}
data.addElement(row);
}
rset.close();
stmt.close();
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
}
//System.out.println("lignes : "+data);
return data;
}
public static Vector columns()
{ Connection c ;
Vector cols = new Vector ();
String sql2=null;
try {
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
c = DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:XE",
"system", "manager");
sql2 = "select * from SITE";
Statement stmt = c.createStatement();
ResultSet rs = stmt.executeQuery(sql2);
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
//récupération des noms des colonnes dans la table site
for (int i = 1; i <= columns; i++) {
cols.addElement(md.getColumnName(i));
}
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
}
//System.out.println("colonnes ::: "+cols);
return cols;
}
public static void main(String args[]) {
try {
listing dialog = new listing();
dialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public listing() {
super();
getContentPane().setLayout(null);
setTitle("Listing de la table \"SITE\"");
setBounds(100, 100, 500, 363);
setResizable(false);
final JLabel laTablesiteLabel = new JLabel();
laTablesiteLabel.setText("La table \"SITE\" contient . . . ");
laTablesiteLabel.setBounds(10, 34, 274, 16);
getContentPane().add(laTablesiteLabel);
final JLabel label = new JLabel();
label.setIcon(SwingResourceManager.getIcon(listing.class, "/pictures/130.png"));
label.setBounds(402, 18, 49, 48);
getContentPane().add(label);
final JButton okButton = new JButton();
okButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent arg0) {
dispose();
setVisible(false);
}
});
okButton.setIcon(SwingResourceManager.getIcon(listing.class, "/pictures/33-32x32.png"));
okButton.setText("Ok");
okButton.setBounds(10, 291, 148, 32);
getContentPane().add(okButton);
final JButton refeshButton_1 = new JButton();
refeshButton_1.setIcon(SwingResourceManager.getIcon(listing.class, "/pictures/48-32x32.png"));
refeshButton_1.setText("Actualiser");
refeshButton_1.setBounds(171, 291, 148, 32);
getContentPane().add(refeshButton_1);
final JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 85, 474, 187);
getContentPane().add(scrollPane);
table = new JTable(rows(), columns()); // chargement de JTable
scrollPane.setViewportView(table);
final JButton printButton_1_1 = new JButton();
printButton_1_1.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent arg0) {
try {
table.print();
} catch (PrinterException e) {
e.printStackTrace();
}
}
});
printButton_1_1.setIcon(SwingResourceManager.getIcon(listing.class, "/pictures/Printer_h.png"));
printButton_1_1.setText("Imprimer");
printButton_1_1.setBounds(336, 291, 148, 32);
getContentPane().add(printButton_1_1);
}
}