Reset JTable depending on content (number of rows) - java

I have a JTable inside a JPanel which in turn is in a Jframe. The JTable loads users from a table (database in MySQL).
I have a search engine using DNIs in which key-to-key, with a KeyTyped event, is updating the contacts in the table, and show only those that meet the browser pattern (JTextField). If there are only 2-3-4 clients, the table is not resized to the customer size, but fills the rest of the table with a gray background. (see image). How could the lower bound of the table be reset?
Code:
public class Listado_clientes1 extends javax.swing.JFrame{
private TableRowSorter<DefaultTableModel> TRSFiltro;
public Listado_clientes1() {
this.getContentPane().setBackground(Color.orange);
panel_top.setBackground(Color.orange);
tabla_clientes.setPreferredScrollableViewportSize(
new Dimension(tabla_clientes.getPreferredSize().width, tabla_clientes.getRowHeight()*20)
);
try {
DefaultTableModel modelo = new DefaultTableModel();
tabla_clientes.setModel(modelo);
PreparedStatement ps = null;
ResultSet rs = null;
Connection con = Conexiones.conexion_a_BBDD("agenda");
String sql = "SELECT dni, nombre, apellidos, telefono, direccion, ciudad, email FROM clientes";
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
ResultSetMetaData rsMd = (ResultSetMetaData) rs.getMetaData();
int cantidadColumnas = rsMd.getColumnCount();
modelo.addColumn("DNI");
modelo.addColumn("NOMBRE");
modelo.addColumn("APELLIDOS");
modelo.addColumn("TLFONO");
modelo.addColumn("DIRECCION");
modelo.addColumn("CIUDAD");
modelo.addColumn("EMAIL");
while (rs.next()) {
Object[] filas = new Object[cantidadColumnas];
for (int i=0; i<cantidadColumnas; i++) {
filas[i] = rs.getObject(i+1);
}
modelo.addRow(filas);
}
} catch (SQLException ex) {
System.err.println(ex.toString());
}
}
/**
* Filtrar: Buscar por DNI.
*/
public void filtrar_dni() {
int columna = 0; //Es la fila del DNI.
TRSFiltro.setRowFilter(RowFilter.regexFilter(textfield_buscar.getText(), columna));
}
private void textfield_buscarKeyTyped(java.awt.event.KeyEvent evt) {
Character letra = evt.getKeyChar();
evt.setKeyChar(Character.toUpperCase(letra));
textfield_buscar.addKeyListener(new KeyAdapter(){
public void keyReleased(final KeyEvent e){
String texto = (textfield_buscar.getText());
textfield_buscar.setText(texto);
filtrar_dni();
}
});
TRSFiltro = new TableRowSorter<DefaultTableModel>((DefaultTableModel) tabla_clientes.getModel());
tabla_clientes.setRowSorter(TRSFiltro);
}
}
Outline / Scheme:

Any time the number of rows in the view of the table changes you need to recalculate the
preferred scrollable viewport size of the table. Once this size is recalculated you need to invoke the layout manager of the panel containing the table:
A reusable method would be something like:
public void resetTablePreferredScrollableViewportSize(JTable table, int maxRows)
{
Dimension size = table.getPreferredSize();
int displayRows = Math.min(table.getRowCount(), maxRows);
size.height = displayRows * table.getRowHeight();
table.setPreferredScrollableViewportSize( size );
Container parent = SwingUtilities.getAncestorOfClass(JPanel.class, table);
parent.revalidate();
parent.repaint();
}
So after setting the row filter you could use:
tabla_clientes.setRowSorter(TRSFiltro);
resetTablePreferredScrollableViewportSize(tabla_clientes, 10);
Now the scroll pane should be sized to display up to 10 rows after which the scrollbar of the scroll pane will appear.
Edit:
I don't know how to put a reproducible example
Then you don't understand what your problem is.
Your question is that you want to:
Reset JTable (size) depending on number of rows
So the data is irrelevant, only the number of rows is relevant.
It is easy to test this because you can create a DefaultTableModel with a specified number of rows.
Below is a simple MRE. To test you:
enter a number in the text field
press enter
The table will be resized to display the specified number of rows. If the number is greater that 10 the table size will be fixed and a scrollbar will appear:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.table.*;
public class SSCCE extends JPanel
{
JTextField textField;
JTable table;
public SSCCE()
{
setBackground(Color.YELLOW);
textField = new JTextField(5);
add(textField);
table = new JTable(new DefaultTableModel(0, 4));
table.setPreferredScrollableViewportSize(table.getPreferredSize());
add( new JScrollPane(table) );
textField.addActionListener((e) ->
{
int rows = Integer.parseInt( textField.getText() );
table.setModel( new DefaultTableModel(rows, 4) );
resetTablePreferredScrollableViewportSize(table, 10);
});
}
public void resetTablePreferredScrollableViewportSize(JTable table, int maxRows)
{
Dimension size = table.getPreferredSize();
int displayRows = Math.min(table.getRowCount(), maxRows);
size.height = displayRows * table.getRowHeight();
table.setPreferredScrollableViewportSize( size );
Container parent = SwingUtilities.getAncestorOfClass(JPanel.class, table);
parent.revalidate();
parent.repaint();
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// frame.pack();
frame.setSize(500, 250);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}

Related

triggering java events from different classes

so i have this JFrame window that has a button that opens a different JFrame, the goal from the second window is upon clicking its ok button a table refresh in the first window, but i'm having a hard time solving the issue and didn't find any answer after about an hour of searching (it's not a lot i know but i'm pressed for time). so this is my code and i hope you guys help me out.
the code for the first window:
// the event that i want to trigger
public void refreshTable() {
try {
ResultSet rs = new dbcon().getResultSet("select * from users", new Vector<Object>());
Vector<Vector<Object>> v = new Vector<Vector<Object>>();
while(rs.next()) {
Vector<Object> element = new Vector<Object>();
element.add(rs.getInt("id"));
element.add(rs.getString("name"));
element.add(rs.getString("uname"));
element.add(rs.getString("pwd"));
element.add(rs.getString("date"));
element.add(rs.getInt("admin"));
v.add(element);
}
DefaultTableModel md = (DefaultTableModel) table.getModel();
md.setRowCount(0);
for(int i=v.size()-1;i>=0;i--) {
md.addRow(v.elementAt(i));
}
}catch(Exception exp) {
exp.getLocalizedMessage();
}
}
//the event where the second window is opened
else if(e.getSource() == mod) {
int id = (int) table.getModel().getValueAt(table.getSelectedRow(),0);
String user = (String) table.getModel().getValueAt(table.getSelectedRow(),2);
String pass = (String) table.getModel().getValueAt(table.getSelectedRow(),3);
new Edits().changeUser(user, pass, id);
this.refreshTable();
}
and this is the code for the second window:
//the frame of the second window
public void changeUser(String user,String pass, int id) {
//init frame
this.setTitle("Change User Login");
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JFrame.setDefaultLookAndFeelDecorated(false);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(dim.width/6-this.getSize().width/2, dim.height/16-this.getSize().height/2);
this.setSize(400, 290);
this.setResizable(false);
this.setVisible(true);
//change sizes
Dimension labels = new Dimension(150,25);
Dimension inputs = new Dimension(200,25);
Dimension btn = new Dimension(80,35);
Dimension btn1 = new Dimension(120,35);
//labels size
currentUser.setSize(labels);
currentUser.setMaximumSize(labels);
currentUser.setMinimumSize(labels);
currentUser.setPreferredSize(labels);
changeUser.setSize(labels);
changeUser.setMaximumSize(labels);
changeUser.setMinimumSize(labels);
changeUser.setPreferredSize(labels);
currentPass.setSize(labels);
currentPass.setMaximumSize(labels);
currentPass.setMinimumSize(labels);
currentPass.setPreferredSize(labels);
changePass.setSize(labels);
changePass.setMaximumSize(labels);
changePass.setMinimumSize(labels);
changePass.setPreferredSize(labels);
//inputs size
oldUser.setSize(inputs);
oldUser.setMaximumSize(inputs);
oldUser.setMinimumSize(inputs);
oldUser.setPreferredSize(inputs);
newUser.setSize(inputs);
newUser.setMaximumSize(inputs);
newUser.setMinimumSize(inputs);
newUser.setPreferredSize(inputs);
oldPass.setSize(inputs);
oldPass.setMaximumSize(inputs);
oldPass.setMinimumSize(inputs);
oldPass.setPreferredSize(inputs);
newPass.setSize(inputs);
newPass.setMaximumSize(inputs);
newPass.setMinimumSize(inputs);
newPass.setPreferredSize(inputs);
//button sizes
okUser.setSize(btn1);
okUser.setMaximumSize(btn1);
okUser.setMinimumSize(btn1);
okUser.setPreferredSize(btn1);
closeUser.setSize(btn);
closeUser.setMaximumSize(btn);
closeUser.setMinimumSize(btn);
closeUser.setPreferredSize(btn);
//set layout
this.setLayout(new FlowLayout(FlowLayout.CENTER,10,15));
//add components
this.add(currentUser);
this.add(oldUser);
this.add(changeUser);
this.add(newUser);
this.add(currentPass);
this.add(oldPass);
this.add(changePass);
this.add(newPass);
this.add(okUser);
this.add(closeUser);
//button & input configuration
oldUser.setEditable(false);
oldUser.setText(user);
oldPass.setEditable(false);
oldPass.setText(pass);
Id.setValue(id);
newUser.setText(user);
newPass.setText(pass);
okUser.addActionListener(this);
closeUser.addActionListener(this);
}
//the action of the second window
else if(e.getSource() == okUser) {
String user = oldUser.getText();
String pass = oldPass.getText();
int id = (int) Id.getValue();
if(!newUser.getText().equals("") && !newPass.getText().equals("")) {
try {
Vector<Object> params = new Vector<Object>();
params.add(newUser.getText());
params.add(newPass.getText());
params.add(id);
new dbcon().setUpdates("update users set uname = ?, pwd = ? where id = ?", params);
JOptionPane.showMessageDialog(null, "User Informations Updated");
this.dispose();
}catch(Exception exp) {
exp.printStackTrace();
}
}else {
JOptionPane.showMessageDialog(null, "Please make sure to fill out all the fields!");
}
}
i hope you guys be able to help me out because it's for a school project due in 5 hours. thank you all for your time :D

Java Resultset to JTable with Checkbox

I have this code to which it can display data from database. It's working well but I want it to have checkbox at last column. I've found some codes here but It's only for pre-defined not values and not from database. (How to add checkboxes to JTABLE swing)
Screenshot:
Code:
public print() {
initComponents();
try{
conn = (Connection) db_connect.connectDB();
}
catch(ClassNotFoundException | SQLException ex){
JOptionPane.showMessageDialog(null, ex);
}
update_table("select name, section, student_number, gender from students");
}
public void update_table(String q){
try{
st= conn.createStatement();
st.executeQuery(q);
ResultSet rs = st.executeQuery(q);
users_list.setModel(DbUtils.resultSetToTableModel(rs));
users_list.getColumnModel().getColumn(0).setPreferredWidth(250);
users_list.getColumnModel().getColumn(0).setPreferredWidth(250);
users_list.getColumnModel().getColumn(1).setPreferredWidth(150);
users_list.getColumnModel().getColumn(2).setPreferredWidth(120);
users_list.getColumnModel().getColumn(3).setPreferredWidth(100);
int count= users_list.getModel().getRowCount();
if(count==0){
no_results_found.setVisible(true);
}
else{
no_results_found.setVisible(false);
}
}
catch(SQLException ex){
JOptionPane.showMessageDialog(null,ex);
}
}
You can try something like this:
public class JTableWithCheckBox {
private JFrame mainFrame;
private JTable studentTable;
private JScrollPane scrollPaneTable;
private DefaultTableModel model = new DefaultTableModel(new Object[][] {
{ "Ramesh", "Male" }, { "Sheela", "Female" },
{ "Amithabh", "Male" }, { "Katrina", "Female" } }, new Object[] {
"Name", "Gender" });
public static void main(String[] args) {
final JTableWithCheckBox ui = new JTableWithCheckBox();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ui.initGUI();
}
});
}
private void initGUI() {
mainFrame = new JFrame("View");
mainFrame.getContentPane().setLayout(new BorderLayout());
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(300, 200);
mainFrame.setVisible(true);
mainFrame.setLocationRelativeTo(null);
studentTable = new JTable(model);
studentTable.getColumnModel().getColumn(1)
.setCellRenderer(new MFCheckBox());
scrollPaneTable = new JScrollPane(studentTable);
mainFrame.add(scrollPaneTable, BorderLayout.NORTH);
}
private class MFCheckBox implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
JPanel cbPanel = new JPanel();
JCheckBox maleBox = new JCheckBox("Male");
JCheckBox femaleBox = new JCheckBox("Female");
cbPanel.setLayout(new BorderLayout());
cbPanel.add(maleBox, BorderLayout.WEST);
cbPanel.add(femaleBox, BorderLayout.EAST);
if (value != null) {
if (value instanceof String) {
String valStr = (String) value;
switch (valStr) {
case "Male":
maleBox.setSelected(true);
femaleBox.setSelected(false);
break;
case "Female":
maleBox.setSelected(false);
femaleBox.setSelected(true);
break;
default:
maleBox.setSelected(false);
femaleBox.setSelected(false);
break;
}
}
}
return cbPanel;
}
}
}
If you also want checkbox editable, you will have to set TableCellEditor as well.
The easiest way is to NOT use DBUtils and to load the data from the ResultSet into the TableModel` yourself.
The code is not difficult and you can use the Table From Database Example found in Table From Database as the starting point.
The code just loads the data from the ResultSet into Vectors, so you can then manually add another column to contain Boolean data.
The changes to the code would be something like:
// Get column names
for (int i = 1; i <= columns; i++)
{
columnNames.addElement( md.getColumnName(i) );
}
columnName.addElement( "Check Mark" ); // added
// 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) );
}
row.addElement( Boolean.FALSE ); // added
data.addElement( row );
}
The other option is to create a "wrapper" TableModel that wraps a Boolean column with your DBUtils TableModel. Check out How to add checkbox in Jtable populated using rs2xml for an example of this approach.
That answer places the check box column at the start of the table, so you would need to modify the code to place the check box at the end.

How add status image in default jTable java Netbeans

I have a jtable functioning normally. The table lists tasks, and each task you an associated status.
I want every status is associated with an image.
So the image would appear in the table as show below.
------Code for jTable----------
DefaultTableModel tmSubTask = new DefaultTableModel(null, new String[]{"Status", "Priority", "Task", "SubTask", "Desc", "Prevision Begin", "Time", "Prevision Duration", "Prevision hour", "Begin", "Hour Begin","End Date" ,"End Hour", "Duration"});
List<SubTask> subTask;
ListSelectionModel lsmSubTask;
Connection conexao = null;
PreparedStatement pst= null;
ResultSet rs = null;
private void showSubTask(List<SubTask> subTask) {
while (tmSubTask.getRowCount() > 0) {
tmSubTask.removeRow(0);
}
if (subTask.size() == 0) {
JOptionPane.showMessageDialog(null, "showSubTask");
} else {
String[] line = new String[]{null, null, null};
for (int i = 0; i < SubTask.size(); i++) {
tmSubTask.addRow(linha);
tmSubTask.setValueAt(subTask.get(i).getStatus(), i, 0);
tmSubTask.setValueAt(subTask.get(i).getIdPriority(), i, 1);
tmSubTask.setValueAt(subTask.get(i).getIdTask(), i, 2);
tmSubTask.setValueAt(subTask.get(i).getIdSubTask(), i, 3);
tmSubTask.setValueAt(subTask.get(i).getDescSubTask(), i, 4);
tmSubTask.setValueAt(subTask.get(i).getDateBegin(), i, 5);
tmSubTask.setValueAt(subTask.get(i).getTerm(), i, 6);
tmSubTask.setValueAt(subTask.get(i).getDuration(), i, 7);
tmSubTask.setValueAt(subTask.get(i).gethourBeginP(), i, 8);
tmSubTask.setValueAt(subTask.get(i).getDateBegin(), i, 9);
tmSubTask.setValueAt(subTask.get(i).getHourBegin(), i, 10);
tmSubTask.setValueAt(subTask.get(i).getDateEnd(), i, 11);
tmSubTask.setValueAt(subTask.get(i).getHourEnd(), i, 12);
tmSubTask.setValueAt(subTask.get(i).getDuration(), i, 13);
}
}
}
---------------jTable--------------
---------------What I want---------
Imagine if Status like Delay in jTable show image red.
I honestly don't even know where to start.
I apologize if I did not make myself clear.
Thank all any help you can give me.
Greetings.
Any questions I will try to explain as best as possible.
Add an ImageIcon to the table and override the getColumnClass(...) method of the JTable to return Icon.class and the table will use an appropriate renderer to display the Icon. Something like:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableIcon extends JFrame
{
public TableIcon()
{
Icon aboutIcon = new ImageIcon("about16.gif");
Icon addIcon = new ImageIcon("add16.gif");
Icon copyIcon = new ImageIcon("copy16.gif");
String[] columnNames = {"Picture", "Description"};
Object[][] data =
{
{aboutIcon, "About"},
{addIcon, "Add"},
{copyIcon, "Copy"},
};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable( model )
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
new TableRowResizer(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumnAdjuster tca = new TableColumnAdjuster(table);
tca.adjustColumns();
}
public static void main(String[] args)
{
TableIcon frame = new TableIcon();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
}

create jcomponents using database

I want to create jcomponents dynamically using database. when I open any jframe or jpanel components like jlabel, jtextfields, jcombobox, etc should be created by reading database rows.
I am confused in how to give reference from database value i.e. in the String to the jcomponent's object.
this is my database table
try{
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db","root","pass");
stat = con.createStatement();
ResultSet rs = stat.executeQuery("select * from design");
while(rs.next()){
jTextField1 = new JTextField();
jTextField1.setSize(rs.getInt("height"),rs.getInt("width"));
jTextField1.setLocation(rs.getInt("x"), rs.getInt("y"));
}
rs.close();
stat.close();
con.close();
}
catch(Exception e){
System.out.println(e);
}
this is demo table.
I know this will not work because I can't communicate with objects and database.
I want to print jcomponents on jframe. I will write for loop to print them multiple times.
please help me.
First of all see this #AndrewThompson's wise advice:
Java GUIs might have to work on a number of platforms, on different
screen resolutions & using different PLAFs. As such they are not
conducive to exact placement of components. To organize the components
for a robust GUI, instead use layout managers, or combinations of
them, along with layout padding & borders for white space.
There are some helpful topics to understand what it means here:
Non resizable window border and positioning
Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
Nested Layout Example
Providing white space in a Swing GUI
You'll see the use of methods like setLocation(), setBounds() or setSize() is highly discouraged. However I've seen this approach before applied to allow customizing forms. But instead of specific (x,y) coordinates and fixed (width,height) you can store constraints for GridBagLayout. Let's say you have a table like this:
I'd start first with a class to wrap data from the DB:
public class Data {
private String componentType, text;
private int column, row, width, height, weightX, weightY;
public Data(String componentType, int column, int row, int width, int height
,int weightX, int weightY, String text) {
this.componentType = componentType;
this.column = column;
this.row = row;
this.width = width;
this.height = height;
this.weightX = weightX;
this.weightY = weightY;
this.text = text;
}
// getters and setters here
}
As database calls are time consuming task you have to consider use a SwingWorker to do the database call (time consuming task) in a background thread and create/update your GUI in the Event Dispatch Thread.
Having said this you may have something like this:
public class Demo {
private JPanel content;
private JFrame frame;
private void createAndShowGUI() {
content = new JPanel(new GridBagLayout());
SwingWorker<Void, Data> worker = new SwingWorker<Void, Data>() {
#Override
protected Void doInBackground() {
try{
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db","root","password");
Statement stat = con.createStatement();
ResultSet rs = stat.executeQuery("select * from TableName");
while(rs.next()){
String componentType = rs.getString("component");
int column = rs.getInt("x");
int row = rs.getInt("y");
int width = rs.getInt("width");
int height = rs.getInt("height");
int weightx = rs.getInt("weightx");
int weighty = rs.getInt("weighty");
String text = rs.getString("text");
Data data = new Data(componentType, column, row, width, height
,weightx, weighty, text);
publish(data);
}
rs.close();
stat.close();
con.close();
} catch(Exception e) {
System.out.println(e);
}
return null;
}
#Override
protected void process(List<Data> chunks) {
for(Data data : chunks) {
JComponent component = null;
if(data.getComponentType().equalsIgnoreCase("JTextField")) {
component = new JTextField(data.getText());
}
if(data.getComponentType().equalsIgnoreCase("JComboBox")) {
component = new JComboBox();
}
if(data.getComponentType().equalsIgnoreCase("JLabel")) {
component = new JLabel(data.getText());
}
if(component != null) {
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = data.getColumn();
constraints.gridy = data.getRow();
constraints.gridwidth = data.getWidth();
constraints.gridheight = data.getHeight();
constraints.weightx = data.getWeightX();
constraints.weighty = data.getWeightY();
constraints.anchor = GridBagConstraints.WEST;
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(8,8,8,8);
content.add(component, constraints);
}
}
}
#Override
protected void done() {
frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
};
worker.execute();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
}
And you'll see something like this:

How to provide pagination support to a JTable in Swing?

I have created one GUI in Swing Java in which I have used JTable.Now I want to display next page information into it by using pagination. How should I do that ?
Another option to implement this is to use a scrollbar-less scrollpane and a couple nav buttons to effect the control. The buttons that have been added are normal JButtons for the prototype.
A quick prototype is added below. It makes a couple assumptions, one of which is that the table model has all of its data. Work could be done to ensure that rows end up flush at the top of the view upon navigation.
private void buildFrame() {
frame = new JFrame("Demo");
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addStuffToFrame();
frame.setVisible(true);
}
private void addStuffToFrame() {
final JTable table = getTable();
final JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
final JButton next = new JButton("next");
final JButton prev = new JButton("prev");
ActionListener al = new ActionListener(){
public void actionPerformed(ActionEvent e) {
Rectangle rect = scrollPane.getVisibleRect();
JScrollBar bar = scrollPane.getVerticalScrollBar();
int blockIncr = scrollPane.getViewport().getViewRect().height;
if (e.getSource() == next) {
bar.setValue(bar.getValue() + blockIncr);
} else if (e.getSource() == prev) {
bar.setValue(bar.getValue() - blockIncr);
}
scrollPane.scrollRectToVisible(rect);
}
};
next.addActionListener(al);
prev.addActionListener(al);
JPanel panel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel();
buttonPanel.add(prev);
buttonPanel.add(next);
panel.add(buttonPanel, BorderLayout.NORTH);
panel.add(scrollPane, BorderLayout.CENTER);
frame.getContentPane().add(panel);
}
private JTable getTable() {
String[] colNames = new String[]{
"col 0", "col 1", "col 2", "col 3"
};
String[][] data = new String[100][4];
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 4; j++) {
data[i][j] = "r:" + i + " c:" + j;
}
}
return new JTable(data,colNames);
}
alt text http://img7.imageshack.us/img7/4205/picture4qv.png
Paging in a Swing JTable looks like a nice article.
Here is an excerpt:
As far as I remember the solution for this problem lies in the concept of paging: just retrieve the data that the user wants to see and nothing more. This also means you have to sometimes get extra data from the db server (or appserver) if your user scrolls down the list.
Big was my surprise that there wasn't really an out-of-the-box solution (not even a copy- paste solution) for this problem. Anyone that knows one, please don't hesitate to extend my (rather limited) knowledge of the J2EE platform.
So we dug in, and tried to build a solution ourselves.
What we eventually came up with was an adapted TableModel class to takes care of the paging.
You can try with 2 query, first query is to count total rows in DB and second query is for the real data :) And for the UI side, you can try like this:
public class MainForm extends javax.swing.JFrame {
private void initDefaultValue() {
rowsPerPage = Integer.valueOf(cmbPageSize.getSelectedItem().toString());
totalRows = Main.getTablePagingService().countComments();
Double dblTotPage = Math.ceil(totalRows.doubleValue()/rowsPerPage.doubleValue());
totalPage = dblTotPage.intValue();
if (pageNumber == 1) {
btnFirst.setEnabled(false);
btnPrevious.setEnabled(false);
} else {
btnFirst.setEnabled(true);
btnPrevious.setEnabled(true);
}
if (pageNumber.equals(totalPage)) {
btnNext.setEnabled(false);
btnLast.setEnabled(false);
} else {
btnNext.setEnabled(true);
btnLast.setEnabled(true);
}
txtPageNumber.setText(String.valueOf(pageNumber));
lblPageOf.setText(" of " + totalPage + " ");
lblTotalRecord.setText("Total Record " + totalRows + " rows.");
List wPComments = Main.getTablePagingService().findAllComment(pageNumber, rowsPerPage);
jTable1.setModel(new CommentTableModel(wPComments));
autoResizeColumn(jTable1);
}
private void btnFirstActionPerformed(ActionEvent evt) {
pageNumber = 1; initDefaultValue();
}
private void btnPreviousActionPerformed(ActionEvent evt) {
if (pageNumber > 1) {
pageNumber -= 1; initDefaultValue();
}
}
private void btnNextActionPerformed(ActionEvent evt) {
if (pageNumber
And in service layer, you just need use limit function like this :
public List findAllComment(Integer pageNumber, Integer rowsPerPage) {
try {
List listWP = new ArrayList();
preparedFindAll.setInt(1, (rowsPerPage*(pageNumber-1)));
preparedFindAll.setInt(2, rowsPerPage);
ResultSet rs = preparedFindAll.executeQuery();
while (rs.next()) {
WPComment comment = new WPComment();
comment.setCommentID(rs.getInt("comment_ID"));
comment.setCommentAuthor(rs.getString("comment_author"));
comment.setCommentDate(rs.getDate("comment_date"));
comment.setCommentContent(rs.getString("comment_content"));
listWP.add(comment);
}
return listWP;
} catch (SQLException ex) {
Logger.getLogger(TablePagingServiceJDBC.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public Integer countComments() {
try {
Integer totalRows = 0;
ResultSet rs = preparedCount.executeQuery();
while (rs.next()) {
totalRows = rs.getInt("count(*)");
}
return totalRows;
} catch (SQLException ex) {
Logger.getLogger(TablePagingServiceJDBC.class.getName()).log(Level.SEVERE, null, ex);
}
return 0;
}
Or you can fork me on github at Project Page Table Paging on Swing :)
I have written a Java pagination tool dataj. It uses JQuery dataTables plug-in pagination metadata to build up the result page.
I have also added some client classes for Java Swing including a TableRowSorter that calls the (server side) sorting instead of sorting inside the table model.
Feel free to download it and contact me if you have any questions. It's under Apache 2 license.
Alternatively, you can make use of the QuickTable project.
Screenshot
Here is the DBTable component in action:
The DBTable component is embedded in a traditionnal JFrame.
Sample code
The following sample code produces the window shown in the previous screenshot:
import javax.swing.JFrame;
import javax.swing.UIManager;
import quick.dbtable.DBTable;
public class QuickTableFrame extends JFrame {
private static final long serialVersionUID = -631092023960707898L;
public QuickTableFrame() {
try {
// Use system look and feel
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
// set Frame properties
setSize(300, 200);
setVisible(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// create a new quicktable
DBTable dBTable1 = new DBTable();
// add to frame
getContentPane().add(dBTable1);
// set the database driver to be used, we are using jdbc-odbc driver
dBTable1.setDatabaseDriver("org.h2.Driver");
/*
* set the jdbc url,"quicktabledemo" is the data source we have
* created for the database
*/
dBTable1.setJdbcUrl("jdbc:h2:mem:test;INIT=create table employee as select * from CSVREAD('test.csv');");
// set the select statement which should be used by the table
dBTable1.setSelectSql("select * from employee");
// to create the navigation bars for the table
dBTable1.createControlPanel();
// connect to database & create a connection
dBTable1.connectDatabase();
// fetch the data from database to fill the table
dBTable1.refresh();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// create a new table frame
QuickTableFrame myframe = new QuickTableFrame();
}
}
Resources and dependencies
test.csv
empid,emp_name,emp_dept,emp_salary
1,Azalia,ornare,114918
2,Jade,tristique,152878
3,Willa,In scelerisque scelerisque,166733
...
H2
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.187</version>
</dependency>
References
QuickTable basic tutorial
QuickTable official tutorials
Download latest jar
h2 database

Categories