Solved

JTable data load /save method ,refreshing .....

Posted on 2000-05-05
22
1,923 Views
Last Modified: 2013-11-23
Hi,

I have to display data from servlet to Jtable and send the updated data if any back to servlet. The JTable is going to be really really big,atleast 20 columns by <god only knows how many> number of rows.

I have implemengted some of our look and feel requirements but am thinking about this all of the time and can't get it out of my mind!

Was thinking that if therfe are say 100,000 cells then send them first from servlet to GUI and then send the next 100,000 and so on.Am a bit unclear abt this but I am afraid of getting OutOfMemoryError

Please note that this whole process should be transparent to the GUI user ,they shouldn't know about it and the changed data has to be sent back to servlet.

So what is the best and most efficient way to do that? Any ideas ? Using DefaultTableModel's vector of vector is really appealing for ease of use but it is a memory hogger? I hope i get some really good advice.

Also how to update the cell data ,it is going to change in the order of atleast 1/2 secs or more ? should I use a thread for the Notifier using Observer pattern?

I will come and look on monday! have a nice weekend.

Thanks
0
Comment
Question by:mbormann
  • 13
  • 3
  • 2
  • +3
22 Comments
 
LVL 1

Expert Comment

by:yanchou
Comment Utility
Hi, Mbormann

There might be some ways around depending the enviroment. In worst scenario(unsigned applet, firewall, low-end client machine, Hight concurrency to  the same set of data), I will prefer to let JTableModel have the capability to interact with servlet to access the data at runtime page by page (200 rows per page fro example). It is not difficult to make  JTableModel a little more intelligent to do some cache work.

If the server has big RAM (which is very cheaper), you hold all data in server side. In this case, Server is actually the "JTableModel" which can service more than one GUI.

What you are working on seems to be a typical Intranet system which has high speed and no firewall problem. I will appreciate if you can tell me what is the typical reason why you chose servlet instead of RMI? (Even RMI can  be tunneled through the firewall).  

If the GUI need to reflect the data changes in server side, servlet would be big problem while RMI is piece of cake.

You might also conside the asynchronized communication (like JMS) which is great to brocadecase the high volum data.  
0
 

Expert Comment

by:Zappie021900
Comment Utility
Amit, let's chat a moment about the application.  You see, I'm having a hard time understanding what sort of application would expect the user to scroll through 5000 or more rows of data and change some here and there.

I don't think a user can possibly do that without missing some things.  So can you limit the number of rows to only the ones the user will change, or provide some sort of positioning to let the user move to a different part of the data?

Please, I'm very interested in this - I write GUI tools for a living, and this is the first time I've heard of someone needing to display thousands of rows of dynamic, interactive data.

Joe "Zappie" Pluta
www.java400.net
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
yanchou,

I do not have a say of what technology to go for.I would have loved to go for RMI but :(

Yes we have tremendously high speeds I never imagined that you can get such speeds,but in some cases we have firewalls.

Can you tell me how to cache data in JTable?

Zappie,
>>>I don't think a user can possibly do that without missing some things.  So can you limit the number of rows to only the ones the user will change, or provide some sort of positioning to let the user move to a different part of the data?

Picture this if u r a guy and u wanna know which boys are bad amongst all the boys in ur school ,first u check whether all OK and then u get to know who is bad and then u exclude the bad boys/girls ,they maybe anywhere in the rollcall right ?

Sorry if i am a bit unclear...
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
>>>I don't think a user can possibly do that without missing some things.  

We will be highlighting that this boy is bad in red so they can easily take action.
0
 

Expert Comment

by:Zappie021900
Comment Utility
There are any number of ways to reduce the size of the JTable requirement.  In your example, I would use the name as a positioning field.  By typing a letter, the JTable would position itself to the closest match.

Once you've decided how to do that, you can design a "virtual" JTable, that really only displays a single page of data.  Let's say you want to show 20 rows in your panel; you would make the JTable 22 rows long, and position it at the SECOND row.  Then, if the user tries to access the first row, you simply send the PREVIOUS 20 rows, and if the user tries to access row 22, you send the NEXT 20 rows.

Zappie
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
Zappie,
we r getting closer to the solution,does that mean that I listen for Scrolling? btw that also means sorting the 'name' field and implmeneting the index's sorting as is done in Windows help files.

>>>There are any number of ways to reduce the size of the JTable requirement.

Can you elaborate? I am new to professional GUI building ,mostly Server side till now.

i will try to contact u after some time say a week/2 weeks,am right now in N. Carolina.

Cheers
Amit
0
 
LVL 7

Expert Comment

by:vladi21
Comment Utility
Hello, Amit!

Sorry, I am very busy now.

Maybe these links can help:

http://java.sun.com/docs/books/tutorial/uiswing/components/table.html

http://manning.spindoczine.com/sbe/files/uts2/Chapter18html/Chapter18.htm
http://users.vnet.net/wwake/swing/faq.html#table
http://www.codeguru.com/java/Swing/JTable/index.shtml
http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/

and very good examples
http://www2.gol.com/users/tame/swing/examples/SwingExamples.html
   
---
How update JTable after I modify the data?
TableModel model=table.getModel();
if (model instanceof AbstractTableModel){
((AbstractTableModel)model).fireTableDataChanged();
}

or implemant your TableModel explicitly.

DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);

