Link to home
Start Free TrialLog in
Avatar of Bourke
Bourke

asked on

Updating a Jtable

Hi,
  I have an app the main window is a JFrame and it has a JInternalFrame in it which is a search window with a Jtable.  When i enter my search criteria and hit a button
the Jtable is populated with the results.
I can highlight a row on the JTable and mouseclick which give me a popup menu
I choose one item from this menu and it displays say and update window(JInternalFrame) it allows me to update the details of the record in the Jtable I selected.
when I hit update on this window I want the JTable in the search window to automatically udpdate.  Has anyone any ideas?

thanks
V
Avatar of zzynx
zzynx
Flag of Belgium image

>> when I hit update on this window I want the JTable in the search window to automatically udpdate.
Just update the corresponding entry in the table model behind the JTable
...then on your tableModel call
       fireTableRowsUpdated(int firstRow, int lastRow);

e.g.

      fireTableRowsUpdated(4, 4);  // 4 being the index in the table of the selected and changed item

zzynx,
shouldnt MVC have that under control? Meaning: If we change a value in the model, the controler will notify the view about it? Or do we really need to call fireTableRowsUpdated?

I'v tried it, you dont need no  fireTableRowsUpdated call, if you are updating the values in the model. Thats the point of MVC.

TableModel tm = table.getModel();
tm.setValueAt("xxx", x, y); /// this will already make the view repaint the values
>> Meaning: If we change a value in the model, the controler will notify the view about it?
Correct.

>> Or do we really need to call fireTableRowsUpdated?
Depending.
If you use your own table model extending from AbstractTableModel you should use those calls inside your table model (e.g. in the setValue() function)
If you use your own table model extending from DefaultTableModel it is done by using e.g. addRow() & setValueAt()
>> tm.setValueAt("xxx", x, y); /// this will already make the view repaint the values
As I just told indeed.
Because by default a JTable uses the DefaultTableModel.

Don't know if the author uses his own table model or not.
If he does use the default one, then my first comment applies.
Sorry for the confusion introduced by my 2nd.
Avatar of Bourke
Bourke

ASKER

I use DefaultTableModel.

My prob. is that the table is in one class (Search JInternalFrame) and the
Update is in another class (Update JInternalFrame).

So how do I access the table model in the Search window? pass it
via the constructor of the Update window?

