0

I'm working on a small project that involves JTable which requires the user to click a button and add a row to the table (I have named the button as addrow). I have used a custom table model (Mytablemodel) which extends Default table model. My table is first made up of five rows and 4 columns where afterwards user can click the addrow button to add more rows

Everything in my code works fine except the addrow button which does nothing. I will appreciate any help.

public class AddingNewRows extends JFrame {
JTable mytable;
JButton addrow;
String[] columns={"Admission number","Name","School","Year"};
TableColumn tc;
int defaultrows=5;
int rows=new Mytablemodel().getRowCount(),columnscount=new Mytablemodel().getColumnCount();
List data=new ArrayList();
Mytablemodel mytbm;
//
public AddingNewRows(){
super("adding rows");
for(int initialrows=0; initialrows<5; initialrows++){
   String[] items={"1","2","3","4"};
 data.add(items);
}
mytbm=new Mytablemodel();
mytable=new JTable(mytbm);

JScrollPane scroll=new JScrollPane(mytable);
addrow=new JButton("ADD ROW");
//
JPanel buttonpanel=new JPanel();
buttonpanel.setLayout(new BoxLayout(buttonpanel,BoxLayout.X_AXIS));
buttonpanel.setAlignmentX(Component.RIGHT_ALIGNMENT);
buttonpanel.add(addrow);

//
add(scroll,BorderLayout.CENTER);
add(buttonpanel,BorderLayout.SOUTH);

addrow.addActionListener(new Myactions());

}
public class Mytablemodel extends DefaultTableModel{

@Override
public String getColumnName(int column) {
    return columns[column];
}
@Override
public Object getValueAt(int row, int col){
 return ((String[])data.get(row))[col]; 
}
@Override
public boolean isCellEditable(int row, int col){
  return true;
}
@Override
public void setValueAt(Object value,int row, int col){
  ((Object[])data.get(row))[col]=value;
  fireTableCellUpdated(row,col);

}
@Override
public Class getColumnClass(int column){
  return getValueAt(0,column).getClass();
}  
@Override
public int getColumnCount(){
  return columns.length;
}

@Override
public int getRowCount(){
  return increaserows; 
}

@Override
public void addRow(Object[] mynewdata){
  int rownum=data.size();
  System.out.println(rownum);
  data.add(madata);
fireTableRowsInserted(rownum,rownum);
}

}
//
private class Myactions implements ActionListener{

@Override
public void actionPerformed(ActionEvent event){
 if(event.getSource()==addrow){ 
   Object[]newdata={"","","",""};
    mytbm.addRow(newdata);  
 } 
} 
}
public static void main(String[] args) {

 AddingNewRows frame=new AddingNewRows();
 frame.setVisible(true);
    frame.setSize(400,400);
    frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);

}

}
Edijae Crusar
  • 3,473
  • 3
  • 37
  • 74
  • 1
    Words typed in all lower case are hard to read, like trying to listen to someone who is mumbling. Please use an upper case letter at the start of sentences, for the word I, and proper names like `ArrayList` or Oracle. – Andrew Thompson Jan 06 '15 at 12:12
  • 1
    `Mytablemodel extends AbstractTableModel{` Do yourself a favor and instead extend **`DefaultTableModel`** instead. It does this type of stuff for you. But for better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example) or [SSCCE](http://www.sscce.org/) (Short, Self Contained, Correct Example). – Andrew Thompson Jan 06 '15 at 12:15
  • @AndrewThompson all data entered in the table are later saved into the database through onther button and this works fine. thats why i used custom table model since i dont think i can use DefaultTableModel to save the data into the database. furthermore AM HAVING TROUBLE UNDERSTANDING THE fireTableRowsInserted(int,int) method. the parameters themself and where or when to call the method – Edijae Crusar Jan 06 '15 at 12:23
  • 1
    Well, post an MCVE.. Hard code some data to replace the DB. – Andrew Thompson Jan 06 '15 at 12:44
  • @AndrewThompson. i thought my code is already MCVE. furthermore as you can see, all my rows contain empty strings since the for loop fills the object array with empty strings. therefore they act like data that replaces the DB – Edijae Crusar Jan 06 '15 at 13:46
  • *"i thought my code is already MCVE."* You thought wrong. It is not *complete,* so it is not compilable, let alone runnable. As such it is not a *verifiable example* either. So of MCVE, it meets only the **first** criterion. – Andrew Thompson Jan 06 '15 at 14:48
  • 1
    @gikarasojokinene ` i dont think i can use DefaultTableModel to save the data into the database.` why do you think that? A model just stores data. Your model doesn't have any special code for a database. All you model has is a getValueAt(...) method, which is also found in ANY TableModel. ` AM HAVING TROUBLE UNDERSTANDING THE fireTableRowsInserted(int,int) method` and the DefaultTableModel already does this for you so you don't need to do anything. So again there is no need to create a custom TableModel based on the functionality of your current model. – camickr Jan 06 '15 at 16:59
  • @camickr i updated my question and used DefaultTableModel but still my addrow button does nothing. please see my edited question and tell me where am going wrong – Edijae Crusar Jan 08 '15 at 16:34
  • @AndrewThompson i used your advice and extended DefaultTableModel but still my addrow button does nothing on click. see my edited question and tell me where am wrong – Edijae Crusar Jan 08 '15 at 16:37
  • That code will not compile here. Please review what an MCVE/SSCCE is.. – Andrew Thompson Jan 08 '15 at 16:41
  • 1
    You are missing the point of using the DefaultTableModel. It already implements an `addRow(...)` method. There is no need for you to create your own. It also implements methods like getColumnNames(), getValueAt(), setValueAt() etc so there is no need to implement those methods either. Just use the default functionality and only override a method if you need to change the default behaviour. – camickr Jan 08 '15 at 17:07
  • @AndrewThompson i finally got it. see my answer below – Edijae Crusar Jan 09 '15 at 16:20
  • @camickr followed your advice and got it right. see my answer below – Edijae Crusar Jan 09 '15 at 16:21

2 Answers2

2

Some notes about your code:

  • You never should call any of the fireXxx() methods explicitely from the outside. Those are intended to be called internally by AbstractTableModel subclasses when needed. Note: IMHO those should be protected and not public, to avoid use them incorrectly. But for some reason they made them public.

  • Your addrow button seems to create a new table model that is not attached to any JTable so it makes no sense. Your table model should provide an addRow(...) method in order to add a new row to it. Most likely you will have to enlarge the two-dimensions array that is the table model's underlyinig data structure any time a row is added.

  • As @AndrewThompson already suggested, DefaultTableModel seems a good match to do what your table model does.

  • Check rows and columnscount properties initialization. It doesn't seem right to me.

On the other hand, you say in a comment:

I'm having trouble understanding the fireTableRowsInserted(int,int) method. the parameters themself and where or when to call the method

This method should be called within the addRow(...) that I've suggested you to create in the second point. This method should enlarge the data structure and notify the TableModelListeners that a new row/s has/have been inserted. The parameters are the first and last indexes respectively. Tipically when you append a new single row to the end of the table model, then both first and last indexes are the same and the new size - 1 of the underlying data structure. Of course, several rows can be inserted and not necessarily at the end of the table model, so you have to figure out the appropriate indexes. See the example shown here which uses a List of custom objects as data structure.

Community
  • 1
  • 1
dic19
  • 17,821
  • 6
  • 40
  • 69
  • 19 when you speak of first and last indexes, what exactly do you mean? for example, i have 5 rows, when i want to add 6th row, will i say fireTableRowsUpdated(6,6)? – Edijae Crusar Jan 06 '15 at 13:31
  • In that case you should call `fireTableRowsInserted(5,5)` because of indexes in Java start counting from 0 (index 5 is the 6th row). Note I've notified rows ***inserted*** (not *updated*) because you want to *add* a new row actually. @gikarasojokinene – dic19 Jan 06 '15 at 13:35
  • therefore the first index signifies the row that is inserted and the second index represents the columns that the row should have. am i right? – Edijae Crusar Jan 06 '15 at 13:51
  • No, both indexes represent rows the first and the last respectively (you can add more than one row). For example, let's say you have 5 rows and you add 3 rows. Assuming you append all the new rows at the end of the data structure then you have to call `fireTableRowsInserted(5, 7)` because the first row added will be the 6th (index == 5) and the last one the 8th (index == 7). Always read [the API](http://docs.oracle.com/javase/7/docs/api/javax/swing/table/AbstractTableModel.html#fireTableRowsInserted%28int,%20int%29) carefully for more details. @gikarasojokinene – dic19 Jan 06 '15 at 13:57
  • that is one point gotten right. dont mind about the rows and columnscount properties initialization. i dont use them to specify getColumnCount and getRowCount() method – Edijae Crusar Jan 06 '15 at 14:16
  • i updated my question and used DefaultTableModel but still my addrow button does nothing. please see my edited question and tell me where am going wrong – Edijae Crusar Jan 08 '15 at 16:35
  • i finally got it. see my answer below – Edijae Crusar Jan 09 '15 at 16:24
0

According to your question,You want to add new rows every time the user clicks the addrow button. Achieve your objective by using DefaultTableModel without creating your own or overriding addrow method. in my example below,parameters in the DefaultTableModel constructor represents the initial rows(5) and columns(4) that the table will have where after execution, the user can add more rows by clicking the addrow button.

public class AddingNewRows extends JFrame {
 DefaultTableModel def;
JTable mytable;
JButton addrow;
//
public AddingNewRows(){
super("adding rows");

def=new DefaultTableModel(5,4);
mytable=new JTable(def);

JScrollPane scroll=new JScrollPane(mytable);
addrow=new JButton("ADD ROW");
//
JPanel buttonpanel=new JPanel();
buttonpanel.setLayout(new BoxLayout(buttonpanel,BoxLayout.X_AXIS));
buttonpanel.add(addrow);

//
add(scroll,BorderLayout.CENTER);
add(buttonpanel,BorderLayout.SOUTH);

addrow.addActionListener(new Myactions());

}

private class Myactions implements ActionListener{

@Override
public void actionPerformed(ActionEvent event){
if(event.getSource()==addrow){ 
Object[]newdata={"","","",""};
def.addRow(newdata);
} 
} 
}
public static void main(String[] args) {
AddingNewRows frame=new AddingNewRows();
frame.setVisible(true);
frame.setSize(400,400);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);

}

}
Edijae Crusar
  • 3,473
  • 3
  • 37
  • 74