--
JTable highlight selected cells
http://www.experts-exchange.com/jsp/qShow.jsp?ta=java&qid=10219262

----
I have JTable in a GUI and a button to save the data in the table to a database. The JTable's view and model are separate. When I do a save, the data in the last cell which I edited is lost.

Only if I change the focus to a different cell or if I press ENTER key, it fires an event to update the cell (i.e. it calls the "setValue" method in the data model). Without this, how can I fire an event to update the data in the cell.

if (isEditing()) myDefaultCellEditor.stopCellEditing();
or
if (isEditing()) getDefaultEditor(String.class).stopCellEditing();

---
How can I clear data entered into a JTable?
http://developer.java.sun.com/developer/qow/archive/23/index.html
http://developer.java.sun.com/developer/qow/archive/archive.html

http://java.sun.com/products/jdk/1.3/docs/guide/swing/JTableChanges.html
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
thanks Vlad
0
 
LVL 1

Expert Comment

by:yanchou
Comment Utility
Hi, mbormann

The reason I talked about RMI vs. servlet is because you said....
>>...send them first from servlet to

So I assumed you are using Http. Http is perfect for C2B, B2B, Inernet Application, but Http is not reliable, low performance. I don't think it is good idea to send <god only knows how many> number of rows.

Supposed we define a page as 100 rows, and the GUI is displaying the n th page. The JTableModel will hold the data for the n-1, n, n+1 pages. When user scroll down, the GUI will display the n+1 page. At this time, JTableModel can run a thread to access data  which fits in the N+2 window from server before user is scroll to it.

In the real world, you can make the JTableModel more intelligent so the user have a smother user interface.

 
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
yes I agree HTTP is not good for hi volume but is portable no ? and thanks for the input ,i will have hopefully learnt something and will let u all know abt it in some time.
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
Can you help me to add a row to a JTable ,I am not getting to add a row dynamically to a JTable ,I will post some code here tommorrow.

Am using my own TableModel wherein the rows are held by a Vctor and each Column data is a element inside it.

I checked and double checked that th size of Vector increases ,the getValueAt(r,c) gives me that the elements are added and I think (?) that I have fired the appropriate fireTableRowsInserted() ,hope you are able to help me.

Thanks
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 16

Expert Comment

by:heyhey_
Comment Utility
well - post the code :)
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
here is code tahnks ,
the code is in 7 files and am posting in enitrity

html


<html>
<applet
code = "GuiScreen.class"  width=800 height=500>
</applet>
</html>

Jacva

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.border.*;
import java.lang.reflect.*;

public class ActualModel extends AbstractTableModel {

      public ActualModel() {
            data=new Vector(193,193);
    }