V (I'm a she :o) )
yourTableModel = (DefaultTableModel)yourTable.getModel();
Avatar of Bourke

ASKER

Sorry I still done understand?
My tablemodel is in a different class to where I am updating.
... then use

  yourTableModel.setValueAt(Object aValue, int row, int column);

e.g.

  yourTableModel.setValueAt("New String item", 0, 0);  // changes the item shown on the 1st row in the 1st column (assuming it's a String)
Avatar of Bourke

ASKER

Will I make it public and shared?
I was trying to say that if you have your JTable object (I guess you have it in the search window. If not you can pass it)
you can always get the table model behind it.
Replace
     JTable object
by
     JTable instance (=your table)
>> If not you can pass it
in the constructor or via a function you call on your search window:

  public void setTable(JTable theTable) {
     this.theTable = theTable;
  }
Sorry again. In the above replace "search window" by "update window" of course
:°/
Avatar of Bourke

ASKER

Hi,
 I passed the table in via the constructor and just wrote these two lines:
               
                DefaultTableModel dtm = (DefaultTableModel)table.getModel();
      dtm.setValueAt("Changed", selectedRow, 2);

selectedRow is also passed in via the constructor.
But nothing happens???

thanks
V
>> selectedRow is also passed in via the constructor.
Not needed. You can use
        table.getSelectedRow(); // Remark: returns -1 if no selected

>>But nothing happens???
Presumably because your table is not editable

Preparing some demo...
Avatar of Bourke

ASKER

this is what I have when constructing the table:
table = new JTable () {
      public boolean isCellEditable (int iRows, int iCols) {
      return false;      //Disable All Columns of Table.
      }
};

but I dont want people to be able to edit the rows by highlighting it I do that in
the update window.
Can I make the table editable for the length of time I want to change it
and then disable it again?

V
            
>>Can I make the table editable for the length of time I want to change it and then disable it again?
You could try:

table = new JTable () {
      public boolean isCellEditable (int iRows, int iCols) {
            return busyEditing;  // and busyEditing is a flag that is set true when the update window comes up and false when it is closed
      }
};

Don't know for sure if it will work, though.
/*
 * MyTableModel.java
 *
 */

import javax.swing.*;
import javax.swing.table.*;
import java.util.*;
/**
 *
 * @author  zzynx
 */
public class MyTableModel extends DefaultTableModel {
   
    List data; // a list of MyObject's
   
    private String[] columnNames = { "Column1", "Column2", "Column3" };
   
    /** Creates a new instance of MyTableModel */
    public MyTableModel(List d) {
        this.data = d;
    }
   
    public Object getTableObject(int index) {
        return data.get(index);
    }

    public void setColumnName(int index, String name) {
        if (index < columnNames.length)
            columnNames[index] = name;
    }
   
   public boolean isCellEditable(int row, int col) {
     return false;
   }
   
   public void addRow(MyTableObject object) {
       data.add(object);
       fireTableRowsInserted(data.size()-2, data.size()-2);
   }
   
   public void removeRow(int index) {
       data.remove(index);
       fireTableRowsDeleted(index, index);
   }

   public Class getColumnClass(int col) {
      return super.getColumnClass(col);
   }
   
   public int getRowCount() {
       return data==null ? 0 : data.size();
   }
   
    public int getColumnCount() {
        return columnNames.length;
    }
   
    public Object getValueAt(int row, int col) {
        if ( row < 0 || row >= data.size() ) return null;
        MyTableObject myObj = (MyTableObject) data.get(row);
        if (col==0)
            return myObj.getField1();
        else if (col==1)
            return myObj.getField2();
        else if (col==2)
            return myObj.getField3();
        else return null;
    }

    // not needed if not editable:
    public void setValueAt(Object value, int row, int col) {
        if ( row < 0 || row >= data.size() || col!=0 ) return;
        // only col=0 is editable (in this example)
        MyTableObject myObj = (MyTableObject) data.get(row);
        if (col==0)
            myObj.setField1( (String)value );
        else if (col==1)
            myObj.setField2( (String)value );
        else if (col==2)
            myObj.setField3( (String)value );
        fireTableCellUpdated(row, col);
    }
   
    public String getColumnName(int col) {
        return columnNames[col];
    }
}


/*
 * MyObject.java
 *
 */

/**
 *
 * @author  zzynx
 */
public class MyTableObject {
   
    private String field1 = "";
    private String field2 = "";
    private String field3 = "";

    /** Creates a new instance of MyTableObject */
    public MyTableObject() {
    }
    public MyTableObject(String f1, String f2, String f3) {
        field1 = f1;
        field2 = f2;
        field3 = f3;
    }

    public String getField1() { return field1; }
    public String getField2() { return field2; }
    public String getField3() { return field3; }
    public void setField1(String f1) { field1 = f1; }
    public void setField2(String f2) { field2 = f2; }
    public void setField3(String f3) { field3 = f3; }
}


/*
 * TableDemo.java
 *
 */

import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import java.util.List;
import java.awt.*;
import java.awt.event.*;
/**
 *
 * @author  zzynx
 */
public class TheTableDemo extends javax.swing.JFrame {
                           
    /** Creates new form TableDemo */
    public TheTableDemo() {
        initComponents();
        initTable();
    }
   
    private void initTable() {
        List data = new ArrayList();
        data.add( new MyTableObject("data1", "data2", "data3") );
        data.add( new MyTableObject("data2.1", "data2.2", "data2.3") );
        data.add( new MyTableObject("data3.1", "data3.2", "data3.3") );
        theTable.setModel(new MyTableModel(data));
    }
   
    private void initComponents() {
        jScrollPane1 = new javax.swing.JScrollPane();
        theTable = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        addButton = new javax.swing.JButton();
        deleteButton = new javax.swing.JButton();
        changeButton = new javax.swing.JButton();

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });

        jScrollPane1.setViewportView(theTable);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jPanel1.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        addButton.setText("Add");
        addButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButtonActionPerformed(evt);
            }
        });

        jPanel2.add(addButton);

        deleteButton.setText("Delete");
        deleteButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteButtonActionPerformed(evt);
            }
        });

        jPanel2.add(deleteButton);

        changeButton.setText("Change");
        changeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                changeButtonActionPerformed(evt);
            }
        });

        jPanel2.add(changeButton);

        jPanel1.add(jPanel2);

        getContentPane().add(jPanel1, java.awt.BorderLayout.SOUTH);

        pack();
    }

    private void changeButtonActionPerformed(java.awt.event.ActionEvent evt) {
        int selectedRow = theTable.getSelectedRow();
        if (selectedRow!=-1) {
            MyTableModel model = (MyTableModel)theTable.getModel();
            MyTableObject obj = (MyTableObject)model.getTableObject(selectedRow);
            obj.setField1("Changed");
            obj.setField2("Changed too");
            obj.setField3("Also changed...");
            model.fireTableRowsUpdated(selectedRow, selectedRow); // needed
        }
    }

    private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {
        if (theTable.getSelectedRow()!=-1)
            ((MyTableModel)theTable.getModel()).removeRow(
                theTable.getSelectedRow() );
    }

    private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
        ((MyTableModel)theTable.getModel()).addRow(
            new MyTableObject("aaaaa", "bbbbbb", "ccccc") );
    }
   
    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {
        System.exit(0);
    }
   
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (Exception e) {
            System.exit(0);
        }
       
        new TheTableDemo().show();
    }
   
    // Variables declaration - do not modify
    private javax.swing.JButton addButton;
    private javax.swing.JButton changeButton;
    private javax.swing.JButton deleteButton;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable theTable;
    // End of variables declaration
   
}


Run TheTableDemo.
Select an entry in the table and press "change".
I know the change isn't done in another window, but the idea to apply in that case is the just same.
Offline I go... Success.
Avatar of Bourke

ASKER

Hi,
 I've been trying to work with your code and what is happening is when I pass the JTable and I want to get the selected row using:
                     selectedRow = table.getSelectedRow();
it returns -1 when I have selected a row in the table.

I'm passing the table in via the contructor.
Avatar of Bourke

ASKER

Oh by the way thanks alot for all that code.
>> it returns -1 when I have selected a row in the table
Impossible.
Looks like you perform getSelectedRow() on "another JTable object".

