Jtable Row delete

java, jtable, swing

Solution

Well, since I Don't have your all code so I am proceeding with a dummy Program for removing a record from `JTable` as well as the corresponding file. Watch the `removeRow` method defined in `MyTabeModel` class. It also covers the risk in case data couldn't be written on `file` (records.temp) after the `record` is deleted from `ArrayList`.

import javax.swing.table.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
public class TableFocus extends JFrame 
{
    MyTableModel model1;
    JTable table1;
    public void createAndShowGUI()
    {
        setTitle("JTables");
        Container c  = getContentPane();
        model1 = new MyTableModel();
        table1 = new JTable(model1);
        table1.setColumnSelectionAllowed(false);
        table1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JScrollPane jsTable1 = new JScrollPane(table1);
        c.add(jsTable1);
        JButton button = new JButton("Delete");
        button.addActionListener( new ActionListener()
        {
            public void actionPerformed(ActionEvent evt)
            {
                if (model1.getRowCount() > 0 && table1.getSelectedRow() != -1 )
                {
                    model1.deleteRow(table1.getSelectedRow());
                }
            }
        });
        add(button,BorderLayout.SOUTH);
        setSize(500,300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
    private class MyTableModel extends AbstractTableModel
    {
        String columns[] ;
        ArrayList<ArrayList<String>> data;
        public MyTableModel()
        {
            columns = new String[] {"Roll No.","Name"};
            prepareData();
        }
        private void prepareData()
        {
            data = new ArrayList<ArrayList<String>>();
            data.add(new ArrayList<String>(){{add("1");add("Michael");}});
            data.add(new ArrayList<String>(){{add("2");add("Derake");}});
            data.add(new ArrayList<String>(){{add("3");add("Archie");}});
        }
        @Override
        public String getColumnName(int columnIndex)
        {
            return columns[columnIndex];
        }
        @Override
        public int getRowCount()
        {
            return data.size();
        }
        @Override 
        public int getColumnCount()
        {
            return columns.length;
        }
        @Override
        public Object getValueAt(int row, int col)
        {
            return data.get(row).get(col);
        }
        @Override
        public void setValueAt(Object aValue, int rowIndex, int colIndex)
        {
            data.get(rowIndex).set(colIndex,(String)aValue);
            fireTableCellUpdated(rowIndex,colIndex);
        }
        @Override
        public boolean isCellEditable(int row, int col)
        {
            return false;
        }
        public void deleteRow(int row)
        {
            ArrayList<String> temp = data.get(row);//backup of value in case of IOException while writing to file
            BufferedWriter bfr = null;
            try
            {
                data.remove(row);
                //Write here the logic for repopulating file with new records.
                bfr = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("records.temp")));
                StringBuffer sBuffer = new StringBuffer();
                for (ArrayList<String> list : data)
                {
                    StringBuffer buf = new StringBuffer();
                    for (String val : list )
                    {
                        buf.append(val+"\t");
                    }
                    buf.replace(buf.length() - 1, buf.length(),"\n");
                    sBuffer.append(buf.toString());
                }
                bfr.write(sBuffer.toString());
                bfr.flush();
                bfr.close();
                fireTableRowsDeleted(row,row);
            }
            catch (Exception ex)
            {
                data.add(row,temp);//Rollback the delete from ArrayList
                ex.printStackTrace();
            }
            finally
            {
                if (bfr != null)
                {
                    try
                    {
                        bfr.close();
                    }
                    catch (Exception ex){}
                }
            }

        }
    }
    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater( new Runnable()
        {
            @Override
            public void run()
            {
                TableFocus ths = new TableFocus();
                ths.createAndShowGUI();
            }
        });
    }
}

UPDATE

Sometimes when i select a row in my table and click to delete button, more that one line has been deleted!

Well after going through your code I got to know the case when you have more than one row deleted. The case is: When you have more than one row in your file starting with the same `user ID` whom record you want to delete. For Example suppose you have entry like this in your file:

85     lo     ii     Female     2013/03/08
86     jkj     nmn     Female     2013/03/08
52     tyr     fgfg     Female     2013/03/08
86     jkj     pqr     Male      2013/03/08
7     dfdf     wew     Female     2013/03/08
47     zczc     asa     Female     2013/03/08
16     erw     www     Male     2013/03/08
83     gfg     dsd     Male     2013/03/08

Here userID `86` is contained in two rows (`row 2` and `row 4`).When you select `4th` row in your `JTable` to delete that particular record, It deletes `2nd` as well as `4th` row from your File. But in `JTable` the `2nd` row will keep showing because it is not refreshed with the new `File` till now. As soon as you refresh your `JTable` with new file , it shows both the rows deleted from there. To know why is it happening , have a look at your `RemoveUserFromFile(int index)` method `while loop` which is as follows:

while ((line = Ubr.readLine()) != null) //Reads the file till the end.
{
  if (line.trim().length() == 0) {
    continue;
  }
  if (!line.startsWith(String.valueOf(getValueAt(index, 0)))) //If line starts with 86 don't write it to new `Uoutput.txt`. so all lines starting with 86 will be ignored.
  {
     Upw.println(line);//Lines starting with 86 is not written.
   }
 }

I hope that now you got the solid reason for why sometimes deleting a record from `JTable` deletes two or more than two lines from your `file`. A workaround to this problem is to change your methods(`RemoveRow` and `RemoveUserFromFile`) in following way:(USE THIS MODIFIED CODE)

public void RemoveRow(int rowIndex) {
    UserInformation temp = Udata.get(rowIndex);//Keep it as back up so that you could reconsolidate it to ArrayList in case RemoveUserFromFile return false
    Udata.remove(rowIndex);//remove the element from Udata on temporary basis.
    if (RemoveUserFromFile(rowIndex)) 
    {
          fireTableRowsDeleted(rowIndex, rowIndex);
    } 
    else 
    {
        Udata.add(rowIndex,temp);//re-insert temp in ArrayList as the file updation is failed.
        JOptionPane.showMessageDialog(null, "Unable to delete");
    }
}

public boolean RemoveUserFromFile(int index) 
{
    File Mf = new File("AllUserRecords.txt");
    File Tf = new File("Uoutput.txt");
    PrintWriter Upw = null;
    try 
    {
        Upw = new PrintWriter(new FileWriter(Tf));
        for (UserInformation uino : Udata )
        {
            Upw.print(uino.toString());//Don't use Upw.println because the toString() method of UserInformation class is already using \n in last.
        }
        Upw.close();
        Mf.delete();
        Tf.renameTo(Mf);
        return true;
    } catch (FileNotFoundException e1) {
        return false;
    } catch (IOException ioe) {
        return false;
    }
    finally 
    {
        if (Upw != null)
        {
            try
            {
                Upw.close();
            }
            catch (Exception ex){}
        }
    }
}

I hope this fixed up your problem now...

NOTE: As a side note. I want to suggest you to stick with java naming convention while writing your codes. For Example: A class name always starts with a capital letter. A variable name always starts with small letter. And the constants (i.e Final variables) are having its all letters in capital. There are many others. Have a look at the official site of oracle.

Problem

