[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3754
  • Last Modified:

Using fireTableDataChanged() within a custom table extending AbstractTableModel

Product: Java, SE 6

It seems I need help.

I am using AbstractTableModel to create a custom table and when I invoke fireTableDataChanged() after editing my table data in my table model nothing seems to happen.

I thought that AbstractTableModel implicitly handles the delegation to update the view, the JTable.

It seems I am missing something in my code to help this along. I am asking you because I want to stop banging my head against a wall.

What I have done is implement the three necessary methods from the table model interface which is implemented by AbstractTableModel:

    public int getColumnCount()
    public int getRowCount()
    public Object getValueAt(int row, int column)

as well as the getColumnName method to add columns.

Since my data model is not editable externally (directly through the cells) I decided not to implement setValueAt.

I am using a vector of vectors for my main data structure. My nested vectors hold Object types of the loan payment info.

I thought it was my data structure but I can initialize my table with data using the vector structure in the constructor of MyCustomTable. However, when i fire a change from elsewhere nothing happens(either using the code that tested the data structure and classes correctness from my constructor or the loan info.). I must be missing something and don't know what. The only other thing I haven't really considered is my JScrollPane but that really shouldn't be an issue.

What I have considered is:

1)providing my own implementation for delegation and updating the view: this seems unnecessary since the docs say its already there.

2) my datastructure: works fine in the constructor

3) where I call fireTableDataChanged(): doesn't seem to matter if i can from within class or from the JTable object, still doesn't work.

4) what i am storing: i am storing vectors of objects that are really strings(maybe cant update table with this object type?)


I hope you can help.

regards,

Justin.

0
justinbh3
Asked:
justinbh3
  • 6
  • 3
1 Solution
 
bpmurrayCommented:
Actually you shouldn't have to call fireXXX() methods directly. However, without some code, I'm just guessing. A few things to look for:
* If the data values are not the right type, you won't get an update, but you should see an exception
* Is the table in edit mode? Can you call editor.StopCellEditing?
* Is your renderer code being called? This is probably the most likely.
0
 
justinbh3Author Commented:
I have posted some code. Maybe this is clearer.

public class MyCustomTable extends AbstractTableModel {

      private String colNames [] = { "Payment#", "Interest", "Principal", "Balance" };
      
      private Vector data;
      
      double balance, principal, interest, monthlyPayment;
      
      int noOfYears;
      

      
      
      
      public MyCustomTable()
      {
          data = new Vector(new Vector());
      }
      
      public String getColumnName(int column)
      {
            return this.colNames[column];
      }
      
      /* (non-Javadoc)
       * @see javax.swing.table.TableModel#getColumnCount()
       */
      public int getColumnCount() {

            return this.colNames.length;
      }

      /* (non-Javadoc)
       * @see javax.swing.table.TableModel#getRowCount()
       */
      public int getRowCount() {

            return this.data.size();
      }

      /* (non-Javadoc)
       * populates table
       */
      public Object getValueAt(int row, int column) {
            return ((Vector)(data.get(row))).get(column);
      }

      public void setData(double loanAmnt, double noOfYears, double interestRate)
      {
            
            Vector newRow;
            

            double monthlyInterestRate = 0;
            
            data.removeAllElements();
            monthlyInterestRate =  interestRate / 12;
            this.balance = loanAmnt;
            
      
            while (this.balance != 0)
            {
                  this.monthlyPayment = loanAmnt * monthlyInterestRate /
                                        (1 - (Math.pow(1/(1+monthlyInterestRate),noOfYears *12)));
                  
                  this.interest = monthlyInterestRate * this.balance;
                  
                  this.principal = this.monthlyPayment - this.interest;
                  
                  this.balance -= this.principal;
                  
                  newRow = new Vector();
                  
                  newRow.add((Object)(new Double(this.monthlyPayment).toString()));
                  newRow.add((Object)(new Double(this.interest).toString()));
                  newRow.add((Object)(new Double(this.principal).toString()));
                  newRow.add((Object)(new Double(this.balance).toString()));
                  
                  data.add(newRow);
                  

                  
                  if (this.balance < 0)
                      this.balance = 0;
                  
                  this.interest = 0;
                  this.principal = 0;
                  this.monthlyPayment = 0;
                  
                  
            }
      


            
            
      }
      

}
0
 
justinbh3Author Commented:
One more comment. I thought with AbstractTableModel that you needed to call one of the fire methods when updating your model data. Also, you will notice that fireTableDataChanged() isnt being invoked above. It will not matter if I put it at the end of my setData function or not, the table will not update.

0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
objectsCommented:
yes, you do need to call fireXXX()
can u post where u use your table model?
0
 
justinbh3Author Commented:
public class Lab03Frame extends JFrame {