Is it possible to post some relevant code?
>> Oh by the way thanks alot for all that code.
No problem.
I hope it gives you an idea of how (flexible it is) to work with a table model.
Avatar of Bourke

ASKER

Ok
This is in the update:

Constructor:
public UpdateBook(JComponent comp, String user, Connection con, String bookId, JTable table, int selectedRow){
            
            super("Update Book", false, true, false, true);
            
            this.con = con;
            this.user = user;
            this.comp = comp;
            this.table = table;
            this.selectedRow = selectedRow;
            
            comp.add(this);
            
            SetUpComponents();
            
            GetBookDetails(bookId);         
            
            
}

THis is when the Details have been updated:

JOptionPane.showMessageDialog(this, "Book has been updated successfully");
selectedRow = table.getSelectedRow();

JOptionPane.showMessageDialog(this, "Selected Row = " + selectedRow);
                              
if (selectedRow!=-1) {
          SearchTableModel model = (SearchTableModel)table.getModel();
          SearchTableObject obj =
                       (SearchTableObject)model.getTableObject (selectedRow);
          obj.setField1("Changed");
          obj.setField2("Changed too");
          obj.setField3("Also changed...");
           model.fireTableRowsUpdated(selectedRow, selectedRow); // needed
}

THis code is in the main Search page for the action on a popmenu on the jtable
       if(e.getActionCommand() == "Update"){
      if(selIndex == 0){
             UpdateBook updateBook = new UpdateBook                  
                       (this.theDesktop,this.user, this.con,
                       rowRecBk[selectedRow][0], table,selectedRow);
            
                       updateBook.show();
                        
      }
       }

                              
Just a remark:

Replace
>> if(e.getActionCommand() == "Update"){
by
      if(e.getActionCommand().equals("Update")) {

That's safer.
Run this snippet and see why:

        // Don't compare Strings by using ==
        // Use equals() instead
        StringBuffer buf1 = new StringBuffer("Hello");
        StringBuffer buf2 = new StringBuffer("Hello");
        String myStr1 = buf1.toString();
        String myStr2 = buf2.toString();
        if (myStr1 == myStr2)
            System.out.println("1) equal");
        else
            System.out.println("1) not equal");
        if (myStr1.equals(myStr2))
            System.out.println("2) equal");
        else
            System.out.println("2) not equal");
>>THis code is in the main Search page for the action on a popmenu on the jtable
>>       if(e.getActionCommand() == "Update"){
>>     if(selIndex == 0){
>>            UpdateBook updateBook = new UpdateBook                  
>>                       (this.theDesktop,this.user, this.con,
>>                       rowRecBk[selectedRow][0], table,selectedRow);   // <<<<<<<<<<
>>           
>>                       updateBook.show();
>>                   
>>     }
>>       }

Is "selectedRow" OK (I mean !=-1) at the marked line of code?
How is it determined? As table.getSelectedRow()?

Than table.getSelectedRow() should be !=-1 inside the function too.


>>THis is when the Details have been updated:
>>JOptionPane.showMessageDialog(this, "Book has been updated successfully");
>>selectedRow = table.getSelectedRow();

Is this code part of the Search window code or the update window code?
You should be aware of the fact that the selection is gone if you reset the table's model.
Avatar of Bourke

ASKER

>Is "selectedRow" OK (I mean !=-1) at the marked line of code?this is the code ?
it is 1 at this point

in the main search page that I use to get the selectedRow

ListSelectionModel rowSM = table.getSelectionModel();
          rowSM.addListSelectionListener(new ListSelectionListener(){
           public void valueChanged(ListSelectionEvent e) {
          ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                  if (!lsm.isSelectionEmpty()) {
                         selectedRow = lsm.getMinSelectionIndex();
                        
                      }
          }
 });


>>THis is when the Details have been updated:
>>JOptionPane.showMessageDialog(this, "Book has been updated successfully");
>>selectedRow = table.getSelectedRow();

This is part of the update window code.
>> it is 1 at this point
Then table.getSelectedRow() should be 1 inside the update window code too.

>>THis is when the Details have been updated
Why do you need the selected row *after* the details have been updated?
I would say you need the selected row to determine which item to update...
Avatar of Bourke

ASKER

>>Then table.getSelectedRow() should be 1 inside the update window code too.
Yes, but for some reason it's -1 and I did a message box for both and they were different.

This is the constructor for the update window.

UpdateBook(JComponent comp, String user, Connection con, String bookId, JTable table, int selectedRow)

I use the bookId to bring up all the book details and then I can change them.
So when I hit the update button on the update window it updates the database.
I then get the rowSelected again to update the JTable in the Search window.

Does this make sense to you?
>> Yes, but for some reason it's -1
Impossible.
Try this in the constructor:

public UpdateBook(JComponent comp, String user, Connection con, String bookId, JTable table, int selectedRow){
         
          super("Update Book", false, true, false, true);
         
          this.con = con;
          this.user = user;
          this.comp = comp;
          this.table = table;

          System.out.println("a) Selected row: " + table.getSelectedRow());  // <<<<<<<<<<<<

          this.selectedRow = selectedRow;

          System.out.println("b) Selected row: " + selectedRow);  // <<<<<<<<<<<<
         
          comp.add(this);
         
          SetUpComponents();
         
          GetBookDetails(bookId);        
}

It should print 1 twice. (I'm rather sure it will)

>> So when I hit the update button on the update window it updates the database.
>> I then get the rowSelected again to update the JTable in the Search window
>> Does this make sense to you?
Yes. At first sight.

Avatar of Bourke

ASKER

I'll try that so.

But I put a check for the selected row in the Search window just before I pass the
table in and it comes up as -1 there!
That doesnt make sense!
Avatar of Bourke

ASKER

I got the following results:

a) Selected row: -1

b) Selected row: 1
Which seems to indicate that you pass the wrong JTable object.

Another test. Could you add this:

THis code is in the main Search page for the action on a popmenu on the jtable
       if(e.getActionCommand() == "Update"){
         if(selIndex == 0){
            System.out.println("c) Selected row = " + table.getSelectedRow()); // <<<<<<<<<<
            UpdateBook updateBook = new UpdateBook                  
                       (this.theDesktop,this.user, this.con,
                       rowRecBk[selectedRow][0], table,selectedRow);
           
                       updateBook.show();
                   
         }
       }

I expect it to be -1 too.
Which means that the selection is already "gone" (?), when reaching this instruction.
Then simply use the passed selectedRow in your update window.

Can you explain what

 >> if(selIndex == 0){

is for in the above code?
Avatar of Bourke

ASKER

This is the code I wrote to make the JTable:

private void makeTable (String[][] rowRec) {

     //String Array For Table Columns.
     String colsName[] = {"Book No" ,"Book ISBN", "Book Title", "Book  
                                    Author", "Category", "Member ID", "Status"};
     int j = 0;
            
     List data = new ArrayList();
            
    for(int i=0; i < rowRec.length; i++){
                  
              System.out.println("length of rowRec" + rowRec.length);      
              data.add( new SearchTableObject(rowRec[i][j], rowRec[i][++j],  
                              rowRec[i][++j], rowRec[i][++j], rowRec[i][++j],
                              rowRec[i][++j], rowRec[i][++j] ));
                            j = 0;      
              
                }      
            
      table = new JTable ();
      table.setModel(new SearchTableModel(data, colsName));
      
      table.getModel().addTableModelListener(this);
      int s = table.getSelectedRow();
      System.out.println("In make table selected Row = " + s);
            
      ListSelectionModel rowSM = table.getSelectionModel();
          rowSM.addListSelectionListener(new ListSelectionListener(){
          public void valueChanged(ListSelectionEvent e) {
                  ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                if (!lsm.isSelectionEmpty()) {
                  selectedRow = lsm.getMinSelectionIndex();
                        
                 }
          }
          });
            
            
        if(table.getModel().getRowCount() > 0)
          //rowSM.setSelectionInterval(0,0);
                       table.addMouseListener(new MouseAdapter(){
            
                       public void mousePressed(MouseEvent e){
              int nModifier = e.getModifiers();
                JTable table = (JTable)e.getSource();
                  int selectedRow = table.rowAtPoint(e.getPoint());
                  
             constructPopupMenu();
             popupmenu.show(table,e.getX(), e.getY());
                        
                 }
             });

                       //Remove the ID column from the table
              TableColumnModel columnNo = table.getColumnModel();
              columnNo.removeColumn( columnNo.getColumn( 0 ) );      

}
Avatar of Bourke

ASKER

>> if(selIndex == 0){
I have a tabbed pane, and I just am checking here if the tab seleceted is tab 0

also above table is defined as
private JTable table;
in the Search class
Avatar of Bourke

ASKER

I tried using the selected row passed in and I got this error:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.RangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at Logon.SearchTableModel.getTableObject(SearchTableModel.java:20)
at Logon.UpdateBook.UpdateBook(UpdateBook.java:380)
at Logon.UpdateBook.actionPerformed(UpdateBook.java:278)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(Unknown Source)

at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)

at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

>>I tried using the selected row passed in and I got this error:

>>java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
>>at java.util.ArrayList.RangeCheck(Unknown Source)
>>at java.util.ArrayList.get(Unknown Source)
>>at Logon.SearchTableModel.getTableObject(SearchTableModel.java:20)

Which means that you try to perform getTableObject(1) on your SearchTableModel,
while it only contains one item. So 1 is an invalid index.


Hey,

>> int selectedRow = table.rowAtPoint(e.getPoint());

this is no good!
It's not because you right-click on a table item that it is also selected, is it?
So, selectedRow will become 1 or whatever the index of the corresponding row might be,
(that's the index of the row you right-clicked on) while table.getSelectedRow() remains -1 (no row selected)
That's why we had the previous problems.
btw, I'm almost reaching my 50 points-limit ;°)
Avatar of Bourke

ASKER

I tried to do this in the constructor of SearchTableModel:

 public SearchTableModel(List d, String[] columnNames) {
        this.data = d;
        this.columnNames = columnNames;
       
        System.out.println("length of data = " + d.getItemCount());
}

I get the following compiler error:
SearchTableModel.java:19: cannot resolve symbol
symbol  : method getItemCount ()
location: interface java.util.List
        System.out.println("length of data = " + d.getItemCount());
                                                                   ^

Avatar of Bourke

ASKER

Ok can Increase the points, would that be ok?
getItemCount() doesn't exist on List. Use size().

This error means that the code you gave before

>> table.setModel(new SearchTableModel(data, colsName));

has never run.
Then you make it rather difficult for me to help you.
Please be honest.
Avatar of Bourke

ASKER

What do you mean by please be honest?

I used size above and got back 1 so there is something in the data is there not?
Avatar of Bourke

ASKER

I found some of the problem!
I have two tabs and I use the same function to make the JTable.
So the second tab overwrites the data of the first.
I'll have to find a way round this.
>>What do you mean by please be honest?
I mean: Don't post code you don't run.
But my sincere apologies, I see I misinterpreted.
You just (try to) add
>> System.out.println("length of data = " + d.getItemCount());
in the SearchTableModel.

OK.
>> I used size above and got back 1 so there is something in the data is there not?
Yes, there is something in, but that means that there is only one record in.
That's why trying to get the table object on the 2nd row gives an exception.
So, selectedRow shouldn't be 1, but 0.
Up to you to find out why it is 1 instead of 0.
>> So the second tab overwrites the data of the first.
Whooo. Nasty ;°)

>> I use the same function to make the JTable.
Do you want the table's in both tabs to contain the same data?
No? Then why use the same JTable/table model?
>> I use the same function to make the JTable.
Which one?
Avatar of Bourke

ASKER

>>Which one?
private void makeTable (String[][] rowRec) that I posted above.

Ok all that works fine now.

What was happening was that I have a JTabbedPane with two tabs
and I use the same makeTable function to display up results.
I send in different 2-d arrays depending on the tab that is currently
selected.

Should I have 2  different functions to create the table for each tab?
Avatar of Bourke

ASKER

or I could have two Lists in the SearchTableModel class
one for each tab?
>> Should I have 2  different functions to create the table for each tab?
>> or I could have two Lists in the SearchTableModel class
>> one for each tab?
No, you should just use two different SearchTableModel instances; one for each JTable.

For the first JTable you pass the first data list.
For the 2nd JTable you pass another data list.

List data1 = new ArrayList();

 // create your data for the 1st table          
         
table = new JTable ();
table.setModel(new SearchTableModel(data1, colsName));


List data2 = new ArrayList();
 // create your data for the 2nd table          
table2 = new JTable ();
table2.setModel(new SearchTableModel(data2, colsName));
Avatar of Bourke

ASKER

Hi,
  I got the above sorted anyway.  But a few strange things seem to be happening.
When I update the details in the update I printed the following to the console:

Before update
Field2 = 0-672-32128-9
Field3 = title1
Field4 = author1
Field5 = Java

after update: (this is what is displayed in the table)
Field3 changed = author2 (field3 should be title2)
Field4 changed = author1 (field4 should be author2)


Avatar of Bourke

ASKER

I thought that since I removed a column in the maketable function code
above that it might cause problems but it should'nt should it?
Avatar of Bourke

ASKER

I put back the column I removed and tried that but it still gave me the same
problem!
Avatar of Bourke

ASKER

actually it only seems to set the first 3 columns? any idea?
>> actually it only seems to set the first 3 columns? any idea?
Can you post the table model you use at the moment?
Avatar of Bourke

ASKER

This is the table model, nearly same as the one you posted earlier

package Logon;

import javax.swing.*;
import javax.swing.table.*;
import java.util.*;
import java.util.List;

public class SearchTableModel extends DefaultTableModel {
   
    List data; // a list of MyObject's
   
    private String[] columnNames;
   
    /** Creates a new instance of MyTableModel */
    public SearchTableModel(List d, String[] columnNames) {
        this.data = d;
        this.columnNames = columnNames;
       
        System.out.println("length of data = " + data.size());
    }
   
    public Object getTableObject(int index) {
   
        return data.get(index);
    }

    public void setColumnName(int index, String name) {
        if (index < columnNames.length)
            columnNames[index] = name;
    }
   
   public boolean isCellEditable(int row, int col) {
     return false;
   }
   
   public void addRow(SearchTableObject object) {
       data.add(object);
       fireTableRowsInserted(data.size()-2, data.size()-2);
   }
   
   public void removeRow(int index) {
       data.remove(index);
       fireTableRowsDeleted(index, index);
   }

   public Class getColumnClass(int col) {
      return super.getColumnClass(col);
   }
   
   public int getRowCount() {
       return data==null ? 0 : data.size();
   }
   
    public int getColumnCount() {
        return columnNames.length;
    }
   
    public Object getValueAt(int row, int col) {
        if ( row < 0 || row >= data.size() ) return null;
        SearchTableObject myObj = (SearchTableObject) data.get(row);
        if (col==0)
            return myObj.getField1();
        else if (col==1)
            return myObj.getField2();
        else if (col==2)
            return myObj.getField3();
        else if (col==3)
            return myObj.getField4();
        else if (col==4)
            return myObj.getField5();
        else if (col==5)
            return myObj.getField6();
        else if (col==6)
            return myObj.getField7();                
        else return null;
    }

    // not needed if not editable:
    public void setValueAt(Object value, int row, int col) {
        if ( row < 0 || row >= data.size() /*|| col!=0*/ ) return;
        // only col=0 is editable (in this example)
        SearchTableObject myObj = (SearchTableObject) data.get(row);
        if (col==0)
            myObj.setField1( (String)value );
        else if (col==1)
            myObj.setField2( (String)value );
        else if (col==2)
            myObj.setField3( (String)value );
        else if (col==3)
            myObj.setField4( (String)value );
        else if (col==4)
            myObj.setField5( (String)value );
        else if (col==5)
            myObj.setField6( (String)value );
        else if (col==6)
            myObj.setField7( (String)value );                
           
           
        fireTableCellUpdated(row, col);
       
    }
   
    public String getColumnName(int col) {
        return columnNames[col];
    }
   
   
   
}

Avatar of Bourke

ASKER

I've tried absolutely nearly eveything to sort out the above
problem.

Field1, Field2, Field3 update fine from the update window
to the table on the Search window.  If I change Field4
Field 3 is overwritten with what Field4 is set to etc

So if Field 4,5,6 are changed Field3 in the table is overwritten by first field4 value then Field5 value then Field6 value.  

Cant see what the problem is????
Would you have any ideas?




Avatar of Bourke

ASKER

Maybe you want me to increase the points?
Sorry, I really have no idea.
I would check (by printing out)
- if you really change the fields you think you change
- if you really show the fields you think you show in that column
Avatar of Bourke

ASKER

I've tried all that.
I print out by using the getFieldX function before I change
them and they are print out exactly what is there.
Then I set the first 3 fields by using the setFieldX function and that is grand.
It is when I try to set field4 it goes in field3
and if I set field5 it goes into field3 and if I set field6 it goes into field3.

I know the orig. example you gave me above had just 3 fields in it did you set the no of fields anywhere to 3 maybe?




>> I know the orig. example you gave me above had just 3 fields in it
I thought about that to, but your SearchTableModel is just OK.

>> It is when I try to set field4 it goes in field3
Did you check that *the object's field3* is really changed (data) or do you just *see* it in that table that way (view)?

Difficult to help without your code :°/
But I guess it is too much to post...
Maybe you can post where you perform the field changes?
Avatar of Bourke

ASKER

>>Maybe you can post where you perform the field >>changes?

This is where I make the changes.

obj.setField2(strTitle);
obj.setField3(strAuthor);
obj.setField4(
          Category[1][cboCategory.getSelectedIndex()] );

It's just that field4 is written into field3 on the view of the table.

I dont change the data at all would that make a difference?
Would I have to?
>> It's just that field4 is written into field3 on the view of the table
So in reality that field3 still has its previous value and field4 is changed? Sure the object's setField4() is OK?
So it's a visualization problem?

What can I say?
It is impossible if you use this in the table model:

 public Object getValueAt(int row, int col) {
        if ( row < 0 || row >= data.size() ) return null;
        SearchTableObject myObj = (SearchTableObject) data.get(row);
        if (col==0)
            return myObj.getField1();
        else if (col==1)
            return myObj.getField2();
        else if (col==2)                         // 3rd column
            return myObj.getField3();      // 3rd field
        else if (col==3)                          // 4th column
            return myObj.getField4();       // 4th field
        else if (col==4)
            return myObj.getField5();
        else if (col==5)
            return myObj.getField6();
        else if (col==6)
            return myObj.getField7();                
        else return null;
    }
Avatar of Bourke

ASKER

I'll try writing up some code that could run on it's own
and I'll post it tomorrow.

Thanks for all your help, very much appreciated.

V
OK
CU
Avatar of Bourke

ASKER

Hi,
   I've wrote some independant code that is doing similar to what is happening here, if you have the
time to take a look that would be great, thanks.

What's happening in this one is that the last column is not being updated, it updates the secondlast column
with the last columns data.

//TableDemo.java
package Logon;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import java.util.List;
import java.awt.*;
import java.awt.event.*;
/**
 *
 * @author  zzynx
 */
public class TableDemo extends javax.swing.JFrame implements ActionListener{
                           
    /** Creates new form TableDemo */
    public TableDemo() {
        initComponents();
       
    }
   
    private void initTable() {
       
        int j = 0;
                        
            for(int i=0; i < rowRec.length; i++){
                  
              data.add(new SearchTableObject(rowRec[i][j++], rowRec[i][j++], rowRec[i][j++], rowRec[i][j++], rowRec[i][j++], rowRec[i][j++]));
              j = 0;      
              
        }      
       
        table.setModel(new SearchTableModel(data, colsName));
    }
   
    private JTable makeTable () {

            
            table = new JTable ();
            initTable();
            table.setModel(new SearchTableModel(data, colsName));
      
            table.getModel().addTableModelListener(table);
            
            ListSelectionModel rowSM = table.getSelectionModel();
          rowSM.addListSelectionListener(new ListSelectionListener(){
          public void valueChanged(ListSelectionEvent e) {
                ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                  if (!lsm.isSelectionEmpty()) {
                        selectedRow = lsm.getMinSelectionIndex();
                        
            }
                }
                });
            
            
         if(table.getModel().getRowCount() > 0)
          
            table.addMouseListener(new MouseAdapter(){
                  
                    public void mousePressed(MouseEvent e){
                          
              
                  
                      int nModifier = e.getModifiers();
                

                              JTable table = (JTable)e.getSource();
                              int selectedRow = table.rowAtPoint(e.getPoint());
                  
                          constructPopupMenu(table);
                          popupmenu.show(table,e.getX(), e.getY());
                        
                }
            });

 
             return table;
            }
   
    private void constructPopupMenu(JTable table){
            
            popupmenu = new JPopupMenu();
            
            
            // Create some menu items for the popup
            JMenuItem menuIssue = new JMenuItem( "Issue" );
            JMenuItem menuReturn = new JMenuItem( "Return" );
            JMenuItem menuDelete = new JMenuItem( "Delete" );
            JMenuItem menuUpdate = new JMenuItem( "Update" );
            JMenuItem menuDetails = new JMenuItem( "Details" );

            // Create a popup menu
            popupmenu = new JPopupMenu( "Menu" );
            popupmenu.add( menuIssue );
            popupmenu.add( menuReturn );
            popupmenu.add( menuDelete );
            popupmenu.add( menuUpdate );
            popupmenu.add( menuDetails );
            
            // Action and mouse listener support
            enableEvents( AWTEvent.MOUSE_EVENT_MASK );
            menuIssue.addActionListener( this );
            menuReturn.addActionListener( this );
            menuDelete.addActionListener( this );
            menuUpdate.addActionListener( this );
            menuDetails.addActionListener( this );
            
            SearchTableModel model = (SearchTableModel)table.getModel();
        SearchTableObject obj = (SearchTableObject)model.getTableObject(selectedRow);
           
        if(obj.getField6().equals("Reserved")){
              
              menuIssue.setEnabled(false);
              
        }else if(obj.getField6().equals("Available")){
              menuReturn.setEnabled(false);
        }      
      }
      
      public void actionPerformed(ActionEvent e){
            
            if(e.getActionCommand() == "Update"){
                  UpdateBook updateBK = new UpdateBook(theDesktop, rowRec[selectedRow][0], table, selectedRow);
                  updateBK.show();
            }
      }            
      
      
      
    private void initComponents() {
          
        jScrollPane1 = new javax.swing.JScrollPane();
        theTable = makeTable();
        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        addButton = new javax.swing.JButton();
        deleteButton = new javax.swing.JButton();
        changeButton = new javax.swing.JButton();

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });

        jScrollPane1.setViewportView(theTable);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jPanel1.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        addButton.setText("Add");
        addButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButtonActionPerformed(evt);
            }
        });

        jPanel2.add(addButton);

        deleteButton.setText("Delete");
        deleteButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteButtonActionPerformed(evt);
            }
        });

        jPanel2.add(deleteButton);

        changeButton.setText("Change");
        changeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                changeButtonActionPerformed(evt);
            }
        });

        jPanel2.add(changeButton);

        jPanel1.add(jPanel2);
            //getContentPane().add(theDesktop);
        getContentPane().add(jPanel1, java.awt.BorderLayout.SOUTH);
            
        pack();
    }

    private void changeButtonActionPerformed(java.awt.event.ActionEvent evt) {
        int selectedRow = theTable.getSelectedRow();
        if (selectedRow!=-1) {
            SearchTableModel model = (SearchTableModel)theTable.getModel();
            SearchTableObject obj = (SearchTableObject)model.getTableObject(selectedRow);
            obj.setField1("Changed");
            obj.setField2("Changed too");
            obj.setField3("Also changed...");
            obj.setField4("New one1...");
            obj.setField5("New one2...");
            obj.setField6("New one3...");
            model.fireTableRowsUpdated(selectedRow, selectedRow); // needed
        }
    }

    private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {
        if (theTable.getSelectedRow()!=-1)
            ((SearchTableModel)theTable.getModel()).removeRow(
                theTable.getSelectedRow() );
    }

    private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
        ((SearchTableModel)theTable.getModel()).addRow(
            new SearchTableObject("aaaaa", "bbbbbb", "ccccc", "dddd", "eeee", "ffff" ) );
    }
   
    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {
        System.exit(0);
    }
   
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (Exception e) {
            System.exit(0);
        }
       
        new TableDemo().show();
    }
   
    // Variables declaration - do not modify
    private javax.swing.JButton addButton;
    private javax.swing.JButton changeButton;
    private javax.swing.JButton deleteButton;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable theTable;
   
    private List data = new ArrayList();
    private int selectedRow;
    private JPopupMenu popupmenu;
    private JTable table;
    private String colsName[] = {"RefNo", "Title", "Author", "Category", "Member ID", "Status"};
    private JDesktopPane theDesktop = new JDesktopPane ();
    private String[][] rowRec = {
                                            {"1234", "Java", "JB", "Java", "vbourke", "available"},
                                            {"5678", "Java2", "VB", "Java", "vblogs1", "available"},
                                            {"0112", "Java3", "SB", "Java", "vblogs2", "available"},
                                            {"3456", "Java4", "DB", "Java", "vblogs3", "available"},
                                            {"7892", "Java5", "NB", "Java", "vblogs4", "available"},
       
                                      };
    // End of variables declaration
   
}