      /**
       * Add a single row with column data.
       * @param columns The raw column data
       */
      public void addRow(Object []columns) {

            System.out.println("inside just data.size()"+data.size());
            if(columns.length != getColumnCount()) {
                  throw new IllegalArgumentException("The length of the columns array is incorrect.");
            }
/*
            for(int i=columns.length;--i>=0;) {
                  if(!(columns[i] instanceof java.lang.Comparable)) {
                        throw new Exception("The data for one or more columns is not an instance of Comparable");
                  }
            }
*/            data.addElement(columns);
            System.out.println("data.size()"+data.size());
            System.out.println("data rows"+this.getRowCount());
            for(int i=0;i<data.size();i++) {
                  System.out.println("'"+this.getValueAt(i,0)+"'");
                  System.out.println("'"+this.getValueAt(i,1)+"'");
            }            
            
            //this.fireTableRowsInserted(data.size()-1,data.size()-1);
            //this.fireTableStructureChanged();
            fireTableChanged(new TableModelEvent(this, getRowCount()-1, getRowCount()-1,
                             TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
      }
      
      /**
       * Delete a single Indexed row.
       * @param index The index of row to delete
       */
      public void delRow(int index) {
            
            if(index<0 || index>data.size())
                  throw new IllegalArgumentException("The index of the given row is incorrect.");
      
            data.removeElementAt(index);
            this.fireTableRowsDeleted(index,index);
      }

      /**
       * Append a single row at the end so that user should edit and fill in the cell data.
       */
      public void grow() {
            data.addElement(new Object[getColumnCount()]);
            this.fireTableRowsInserted(data.size()-1,data.size()-1);
      }
      
      /**
       * Deletes a single row at the end.
       */
      public void shrink() {
            data.removeElementAt(data.size()-1);
            this.fireTableRowsDeleted(data.size(),data.size());
      }

      /**
       * Add a bunch of rows with column data.
       * @param columns The raw row+column data
       */
      public void addRows(Object [][]rawData) {

            int oldDataSize=data.size();
            
            if(rawData != null) {
                  if(rawData[0].length != getColumnCount()) {
                        throw new IllegalArgumentException("The length of the columns array is incorrect.");
                  }
            }

            // Make a check only once if all column data is Comparable,cry otherwise
/*            
            Object [] oneColumn = rawData[0];
            
            for(int i=oneColumn.length;--i>=0;) {
                  if(!(oneColumn[i] instanceof java.lang.Comparable)) {
                        throw new Exception("The data for one or more columns is not an instance of Comparable");
                  }
            }
*/
            int len=rawData.length;
            
            //for(int i=len;--i>=0;)
            for(int i=0;i<len;i++)
                  data.addElement(rawData[i]);

            System.out.println(oldDataSize);
            System.out.println(data.size()-1);
            
            this.fireTableRowsInserted(oldDataSize,data.size()-1);
      }

      public void addRows(Vector rawData) {

            int oldDataSize=data.size();
            
            if(rawData != null) {
                  if(((Object [])rawData.elementAt(0)).length != getColumnCount()) {
                        throw new IllegalArgumentException("The length of the columns array is incorrect.");
                  }
            }
            
            int len=rawData.size();
            
            for(int i=0;i<len;i++)
                  data.addElement(rawData.elementAt(i));

            System.out.println(oldDataSize);
            System.out.println(data.size()-1);
            
            this.fireTableRowsInserted(oldDataSize,data.size()-1);
      }

      public Vector getRows() {
            return (Vector)data.clone();
      }
      /**
       * Mutator for the column names
       */
      public void setColumns(String []cols) {
            if(columnNames != null) {
                  this.columnNames = cols;
            }

            this.fireTableStructureChanged();
      }
      
      /**
       * Accessor for the column names
       */
      public Object[]getColumns() {
            return (Object [])columnNames.clone();
      }
      
      // The methods to implement our model
    public int getColumnCount() {
        return columnNames.length;
    }
      
      public String getColumnName(int columnIndex) {
            if(columnIndex<0 || columnIndex>columnNames.length)
                  throw new IllegalArgumentException("The index for column name is incorrect.");
            
            return columnNames[columnIndex];
      }

    public int getRowCount() {

            return data.size();
    }

    public Object getValueAt(int row, int col) {            
            return ((Object [])data.elementAt(row))[col];
      }
      
    public void setValueAt(Object o,int row, int col) {
            ((Object [])data.elementAt(row))[col]=o;      }
      protected String[] columnNames;    
      protected Vector data;
}






import javax.swing.*;
import javax.swing.event.*;

public class TableRowHandler implements ListSelectionListener {
      public void valueChanged(ListSelectionEvent e) {
   
            System.out.println();
            
            int firstIndex = e.getFirstIndex();
            int lastIndex = e.getLastIndex();
            boolean isAdjusting = e.getValueIsAdjusting();
                                          
            ListSelectionModel lsm = (ListSelectionModel)e.getSource();
            if (lsm.isSelectionEmpty()) {
                  System.out.println("No rows are selected.");
            }
            else {
                  int minIndex = lsm.getMinSelectionIndex();
                  int maxIndex = lsm.getMaxSelectionIndex();

                  // Find out exactly which indexes are selected.
                  for (int i = minIndex;i<=maxIndex;i++) {
                        if (lsm.isSelectedIndex(i)) {
                              System.out.println("Row " + i);
                        }
                  }                    
            }
      }
}






import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.border.*;
import java.lang.reflect.*;

/*
 * If any data is changed fire the appropriate event and the Model will
 * automatically render the GUI.
 */
public final class SortFilterModel extends AbstractTableModel {
   
      public SortFilterModel(ActualModel m) {
            model = m;
            rows = new Row[model.getRowCount()];

            for (int i = rows.length; --i >= 0 ;) {
                rows[i] = new Row();
                rows[i].index = i;
            }
    }

    public void sort(int c) {    
            computeRows();
            System.out.println();
            sortColumn = c;
        Arrays.sort(rows);
        model.fireTableDataChanged();
    }

    public void addMouseListener(final JTable table) {
        table.getTableHeader().addMouseListener(new MouseAdapter() {
                                                    public void mouseClicked(MouseEvent event) {  

                                                                                    // find column of click and
                                                        int tableColumn
                                                        = table.columnAtPoint(event.getPoint());

                                                        // translate to table model index and sort
                                                        int modelColumn
                                                        = table.convertColumnIndexToModel(tableColumn);
                                                       
                                                                                    sort(modelColumn);
                                                    }
                                                }
                                               );
    }

      /* compute the moved row for the three methods that access
       model elements
    */
    public Object getValueAt(int r, int c) {
        return model.getValueAt(rows[r].index, c);
    }

    public boolean isCellEditable(int r, int c) {
        return false;
    }

    public void setValueAt(Object aValue, int r, int c) {
        model.setValueAt(aValue, rows[r].index, c);

            model.fireTableCellUpdated(r,c);            
    }

    /* delegate all remaining methods to the model
    */
    public int getRowCount() {
        return model.getRowCount();
    }

    public int getColumnCount() {
        return model.getColumnCount();
    }

      public void addRows(Vector v) {
            model.addRows(v);
            computeRows();
      }

      public void addRows(Object[][] v) {
            model.addRows(v);
            computeRows();
      }

      public void addRow(Object[] v) {
            System.out.println("befor rows.length"+rows.length);
            model.addRow(v);
            computeRows();
            System.out.println("after rows.length"+rows.length);
      }
    public String getColumnName(int c) {
        return model.getColumnName(c);
    }

    /* this inner class holds the index of the model row
       Rows are compared by looking at the model row entries
       in the sort column
    */

      private final void computeRows() {
            if( !(rows != null && rows.length == model.getRowCount()) ) {

                  System.out.println("Inside new Row()");
                  rows = new Row[model.getRowCount()];

                  for (int i = rows.length; --i >= 0 ;) {
                      rows[i] = new Row();
                      rows[i].index = i;
                  }
            }
      }
    private class Row implements Comparable {
        public int index;
        public int compareTo(Object other) {
            Row otherRow = (Row)other;
            Object a = model.getValueAt(index, sortColumn);
            Object b = model.getValueAt(otherRow.index, sortColumn);
//            if (a instanceof Comparable)
                return ((Comparable)a).compareTo(b);
//            else
//                return index - otherRow.index;
        }
    }
      
      private ActualModel model;
    private int sortColumn;
    private Row[] rows;
}







import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.border.*;

import java.lang.reflect.*;
import java.util.*;
import java.io.*;


public class Screen1 extends JPanel implements ActionListener {

      public Screen1() {
            
            this.setLayout(new BorderLayout());
            
            model1 = new AModel();
        model2 = new AModel();
            
            model1.addRows(AModel.DUMMY_addRows());
            // Note add the ROWS TO THE MODEL BEFORE INSTANTIATING sorter
            
            SortFilterModel sorter1 = new SortFilterModel(model1);            
        SortFilterModel sorter2 = new SortFilterModel(model2);

        table1 = new JTable();
            table2 = new JTable();
            
            // allow user to select using CTRL / SHIFT Keys
            table1.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
            table2.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
            
            table1.getSelectionModel().addListSelectionListener(new TableRowHandler());
            table2.getSelectionModel().addListSelectionListener(new TableRowHandler());
       
            table1.setModel(sorter1);
            table2.setModel(sorter2);
            
            // set the spacing between 2 adjacent columns,default is 1
            table1.getColumnModel().setColumnMargin(5);
            table2.getColumnModel().setColumnMargin(5);
            
            //don't allow the user to reorder columns in JTable
            table1.getTableHeader().setReorderingAllowed(false);
            table2.getTableHeader().setReorderingAllowed(false);
            
            // set the width of the columns,
            // NOTE this part of code needs to be updated if you add more number of columns
            
            TableColumn device1 = table1.getColumn(model1.getColumnName(AModel.COL_NAME ));
            TableColumn interfaces1 = table1.getColumn(model1.getColumnName(AModel.COL_SURNAME ));
            TableColumn device2 = table2.getColumn(model2.getColumnName(AModel.COL_NAME ));
            TableColumn interfaces2 = table2.getColumn(model2.getColumnName(AModel.COL_SURNAME ));
            
            int deviceWidth1 = TableUtilities.getPrefferedWidthForColumn(table1,device1);
            int interfaceWidth1 = TableUtilities.getPrefferedWidthForColumn(table1,interfaces1);
            int deviceWidth2 = TableUtilities.getPrefferedWidthForColumn(table2,device2);
            int interfaceWidth2 = TableUtilities.getPrefferedWidthForColumn(table2,interfaces2);
            
            device1.setMinWidth(deviceWidth1);
            interfaces1.setMinWidth(interfaceWidth1);
            device2.setMinWidth(deviceWidth2);
            interfaces2.setMinWidth(interfaceWidth2);
            
            // coz of a swing bug
            table1.sizeColumnsToFit(0);
            table2.sizeColumnsToFit(0);

            TableUtilities.setToolTipForColHeader(table1,device1,"Name");
            TableUtilities.setToolTipForColHeader(table1,interfaces1,"Surname");
            TableUtilities.setToolTipForColHeader(table2,device2,"Name");
            TableUtilities.setToolTipForColHeader(table2,interfaces2,"Surname");
                        
            // set up single click sort handler for column headers
        sorter1.addMouseListener(table1);
            sorter2.addMouseListener(table2);

            // actionListeners for all buttons
            b_add.addActionListener(this);
            b_addAll.addActionListener(this);
            b_remove.addActionListener(this);
            b_removeAll.addActionListener(this);
            
            GridBagLayout gbl = new GridBagLayout();
            GridBagConstraints gbc = new GridBagConstraints();

            JPanel top = new JPanel();
            top.setLayout(gbl);
            
            //1
            gbc.weightx = 0.5;
            gbc.weighty = 1.0;
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.gridwidth = 1;
            gbc.gridheight = 4;
            gbc.insets = new Insets(0,0,0,0);
            gbc.fill = GridBagConstraints.BOTH;
            gbc.anchor = GridBagConstraints.CENTER;
            JScrollPane js1 = new JScrollPane(table1,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            add(top,js1,gbl,gbc);

            //2
            gbc.weightx = 0.5;
            gbc.weighty = 1.0;
            gbc.gridx = 2;
            gbc.gridy = 0;
            gbc.gridwidth = 1;
            gbc.gridheight = 4;
            gbc.insets = new Insets(0,0,0,0);
            gbc.fill = GridBagConstraints.BOTH;
            gbc.anchor = GridBagConstraints.CENTER;
            JScrollPane js2 = new JScrollPane(table2,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            add(top,js2,gbl,gbc);

            //3
            gbc.weightx = 0.0;
            gbc.weighty = 0.5;
            gbc.gridx = 1;
            gbc.gridy = 0;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            gbc.insets = new Insets(2,4,2,4);
            gbc.fill = GridBagConstraints.NONE;
            gbc.anchor = GridBagConstraints.SOUTH;
            add(top,this.b_add,gbl,gbc);

            //4
            gbc.weightx = 0.0;
            gbc.weighty = 0.5;
            gbc.gridx = 1;
            gbc.gridy = 1;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            gbc.insets = new Insets(2,4,2,4);
            gbc.fill = GridBagConstraints.NONE;
            gbc.anchor = GridBagConstraints.NORTH;
            add(top,this.b_addAll,gbl,gbc);
            
            //5
            gbc.weightx = 0.0;
            gbc.weighty = 0.5;
            gbc.gridx = 1;
            gbc.gridy = 2;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            gbc.insets = new Insets(2,4,2,4);
            gbc.fill = GridBagConstraints.NONE;
            gbc.anchor = GridBagConstraints.SOUTH;
            add(top,this.b_remove,gbl,gbc);

            //6
            gbc.weightx = 0.0;
            gbc.weighty = 0.5;
            gbc.gridx = 1;
            gbc.gridy = 3;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            gbc.insets = new Insets(2,4,2,4);
            gbc.fill = GridBagConstraints.NONE;
            gbc.anchor = GridBagConstraints.NORTH;
            add(top,this.b_removeAll,gbl,gbc);
                  
            this.add(top,BorderLayout.CENTER);

            JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER));
            buttons.add(b_back);
            buttons.add(b_next);
            
            this.add(buttons,BorderLayout.SOUTH);

            System.out.print("\nThe JTable has '"+table1.getRowCount()+ "' rows ");
            System.out.println("and '"+table1.getColumnCount()+ "' columns.");
            //System.out.println("The class has these fields\n" +TableUtilities.toString(this));
            setVisible(true);
      }
      
      /**
       * This is a utility method to add a component to the Container using
       * GridBagLayout
       */
      
      public final void add(Container container,Component comp,GridBagLayout gbl,GridBagConstraints gbc) {
            // defaults
            gbc.ipadx = 0;
            gbc.ipady = 0;
            
            gbl.setConstraints(comp,gbc);
            container.add(comp);
      }
      
      public void actionPerformed(ActionEvent e) {

            Object evtGen = e.getSource();
            
            // Next button/Tab change should fire off the data in second Jtable to backend
            if(evtGen == b_next) {
                  
                  //this code below is dummy for demo only,replace with real thing later
                  System.out.println("The data is :\n\n\n");

                  int x = table2.getColumnCount();
                  int y = table2.getRowCount();
      
                  ListSelectionModel lsm = table2.getSelectionModel();
                        
                  for(int i=y;--i>=0;) {
                        if(lsm.isSelectedIndex(i)) {
                              for(int j=x;--j>=0;) {
                                    Object o = table2.getValueAt(i,j);
                                    System.out.println("["+i+"]["+j+"]\t= '"+o +"'");
                              }
                        }
                  }
            }
            
            // Back button
            if(evtGen == b_back) {                  
                  System.out.println("Back clicked ...");
            }

            //add button
            if(evtGen == b_add) {
                  
                  System.out.println("add clicked ...");
                  
                  
                  ListSelectionModel lsm = table1.getSelectionModel();
                  int min = lsm.getMinSelectionIndex();
                  int max = lsm.getMaxSelectionIndex();
                  
                  System.out.println("min='"+min+"'");
                  System.out.println("max='"+max+"'");
                  
                  lsm.setSelectionInterval(min,max);
                  int x = table1.getColumnCount();
                  Object []oo=null;

                  for(int i=min;i<=max;i++) {
                        if(lsm.isSelectedIndex(i)) {
                              oo=new Object[2];
                              for(int j=0;j<x;j++) {
                                    oo[j]=table1.getValueAt(i,j);
                                    System.out.println("["+i+"]["+j+"]\t= '"+oo[j] +"'");
                              }
                              
                              //v.addElement(oo);
                        }
                  }
                  
                  SortFilterModel sorter2 = (SortFilterModel)table2.getModel();
                  sorter2.addRow(oo);
                  
                  // Is repaint() necessary for large JTable size ? Have to investigate.                  
                  this.table2.repaint();
            }
            
            // add All button
            if(evtGen == b_addAll) {
                  
                  System.out.println("add all clicked ...");
                  ListSelectionModel lsm = table1.getSelectionModel();
                  System.out.println("table1.getRowCount()='"+table1.getRowCount()+"'");
                  lsm.setSelectionInterval(0,table1.getRowCount()-1);
                  
                  SortFilterModel sorter2 = (SortFilterModel)table1.getModel();
                  sorter2.addRows(model1.getRows());
                  
                  // Is repaint() necessary for large JTable size ? Have to investigate.                  
                  this.table2.repaint();
            }
      }

      public static final String ADD = "Add >>";
      public static final String REMOVE = "<< Remove";
      public static final String BACK = "Back";
      public static final String NEXT = "Next";
      public static final String ADDALL = "Add All >>";
      public static final String REMOVEALL = "<< Remove All";

      private JTable table1;
      private JTable table2;
      
      private JButton b_add = new JButton(ADD);
      private JButton b_remove = new JButton(REMOVE);
      private JButton b_back = new JButton(BACK);
      private JButton b_next = new JButton(NEXT);
      private JButton b_addAll = new JButton(ADDALL);
      private JButton b_removeAll = new JButton(REMOVEALL);
      private AModel model1;
      private AModel model2;
}








import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class GuiScreen extends JApplet {

      public void init() {
            try {
                  UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
            }
            catch(Exception e) {
            }
            Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
            // fill up whole monitor screen
            //this.setSize(dim.width-25,dim.height-75);
            this.setSize(600,400);

            Container contentPane = getContentPane();
            JTabbedPane tp = new JTabbedPane();

            Screen1 routers = new Screen1();
            JPanel switches = new JPanel();

            tp.setSize(885,665);
            tp.add(routers, "Tab 1");
            tp.add(switches,"Tab 2");

            contentPane.setLayout(new GridLayout(1,1));
            contentPane.add(tp);

            tp.addChangeListener(new ChangeListener() {
                  public void stateChanged(ChangeEvent e) {
                        
                        JTabbedPane tabbedPane = (JTabbedPane)e.getSource();
                        int index = tabbedPane.getSelectedIndex();
                        String s = tabbedPane.getTitleAt(index);
                        showStatus("'"+s + "' selected");
                  }
            });
      }
}









public class AModel extends ActualModel {

      public AModel() {
            this.columnNames = new String[2];
            this.columnNames[0] = "Name";
            this.columnNames[1] = "Surname";
      }

      public static Object[][] DUMMY_addRows() {
            return ddd;
      }
      private static Object [][] ddd = {
                                             {"John","Doe"},
                                                {"Mika","Hakinnen"},
                                             {"Joe","Black"}};
      
      public static final int COL_NAME = 0;
      public static final int COL_SURNAME = 1;
}








/**
 * @version 1.00 05-04-2000
 */
import java.lang.reflect.*;
import java.awt.*;

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

/*
 * Please note that when traversing a loop the fastest platform independent way to go is
 *
 * for(int i=some int; --i >= 0;) { //..... }
 */

public class TableUtilities {

      /**
       * This is a utility method for setting the tooltip for a Column Header in a JTable.
       *
       */

      public static final void setToolTipForColHeader(JTable table,TableColumn colHdr,String text) {
            TableCellRenderer colRenderer = colHdr.getHeaderRenderer();
            
            Component comp = colRenderer.getTableCellRendererComponent(table,colHdr.getHeaderValue(),false,false,0,0);
            
            if(comp instanceof JComponent) {
                  ((JComponent)comp).setToolTipText(text);
            }
      }
      
      
      /**
       * These are a set of utility methods for calculating the actual
       * preferred width for a column in a JTable.
       *
       */
      
      public static final int getPrefferedWidthForColumn(JTable table,TableColumn col) {
            
            int headerWidth = columnHeaderWidth(table,col);
            int columnWidth = widestCellInColumn(table,col);
            
            return headerWidth > columnWidth ? headerWidth : columnWidth;
      }
      
      private static final int columnHeaderWidth(JTable table,TableColumn col) {
            
            TableCellRenderer renderer = col.getHeaderRenderer();
            
            Component comp = renderer.getTableCellRendererComponent(table,col.getHeaderValue(),false,false,0,0);
            
            return comp.getPreferredSize().width;
      }

      private static final int widestCellInColumn(JTable table,TableColumn col) {
      
            int c = col.getModelIndex() , width=0,maxw=0;
            
            for(int r=table.getRowCount();--r>=0;) {
                  TableCellRenderer renderer = table.getCellRenderer(r,c);
                  
                  Component comp = renderer.getTableCellRendererComponent(table,table.getValueAt(r,c),false,false,r,c);
                  width = comp.getPreferredSize().width;
                  maxw = width > maxw ? width : maxw;
            }
            
            return maxw;
      }
      
      /**
       * These are another set of utility methods which set the row height to
       * the height of the tallest cell in the given row in a JTable.
       *
       */
      
      public static final int getMaxRowHeight(JTable table) {
            int columnCount = table.getColumnCount(), h=0, maxh=0;

            for(int i=columnCount;--i>=0;) {
                  TableColumn column = table.getColumnModel().getColumn(i);
                  h = getMaxRowHeightForColumn(table,column);
                  maxh = Math.max(h,maxh);
            }
            return maxh;
      }
      
      private static final int getMaxRowHeightForColumn(JTable table,TableColumn column) {
            int height = 0, maxh = 0, c = column.getModelIndex();

            for(int r=table.getRowCount(); --r>=0;) {
                  TableCellRenderer renderer = table.getCellRenderer(r,c);      
                  
                  Component comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r,c),false, false, r, c);

                  height = comp.getMaximumSize().height;
                  maxh = height > maxh ? height : maxh;
            }
            return maxh;
      }

