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 ```