//SearchTableModel.java
package Logon;

import javax.swing.*;
import javax.swing.table.*;
import java.util.*;
import java.util.List;

public class SearchTableModel extends DefaultTableModel {
   
    List data; // a list of MyObject's
   
    private String[] columnNames;
   
    /** Creates a new instance of MyTableModel */
    public SearchTableModel(List d, String[] columnNames) {
        this.data = d;
        this.columnNames = columnNames;
       
        System.out.println("length of data = " + data.size());
    }
   
    public Object getTableObject(int index) {
   
        return data.get(index);
    }

    public void setColumnName(int index, String name) {
        if (index < columnNames.length)
            columnNames[index] = name;
    }
   
   public boolean isCellEditable(int row, int col) {
     return false;
   }
   
   public void addRow(SearchTableObject object) {
       data.add(object);
       fireTableRowsInserted(data.size()-2, data.size()-2);
   }
   
   public void removeRow(int index) {
       data.remove(index);
       fireTableRowsDeleted(index, index);
   }

   public Class getColumnClass(int col) {
      return super.getColumnClass(col);
   }
   
   public int getRowCount() {
       return data==null ? 0 : data.size();
   }
   
    public int getColumnCount() {
        return columnNames.length;
    }
   
    public Object getValueAt(int row, int col) {
        if ( row < 0 || row >= data.size() ) return null;
        SearchTableObject myObj = (SearchTableObject) data.get(row);
        if (col==0)
            return myObj.getField1();
        else if (col==1)
            return myObj.getField2();
        else if (col==2)
            return myObj.getField3();
        else if (col==3)
            return myObj.getField4();
        else if (col==4)
            return myObj.getField5();
        else if (col==5)
            return myObj.getField6();
       
        else return null;
    }

