tags:

views:

470

answers:

3

Hi all,

I'm new to JTable.I'm working in Swings using JTable & Toplink(JPA). I have two buttons "add Row", "Del Row" and I have some records displayed from db. when ever "add row" is clicked a new record, row header should be added to JTable with an auto increment number displayed in sequential order to the JTable Row Header.

During deletion using "Del row " button the record has to be deleted & not its corresponding header so that next rows got updated to the previous headers & the auto increment number remain unchanged and always be in sequence.

please help me on this regard.

Thanks in advance, Chandu

+1  A: 

As you are new to JTable, I'd start with How to Use Tables. As suggested there, I'd extend AbstractTableModel, overriding getValueAt(), setValueAt(), getRowCount(), etc. to use the corresponding JPA entity and controller classes and methods. The NetBeans IDE, for example, can generate such classes automatically. There is also a feature to bind the classes to Swing components, including JTable and JList, but I haven't tried it.

If the row id is an auto increment number managed by the database, I'm not sure there's a reliable way to maintain the appearance of sequential order in a multi-user environment. If the field is displayed at all, isCellEditable() should probably return false for that column. Is that what you mean by Row Header?

Addendum: See also What’s the best way get the ID of the item just inserted?

trashgod
A: 

Do you mean like this?

likeThis

When a new record is added its id is set as a row header ( as in records, 1,2,3 ) and when a record is deleted, the row header remains, but the information is gone ( as in records 4,5 which use to have data, but after being removed only leave the id )

IF that's what you mean.

What you have to do is create two table models, one wrapping the other.

  • The only functionality of the wrapper will be to show an extra column ( the id ) and keep an internal "copy" of the data.

  • When a row is added, the wrapper will get a new record, it will assign a new id and then it will take all the fields and copy the value into his own data and then will forward it to the wrapped table model.

  • When a row is removed, the wrapper will not remove its own record, it will only clean up ( set to "" ) the column values and will keep the id column. Then it will forward the event to the wrapped column which in turn will actually remove the row.

Something like the following noncompiling-java

 // Wrapper table model   
 class IdTableModel implements TableModelListener {
      TableModel original;

      // Analog to: Object[][]
      List<List<Object> data = new ArrayList<List<Object>();

      // will take a copy of the data in original
      public IdTableModel( TableModel original ) {
          this.original = original;
          // fillData with values from original
         for( int row = 0 ; row < original.getRowCount(); row++ ) {
              List<Object> shadowRow = new ArrayList<Object>();
              shadowRow.add( row ); // the id
              // copy the values from original to this shadow
              for( int column = 0 ; column < original.getColumnCount(); column++ ) {
                  shadowRow.add( original.getValueAt(row,i));
              }
              // add the shadow to the data
              data.add( shadowRow );
          }
          original.addTableModelListener( this );
      }

      // for Object getValueAt( x, y ) get the data from your "data" not from the original

       ....
       //Here's the magic. this wapper will be a listener of the original
       // then this method will be invoked when the original gets more data 
       // or when it is removed.....
       public void tableChanged( TableEvent e )  {
           int row = e.getFirstRow();
           List<Object> shadowRow = data.get( row);
           switch( e.getType() ) {
               case TableEvent.INSERT:
                    if( ( shadowRow =) == null )  {
                        // there wasn't shadow data at that position
                        data.add( ( shadowRow = new ArrayList<Object>()));
                     }
                     // takevalues from original 
                     shadowRow.add( row ); // the id
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.add( original.getValueAt(row,i));
                     }
               break;
               case TableEvent.UPDATE:
                      // similar to insert, but you don't create a new row        
                     // takevalues from original 
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.set( i+1, original.getValueAt(row,i));
                     }
               break;
               case TableEvent.DELETE:
                      // You don't delete your shadow rows, but just clean it up
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.set( i+1, "");
                     }

               break;

       } 


       // forward calls to the original
      public int getColumnCount(){
           return original.getColumnCount()+1;
      }
      public String getColumnName( int columnIndex ) {
          if( columnIndex == 0 ) {
              return "id";
           } else {
               return original.getColumnName( columnIndex -1 );
           }
       }

       // and so on for, isEditable etc. etc

 }

Well that was much more code that what I initially wanted.

The idea is to have a table model wrapper that adds that fictional id column for you and don't delete it, you just use it like this:

  JTable yourTable = new JTable( new IdTableModel( originalTableModel ));

If nothing of what I said make sense to you, start reading this: How to use tables

OscarRyz
Thanks Oscar, I'll try to do the same.
Chandu
Would those "row headers" properly work like headers? I.e. they shouldn't scroll horizontally. And the rendering is way off – I think they should at least remotely look like the column headers do. Could you provide a way for doing so?
Joey
@Johannes, Yes, it is possible. You have to take a look at the *rowheader* property of the JScrollPane. By default, when using a JScrollPane with a JTable this *row header* is empty, you could provide a custom component. More info here: http://java.sun.com/docs/books/tutorial/uiswing/components/scrollpane.html
OscarRyz
A: 

This page might be what you're looking for: http://www.chka.de/swing/table/row-headers/JTable.html

Gili