1

I have a jtable that keep book file records and sho them.

I create a "Borrow" jbutton that when clicked to a row that not borrowed, The "Borrow Status" of that row should change to "Yes".

I use this codes, but did not changed!

public class user_AllBooks extends AbstractTableModel{
BookInformation book_info=new BookInformation();
String[] columns=new String[]{"Book Name","Book Date", "Book ID","Borrow Status"};
ArrayList<BookInformation> bData=new ArrayList<BookInformation>();

public user_AllBooks(){
    try{
        BufferedReader br=new BufferedReader(new FileReader("AllBookRecords.txt"));
        String line;
        while((line = br.readLine()) != null){
            bData.add(initializeBookData(line));
        }
        br.close();
    }
    catch(IOException ioe){

    }
}

public BookInformation initializeBookData(String myline){
    BookInformation book_infos=new BookInformation();
    String[] celledLine=myline.split("     ");
    book_infos.setBookName(celledLine[0]);
    book_infos.setBookDate(celledLine[1]);
    book_infos.setBookID(celledLine[2]);
    book_infos.setBorrowStatus(celledLine[3]);
    return book_infos;
}

@Override
public String getColumnName(int col){
    return columns[col];
}

@Override
public int getRowCount() {
    if(bData != null){
        return bData.size();
    }
    else{
        return 0;
    }
}

@Override
public int getColumnCount() {
    return columns.length;
}

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    BookInformation bookInf=bData.get(rowIndex);
    Object value;

    switch(columnIndex){     
        case 0:
            value=bookInf.getBookName();
            break;
        case 1:
            value=bookInf.getBookDate();
            break;
        case 2:
            value=bookInf.getBookID();
            break;
        case 3:
            value=bookInf.getBorrowStatus();
            break;
        default :
            value="...";
    }
    return value;    
}
}

Second Class:

public class user_AllBooksM extends JFrame implements ActionListener{
user_AllBooks uAllBooks=new user_AllBooks();
final JTable bTable=new JTable(uAllBooks);
JButton borrowButton;
public user_AllBooksM(){
    setTitle("All Books");
    exitButton=new JButton("Exit");
    borrowButton=new JButton("Borrow");
    borrowButton.addActionListener(this);
    JPanel Bpanel=new JPanel();
    Bpanel.setLayout(new FlowLayout());
    JScrollPane sp=new JScrollPane(bTable);
    Bpanel.add(sp);
    Bpanel.add(borrowButton);
    this.add(Bpanel);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setBounds(300, 60, 550, 550);
    this.setResizable(false);
    this.setVisible(true);
}

@Override
public void actionPerformed(ActionEvent event) {
        borrowInitialize(bTable.getSelectedRow());  
}

public void  borrowInitialize(int row){
    if(uAllBooks.getValueAt(row, 3).equals("yes")) {
        JOptionPane.showMessageDialog(null, "This Book Was Borrowed");
    }
    else{
        uAllBooks.setValueAt("Yes", row, 3);
        uAllBooks.fireTableRowsUpdated(row, row);
    }
}

public static void main(String[] args){
    new user_AllBooksM();
}

}

Thanks.

Sajad
  • 2,273
  • 11
  • 49
  • 92

3 Answers3

4

To override setValueAt You should use:

@Override
public void setValueAt(Object value, int row, int col)
{
    BookInformation book_infos = bData.get(row);
    if (col==0)
    book_infos.setBookName((String)value);
    else if (col==1)
    book_infos.setBookDate((String)value);
    else if (col==2)
    book_infos.setBookID((String)value);
    else if (col==3)
    book_infos.setBorrowStatus((String)value);
    fireTableCellUpdated(row,col);
}

Define this method within class user_AllBooks

Vishal K
  • 12,976
  • 2
  • 27
  • 38
  • There should be no need to call fireTableDataChanged within setValueAt, because a normal editable table will do this for you. Might be better to have a setBorrowed method instead – MadProgrammer Feb 11 '13 at 19:03
  • @MadProgrammer : I add this method for the assurance that the changed value would surely be reflected in table. Is is unnecessary call? – Vishal K Feb 11 '13 at 19:07
  • Is this method specialy for setBorrow Or not? – Sajad Feb 11 '13 at 19:07
  • Is this method specialy for setBorrow Or not? – Sajad Feb 11 '13 at 19:07
  • @Sajjad-HiFriend: This method is generalized and can be used for changing value in any cell of JTable. – Vishal K Feb 11 '13 at 19:12
  • No, under the conditions that the OP wants to use it, it is required, but under normal table operations it isn't. The `JTable` would update the view automatically after calling the method. This means you will now get to update request, slowing down the application as the table could be painted twice. `fireTableDataChanged` is probably not the best choice here, as it will required the `JTable` to completely repaint itself. – MadProgrammer Feb 11 '13 at 19:19
  • @MadProgrammer: yes I thought about this point . And consequently removed that line from the method.. – Vishal K Feb 11 '13 at 19:22
  • I would mention to the OP that if they call setValueAt directly, they will need to update the view of the table themselves, otherwise the table will no know of the change – MadProgrammer Feb 11 '13 at 19:23
  • @MadProgrammer: I think OP is doing that in his code after setting the value of cell.. – Vishal K Feb 11 '13 at 19:25
  • So long as the next question isn't "why isn't my table changing when I change the value?" ;) – MadProgrammer Feb 11 '13 at 19:32
  • @MadProgrammer: hahahaha..yeah you are right :) . By the way I have seen your answers in many Questions . They are very innovative and exact. It is always a pleasure to read your answers.:) – Vishal K Feb 11 '13 at 19:35
  • +1, for implementing setValueAt(). As already suggested, you should NOT invoke fireTableDataChanged(). However, you SHOULD invoke fireTableCellUpdated(). – camickr Feb 11 '13 at 23:06
  • @VishalK When i do this, it changed in jtable, but when run program again' it was not changed, because not changed in text file – Sajad Feb 12 '13 at 12:45
  • @Sajjad-HiFriend What is the format of your file? is it in csv form or any other?? – Vishal K Feb 12 '13 at 17:04
  • You could use FileWriter to write the contents of JTable in the same File. Files contents couldnot be changed dynamically while you are reading it. My suggestion is that , when you done with changing the cell values of JTable , fire an actionListener and write all the contents of JTable on that file using FileWriter or BufferedWriter .. – Vishal K Feb 12 '13 at 19:04