    // not needed if not editable:
    public void setValueAt(Object value, int row, int col) {
          
        if ( row < 0 || row >= data.size() )/*|| col!=0 )*/ return;
       
       
        // only col=0 is editable (in this example)
        SearchTableObject myObj = (SearchTableObject) data.get(row);
        if (col==0)
            myObj.setField1( (String)value );
        else if (col==1)
            myObj.setField2( (String)value );
        else if (col==2)
            myObj.setField3( (String)value );
        else if (col==3)
            myObj.setField4( (String)value );
        else if (col==4)
            myObj.setField5( (String)value );
        else if (col==5)
            myObj.setField6( (String)value );
             
        fireTableCellUpdated(row, col);
       
    }
   
    public String getColumnName(int col) {
        return columnNames[col];
    }
   
   
   
}

//SearchTableObject.java

package Logon;

public class SearchTableObject {
   
    private String field1 = "";
    private String field2 = "";
    private String field3 = "";
    private String field4 = "";
    private String field5 = "";
    private String field6 = "";

    /** Creates a new instance of MyTableObject */
    public SearchTableObject() {
    }
   
    public SearchTableObject(String f1, String f2, String f3, String f4, String f5, String f6) {
       
        field1 = f1;
        field2 = f2;
        field3 = f3;
        field4 = f4;
        field5 = f5;
        field6 = f6;
       
    }