      private JPanel tablePanel, loanInfoPanel;
      
      private JTable loanTable;
      
      private Box [] loanBoxes;
      
      private Box bigLoanBox, masterBox;
      
      private Container contentPane;
      
      private JSpinner [] loanData;
      
      private JLabel [] loanDataFields;
      
      private JButton calcLoanPaymentSchedule;
      
      private MyCustomTable cTable;
      
      
      public Lab03Frame()
      {
            this.initMembers();
            this.createGUI();
            this.initButtonListener();
      }
      
      
      private void initMembers()
      {
            this.loanData = new JSpinner[3];
            this.loanDataFields = new JLabel[3];
            this.loanBoxes = new Box[3];
            this.cTable = new MyCustomTable();
            
            for (int i = 0; i < 3; ++i)
            {
                  this.loanData[i] = new JSpinner();
                  this.loanDataFields[i] = new JLabel();
                  this.loanBoxes[i] = new Box(BoxLayout.X_AXIS);
            }
            

            this.tablePanel = new JPanel();
            this.loanTable = new JTable(new MyCustomTable());      
            this.loanInfoPanel = new JPanel();
            this.bigLoanBox = new Box(BoxLayout.Y_AXIS);
            this.masterBox = new Box(BoxLayout.X_AXIS);
            this.loanInfoPanel.setBorder(new TitledBorder
                                                ("Enter Loan Amount, " +
                                                 "Number of Years, and Annual " +
                                                 "Interest Rate"));
            
            this.calcLoanPaymentSchedule = new JButton("Get Schedule");
            this.loanDataFields[0].setText("Loan Amount                   ");
            this.loanDataFields[1].setText("Number of Years            ");
            this.loanDataFields[2].setText("Annual Interest Rate     ");
            
      }
      
      private void createGUI()
      {
            this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
            this.contentPane = this.getContentPane();
            
            this.setLayout(new BorderLayout());
            

            this.loanInfoPanel.setLayout(new BorderLayout());
            
            this.loanBoxes[0].add(this.loanDataFields[0]);
            this.loanBoxes[0].add(this.loanData[0]);
            this.loanBoxes[1].add(this.loanDataFields[1]);
            this.loanBoxes[1].add(this.loanData[1]);
            this.loanBoxes[2].add(this.loanDataFields[2]);
            this.loanBoxes[2].add(this.loanData[2]);
            
            this.bigLoanBox.add(this.loanBoxes[0]);
            this.bigLoanBox.add(this.loanBoxes[1]);
            this.bigLoanBox.add(this.loanBoxes[2]);
            
            this.masterBox.add(this.bigLoanBox);
            this.masterBox.add(this.calcLoanPaymentSchedule);
            this.loanInfoPanel.add(this.masterBox);
            
            this.tablePanel.add(new JScrollPane(this.loanTable));
            this.add(this.loanInfoPanel,BorderLayout.NORTH);
            this.add(this.tablePanel, BorderLayout.SOUTH);
            
            this.pack();
            this.setVisible(true);
      }
      
      private void initButtonListener()
      {
            this.calcLoanPaymentSchedule.addActionListener(new ActionListener() {
                  public void actionPerformed( ActionEvent actionEvent )
                {

                        cTable.setData(((Integer)loanData[0].getValue()).doubleValue(),
                                                  ((Integer)loanData[1].getValue()).doubleValue(),
                                                    ((Integer)loanData[2].getValue()).doubleValue());
                  
                        cTable.fireTableDataChanged(); // Here is where i use my fire method
                }});
      }

}

As I mentioned before it doesnt matter if I call it in the model or here it wont update. I have also tried using fireTableStructureChanged() and fireTableDataChanged(TableModelEvent e). Thanks.
0
 
objectsCommented:
that won't work.
move the fireXXX() call inside the setData() method

                  this.interest = 0;
                  this.principal = 0;
                  this.monthlyPayment = 0;
                  fireTableDataChanged();
                 
            }(
0
 
justinbh3Author Commented:
I have already tried that as i mentioned in my first post. I could put it practiaclly anywhere and it wont update my view.

I just find that strange. Since the delegation to update the view should be provided as long as you call firetabledatachanged() within the table model implementation.
0
 
objectsCommented:
>             this.loanTable = new JTable(new MyCustomTable());      

also change that to:

            this.loanTable = new JTable(cdata = new MyCustomTable());      
0
 
justinbh3Author Commented:
ill give it a try, and thanks.

one thing though... did you mean cTable since a dont have a cData member of type MyCustomTable. I do, however, have a cTable. I think that is what you were referring to.

ill let you know how it goes.
0
 
justinbh3Author Commented:
thanks!

a second pair of eyes(or third or fourth) is great.

0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 6
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now