      /**
       * This is a utility method which is to be used for debugging.
       *
       */
    public static final String toString(Object obj) {
            Class cl = obj.getClass();
            StringBuffer r = new StringBuffer(cl.getName() + "[");
            Class sc = cl.getSuperclass();
            if (!sc.equals(Object.class))
                  r.append(sc + ",");
            
            Field[] fields = cl.getDeclaredFields();
            try {
                  AccessibleObject.setAccessible(fields, true);
            }
            catch(SecurityException e) {//e.printStackTrace();
            }
            catch(Exception e) {//e.printStackTrace();
            }
            
            for (int i = fields.length; --i >= 0 ;) {
                  Field f = fields[i];
                  r.append(f.getName() + "=");
               
                  try {
                        r.append(f.get(obj).toString());
                  }
                  catch (IllegalAccessException e) {
                        //e.printStackTrace();
                        r.append("???");
                }
                  catch (NullPointerException e) {
                        r.append("null");
                  }
                  catch(Exception e) {//e.printStackTrace();
                  }
               
                  if (i < fields.length - 1)
                        r.append("\n\n"); //","
                  else
                        r.append("]");
            }
            
            return r.toString();
    }
}
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
I also had teh sorter inside one class but I cant seem to sort the rows by clikcing on 1 of the colummns ,probably I am trying to do too many things at omce.