2

You have overridden the getValueAt method. So it always returns value from your bData arraylist.

public Object getValueAt(int rowIndex, int columnIndex) {
    BookInformation bookInf=bData.get(rowIndex);

So you need to implement the setValueAt method also in your table model so change actual data in the bData arraylist.

Also note that bTable.getSelectedRow() will give you selected row in terms of the view. In model the index might be different if the table is sorted.

Ashwinee K Jha
  • 9,187
  • 2
  • 25
  • 19
2

You could use TableModel#setValueAt, but you would also become responsible for updating the table, which breaks the MCV model.

Instead, you could add a setBorrowed method to your user_AllBooks class.

public void setBorrowed(int row, boolean borrowed) {
    BookInformation book = bData.get(row);
    book.setBorrowedState(borrowed);
    fireTableCellUpdated(row, 3);
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    -1, This IS the job of the setValueAt() method. First it updates the data structure containing the data of the model. Then the TableModel is responsible for notifying the table when the contents of a cell are changed. The TableModel does this by invoking the fireTableCellUpdated(...) method the same as you have done here. This could be considered a convenience method that invokes setValueAt(borrowed, row, 3). – camickr Feb 11 '13 at 23:03
  • @camickr Thank you for at least telling me why I'm a douche bag ;) - It is appreciated. I had a look at `DefaultTableModel` and it does, indeed, use `fireTableCellUpdated`. My concern is (and I hope you can help me here), I've never had to call it when using a `AbstractTableModel` as the table seems to automatically update itself. Is it overkill to fire another event, potentially cause a double repaint?? (Sure in most cases it's a single cell, just curious on another view point) – MadProgrammer Feb 12 '13 at 00:30
  • Data from the editor is saved to the model using the setValueAt(...) method. Then the editor is removed from the table which results in the cell being repainted. So you are correct that the table will be repainted with the new value even if the setValueAt(...) method doesn't fire the update event. However, it is definitely the responsibilty of the Model to notify the View when data changes. The double repaint is caused by the way the JTable implements the editing code. – camickr Feb 12 '13 at 02:34
  • @camickr I agree it's the responsibility of the model to fire the event (the fact that the abstract implementation uses `protected` methods is a good suggestion). Good or bad, that's what the answer states, the (good or bad) assumption I've made is `setValue` doesn't fire the event, in that case, we need a method in the model that can. The bad here is needing to cast the model, which is a valid concern, the good is knowing the model is providing notification back to the client (via `fireTabelCellUpdated`). If that makes sense :P (ps I don't think you're wrong - just seeking clarification) – MadProgrammer Feb 12 '13 at 02:41
  • setValueAt(...) should fire the event because any column in the table potentially can be updated. All updates to the model should be done through this method so it should fire the event. You should not need to create a special method for each column. Also the TableModel can be changed directly without using a table editor. So the setValueAt(...) method can't assume it was invoked from a table editor. I'm not sure what you mean about "casting the model"? – camickr Feb 12 '13 at 02:52
  • My example would you require the OP to cast the model to his `user_AllBooks` implementation before been able to use the `setBorrowed` method. Food for thought. Thanks – MadProgrammer Feb 12 '13 at 03:35
  • @MadProgrammer Ihave a question: Is this setValueAt(...) method for Jtable Of for abstractTableModel? – Sajad Feb 12 '13 at 08:24
  • If it is for abstracttablemodel, Why it is not with other three methods when implemention methods? – Sajad Feb 12 '13 at 08:25
  • @APoliteBoy Primarly about the table model, but the approach applies to both – MadProgrammer Feb 12 '13 at 08:28
  • @APoliteBoy the main reason, I would surmise, that setValue isn't an abstract method, is its not a requirement for table models to be editable – MadProgrammer Feb 12 '13 at 08:32
  • @MadProgrammer When i do this, it changed in jtable, but when run program again' it was not changed, because not changed in text file – Sajad Feb 12 '13 at 12:43
  • How change from "no" to "yes" in text file too? – Sajad Feb 12 '13 at 12:43
  • @Sajjad-HiFriend I would recommend that you raise another question. Let me know when you do so I can take a look – MadProgrammer Feb 12 '13 at 19:48
  • @MadProgrammer I ask this question in here: – Sajad Feb 12 '13 at 21:04
  • http://stackoverflow.com/questions/14837588/effect-jtable-cell-value-changing-on-text-file – Sajad Feb 12 '13 at 21:04