    public String getField1() { return field1; }
    public String getField2() { return field2; }
    public String getField3() { return field3; }
    public String getField4() { return field4; }
    public String getField5() { return field5; }
    public String getField6() { return field6; }
   
    public void setField1(String f1) { field1 = f1; }
    public void setField2(String f2) { field2 = f2; }
    public void setField3(String f3) { field3 = f3; }
    public void setField4(String f4) { field4 = f4; }
    public void setField5(String f5) { field5 = f5; }
    public void setField6(String f6) { field5 = f6; }
}





Found the error:

   public void setField6(String f6) { field5 = f6; }  // you set field5 instead of 6

You see, that my question
>> Sure the object's setField4() is OK?
was not that stupid as it sounds? ;°)

Other remark:
In your mousePressed() function I would add

          public void mousePressed(MouseEvent e){
                     
              if (!SwingUtilities.isRightMouseButton(e))        // <<<<< add this
                   return;                                                   // <<<<<

              ....
         }

So that the menu only appears on a right-click
Avatar of Bourke

ASKER

Hi, thanks for that, looks better with the right mouse click. I went and changed it my application code here it didnt make any difference what so ever.







Avatar of Bourke

ASKER

field3 is the one that is being overwritten all the time.
doesnt make any sense!
>> I went and changed it my application code here
*it*? What?
>> it didnt make any difference what so ever.
Don't know what you mean.
Avatar of Bourke