I have am creating a library system program in java without database.(Directly with file). I have a strange problem with delete a line in my jtable (that delete from file too). Sometimes when i select a row in my table and click to delete button, more that one line has been deleted! also most time it work correctly!! My code: ``` public final class UserPage extends JFrame implements ActionListener { private AllUser userModel; private JTable uTable; JButton deleteUser; int selectedRow; public UserPage() { titleUserCount(); userModel = new AllUser(); uTable = new JTable(userModel); add(new JScrollPane(uTable), BorderLayout.CENTER); add(buttonPanels(), BorderLayout.PAGE_START); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(800, 600); this.setLocation(300, 60); this.setResizable(false); } public final JPanel buttonPanels() { JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); deleteUser = new JButton("Delete User"); deleteUser.addActionListener(this); buttonsPanel.add(deleteUser); return buttonsPanel; } public void titleUserCount() { AllUser userCount = new AllUser(); UserPage.this.setTitle("All User Information , Number Of user is : " + userCount.getRowCount()); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == deleteUser) { int selectedrow = uTable.getSelectedRow(); if (selectedrow >= 0) { userModel.RemoveRow(selectedrow); titleUserCount(); } else { JOptionPane.showMessageDialog(null, "No Row Selected"); } } } } ``` My model class: ``` public class AllUser extends AbstractTableModel { UserInformation uiS = new UserInformation(); String[] col = {"ID", "Fname", "Lname", "Gender", "Date"}; ArrayList<UserInformation> Udata = new ArrayList<UserInformation>(); public AllUser() { BufferedReader br = null; try { FileReader fr = new FileReader("AllUserRecords.txt"); br = new BufferedReader(fr); String line; while ((line = br.readLine()) != null) { if (line.trim().length() == 0) { continue; } Udata.add(initializeUserInfos(line)); } } catch (IOException e) { } finally { if (br != null) { try { br.close(); } catch (IOException ioe) { } } } } private UserInformation initializeUserInfos(String str) { UserInformation Uinit = new UserInformation(); String[] CellArray = str.split(" "); Uinit.setID(CellArray[0]); Uinit.setFname(CellArray[1]); Uinit.setLname(CellArray[2]); Uinit.setGender(CellArray[3]); Uinit.setDate(CellArray[4]); return Uinit; } public void RemoveRow(int rowIndex) { if (RemoveUserFromFile(rowIndex)) { Udata.remove(rowIndex); fireTableRowsDeleted(rowIndex, rowIndex); } else { JOptionPane.showMessageDialog(null, "Unable to delete"); } } public boolean RemoveUserFromFile(int index) { File Mf = new File("AllUserRecords.txt"); File Tf = new File("Uoutput.txt"); try { BufferedReader Ubr = new BufferedReader(new FileReader(Mf)); PrintWriter Upw = new PrintWriter(new FileWriter(Tf)); String line; while ((line = Ubr.readLine()) != null) { if (line.trim().length() == 0) { continue; } if (!line.startsWith(String.valueOf(getValueAt(index, 0)))) { Upw.println(line); } } Upw.close(); Ubr.close(); Mf.delete(); Tf.renameTo(Mf); return true; } catch (FileNotFoundException e1) { return false; } catch (IOException ioe) { return false; } } @Override public String getColumnName(int colu) { return col[colu]; } @Override public int getRowCount() { return Udata.size(); } @Override public int getColumnCount() { return col.length; } @Override public Object getValueAt(int rowIndex, int columnIndex) { UserInformation uinfoS = Udata.get(rowIndex); Object value = null; switch (columnIndex) { case 0: value = uinfoS.getID(); break; case 1: value = uinfoS.getFname(); break; case 2: value = uinfoS.getLname(); break; case 3: value = uinfoS.getGender(); break; case 4: value = uinfoS.getDate(); break; default: value = "..."; } return value; } @Override public void setValueAt(Object value, int rowIndex, int columnIndex) { UserInformation userInfo = Udata.get(rowIndex); switch (columnIndex) { case 0: userInfo.setID((String) value); break; case 1: userInfo.setFname((String) value); break; case 2: userInfo.setLname((String) value); break; case 3: userInfo.setGender((String) value); break; case 4: userInfo.setDate((String) value); break; } } } ``` User information Class: ``` public class UserInformation { private String Fname; private String Lname; private String ID; private String Gender; private String Date; public String getFname() { return Fname; } public void setFname(String fname) { this.Fname = fname; } public String getLname() { return Lname; } public void setLname(String lname) { this.Lname = lname; } public String getID() { return ID; } public void setID(String i_d) { this.ID = i_d; } public String getGender() { return Gender; } public void setGender(String gndr) { this.Gender = gndr; } public String getDate() { return Date; } public void setDate(String date) { this.Date = date; } @Override public String toString() { return ID + " " + Fname + " " + Lname + " " + Gender + " " + Date + "\n"; } } ``` My text File: ``` 85 lo ii Female 2013/03/08 86 jkj nmn Female 2013/03/08 52 tyr fgfg Female 2013/03/08 7 dfdf wew Female 2013/03/08 47 zczc asa Female 2013/03/08 16 erw www Male 2013/03/08 83 gfg dsd Male 2013/03/08 ```

Original source