Can anybody suggest a way of integarting the Sorting and which method to use inside the one single tableModel.

and what is the better way of doing this data? I dont want to go for DefaultTableModel as it will cause us problems later on.

Any general suggestions are welcome and i will gladly use them !

Thanks
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
hey now i am able to add the Row!

the only change I made was to fire tableChanged on the 2nd JTable instead of

fireTableChanged(new TableModelEvent(this, getRowCount()-1, getRowCount()-1,
                             TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));

Thanks but can you guys suggest a better design ?
0
 
LVL 5

Expert Comment

by:Jod
Comment Utility
Found it now mb...lots of code though :)

I can answer regarding the data handling as that is pretty straight forward and also mentioned above.

Basically you need to make a viewport onto your data. If you imagine all the data you are displaying as a huge list then the data you are actually displaying on screen can only be a small amount of this.

You need to check out what is a reaonable size for your client side cache. With such a large amount of data you may want to work with more than just a page of data because if people scroll up and down quickly then the system will be creating a lot of overhead for itself resending or re-querying the database.

You do need to monitor where the user is in your recordset - then as they move through the data then you can always have a set number of records both before and after their current position based on your optimi

You can often do this in most databases by monitoring the row_id number. This is a number that the database adds like a virtual column to each row that tells you for any particular query how far into the recordset you are.

