3

データベースなしでJavaでライブラリシステムプログラムを作成しています(ファイルで直接)。

jtable の行を削除すると奇妙な問題が発生します (ファイルからも削除されます)。

テーブルの行を選択して [削除] ボタンをクリックすると、複数の行が削除されることがあります。

また、ほとんどの場合、正しく動作します!!

私のコード:

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");
            }   
        }   
    }   
}

私のモデルクラス:

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;
        }
    }
}

ユーザー情報クラス:

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";
    }
}

私のテキストファイル:

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
4

3 に答える 3

5

ここで変更するいくつかのこと:

  • あなたのRemoveRow中で、持っているだけUdata.remove(rowIndex); fireTableRowsDeleted(rowIndex, rowIndex);
  • あなたのRemoveUserFromFileメソッドを、あなたのメソッドをsaveToFile(File file)単純に反復しUdata、指定されたfile

補足:

  • Java 命名規則に従います (変数とメソッドは小文字で始まります!)。そのため、コードは非常に読みにくくなっています。
  • titleUserCount()テーブル内のエントリをカウントするためだけに、毎回新しい TableModel を再作成しています。あなたは単に使用することができますuserModel.getRowCount()
  • 延長する必要はありませんJFrame
于 2013-03-08T17:31:45.517 に答える
4

さて、私はあなたのすべてのコードを持っていないので、レコードJTableと対応するファイルを削除するためのダミープログラムを進めています。クラスremoveRowで定義されたメソッドを監視します。から削除された後、(records.temp) にMyTabeModelデータを書き込めなかった場合のリスクもカバーします。filerecordArrayList

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();
            }
        });
    }
}

アップデート

テーブルの行を選択して [削除] ボタンをクリックすると、複数の行が削除されることがあります。

コードを調べた後、複数の行が削除された場合を知りました。ケースは次のとおり です。ファイルに複数の行があり、user ID削除したいレコードが同じである場合。
たとえば、ファイルに次のようなエントリがあるとします。

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

ここで、userID86は 2 つの行 (row 2と) に含まれています。その特定のレコードを削除するために行row 4を選択すると、ファイルから行と同様に削除されます。ただし、今まで新しいものに更新されていないため、行内は表示され続けます。with new fileを更新するとすぐに、そこから削除された両方の行が表示されます。 なぜそれが起こっているのかを知るには、次のような方法を見てください:4thJTable2nd4thJTable2ndFileJTable
RemoveUserFromFile(int index)while loop

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.
   }
 }

からレコードをJTable削除すると、 から 2 つ以上の行が削除されることがありますfile
この問題の回避策は、メソッド (RemoveRowおよびRemoveUserFromFile) を次のように変更することです:(この変更されたコードを使用してください)

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){}
        }
    }
}

これで問題が解決したことを願っています...

注: 補足として。コードを書くときは、Java の命名規則に従うことをお勧めします。例: クラス名は常に大文字で始まります。変数名は常に小文字で始まります。また、定数 (つまり、Final 変数) は、すべての文字が大文字になっています。他にもたくさんあります。オラクルの公式サイトを見てみましょう。

于 2013-03-16T17:11:42.847 に答える
3

このテスト:

if (!line.startsWith(String.valueOf(getValueAt(index, 0)))) {

これは、 3 のような IDremoveUserFromFile()30、31、35、301など (3 で始まるほとんどすべて) に一致するような文字列テストであるためです。

この特定のテストを修正するには、おそらく ID を整数として比較する必要があります。まず、次のような行から番号を引き出します。

Integer.parseInt(line.split("\\s")[0]);

次に、その数値を表の数値と比較しgetValueAtます。

他の回答の方が全体的なデザインが優れていることに注意してください。これは、特定の問題を対象とすることだけを目的としています。

于 2013-03-18T11:18:08.260 に答える