ASKER

I went and changed what you spotted was wrong above.
It worked fine when I changed it in the Demo version
that I posted above.  But in my real application here
it still isnt working properly.
Sure you really run the *adapted* code?
Avatar of Bourke

ASKER

Yeah in the demo, I was overwritting field5 with field6
in my real app. field3 is being overritten by whatever is in field4 if update or field5 if update or field6 if updated.

It's acting really strange:
This is what I am changing
SearchTableModel model =
           (SearchTableModel)table.getModel();
SearchTableObject obj =
 (SearchTableObject)model.getTableObject(selectedRow);

            obj.setField1("Changed");
            obj.setField2("Changed too");
            obj.setField3("Also changed...");
            obj.setField4("New one1...");
            obj.setField5("New one2...");
            obj.setField6("New one3...");

model.fireTableRowsUpdated
             (selectedRow, selectedRow);
ASKER CERTIFIED SOLUTION
Avatar of zzynx
zzynx
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bourke

ASKER

Setfieldx() functions are as follows:
    public void setField1(String f1) { field1 = f1; }
    public void setField2(String f2) { field2 = f2; }
    public void setField3(String f3) { field3 = f3; }
    public void setField4(String f4) { field4 = f4; }
    public void setField5(String f5) { field5 = f5; }
    public void setField6(String f6) { field6 = f6; }
Avatar of Bourke

ASKER

Right all is sorted now.  I did a reboot of my PC and everything seems to updating properly.

Thank you again for your help, it is very much appreciated.
All right! :)
Please kindly close this Q by accepting
Thanks for accepting