So for example,

SELECT * from xyz where row_id < 100

will get you ONLY the first 100 records from your query.

Your database needs to support this but most databases do. Decent ones anyway.

Make this subset of the data your cache and then monitor whn you need to update it. It is best to avoid updating the cahce every time the user moves up or down a row or a page unless the data is out of date.

As for the rest of it I will have a look but I think heyhey is your man here for JTable fiddling...
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
Thanks for the suggestion ,there are many guys who helped me here ,will have to shell out mo money.
:)

yanchou also suggested this (I also said the same to somebdoy here after a freidn also said the same row ID thign to me)

But I am not sure how to do this exactly we use Sybase and Oracle ,Oracle suports this but Sybase will have to cjheck out ,I will go ahead and do the whole list display for testers (they are breathing down our neck :) ),and later on in the beta we will try to integrate this caching.

heyhey_,

Jod is right ,I saw some questions of urs where u were fiddling with JTable a year or more back thanks to EE's cool new search feature.

I have a nagging question.

(1)what gets my goat is why does the fireXXX doesn't work ? I had to do some convoluted code like

model = new Model();
table = new JTable();
model.setJTableInstance(table);

so that I can use table.tableChanged() in the model.

please tell me somebdy as I had been banging my head against the wall for 2/3 days.
0
 
LVL 5

Accepted Solution

by:
Jod earned 200 total points
Comment Utility
As regards the view on the data I would do it like this:

have one variable for the start of your data range and one for the end.

Then when you select data from the database, always append to the where clause your row_id like this:

SELECT * from xyz where row_id >= [bottom] AND row_id < [top];

You now monitor the current row the user is on in this range and when they get near to one end or the other you get some more data.

So if you get 1000 records to start with then you have bottom = 1 and top = 1000.

When the user gets to perhaps row 700 then chnge your range to get rows 200 to 1200.

The balance is to get enough rows in one go but not slow the system down too much when you re-issue the query.
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
guys I seem to have resolved most of issues and as i may need your help weeks later am closing this question but pls monitor it for ur comments!

I feel that yanchou helped with the glimering of an idea which was finally put into place by Jod.

And excellent links from vladi21

am posting question for
yanchou at
http://www.experts-exchange.com/jsp/qShow.jsp?ta=java&qid=10351381

and vladi21 at http://www.experts-exchange.com/jsp/qShow.jsp?ta=java&qid=10351383

pls forgive me as I have to conserve points for later on :)
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
guys I seem to have resolved most of issues and as i may need your help weeks later am closing this question but pls monitor it for ur comments!

I feel that yanchou helped with the glimering of an idea which was finally put into place by Jod.

And excellent links from vladi21

am posting question for
yanchou at
http://www.experts-exchange.com/jsp/qShow.jsp?ta=java&qid=10351381

and vladi21 at http://www.experts-exchange.com/jsp/qShow.jsp?ta=java&qid=10351383

pls forgive me as I have to conserve points for later on :)
0
 
LVL 5

Expert Comment

by:Jod
Comment Utility
Cheers mb.

Tricky little buggers aren't they JTables...
0
 
LVL 5

Author Comment

by:mbormann
Comment Utility
you can say that again!
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now