删除读取文件记录的JTable行



我是新的java,我有一个JTable,可以从txt文件中读取记录,并完美地显示它们。我想向我的JFrame添加一本新书,当用户选择表上的一行并单击"删除"按钮时,该行应该删除,删除的行记录也必须从txt文件中删除。我的代码是这样的,但它有错误,没有看到JTable !:

public class CopyOfAllUserTable extends AbstractTableModel {
Vector data;
Vector column;
public static void main(String[] args){
    new CopyOfAllUserTable();
}
public CopyOfAllUserTable() {
        String line;
        data = new Vector();
        column = new Vector();
        try {
        FileInputStream fis = new FileInputStream("D:\AllUserRecords.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));
      StringTokenizer st1 = new StringTokenizer(br.readLine(), " ");
              while (st1.hasMoreTokens())
               column.addElement(st1.nextToken());
                while ((line = br.readLine()) != null) {
                       StringTokenizer st2 = new StringTokenizer(line, " ");
                        while (st2.hasMoreTokens())
                                data.addElement(st2.nextToken());
                }
                br.close();
        } catch (Exception e) {
                e.printStackTrace();
        }
    final JFrame frame1=new JFrame();
     JTable table=new JTable(data,column);
    JButton button1=new JButton("Delete");

    button1.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
           DefaultTableModel model=new DefaultTableModel(data, column);
           JTable table=new JTable(model);
        }
    });

    JPanel panel=new JPanel();
    panel.add(table);
    panel.add(button1);
    frame1.add(panel);
    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame1.setBounds(200, 80, 600, 500);
    frame1.setVisible(true);
    frame1.setEnabled(true);

}
public int getRowCount() {
        return data.size() / getColumnCount();
}
public int getColumnCount() {
        return column.size();
}
public Object getValueAt(int rowIndex, int columnIndex) {
        return (String) data.elementAt((rowIndex * getColumnCount())
                        + columnIndex);
}
}

我的问题是在删除行,读取记录从文件到jtable是完全成功的。

首先,您没有将JTable添加到框架的内容中。

对于像:frame.getContentPane()JPanel这样的容器,你应该使用它们的#add(...)方法来添加子组件。

例如:

 final JPanel panel=new JPanel(new BorderLayout());
 button1.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
       DefaultTableModel model=new DefaultTableModel(data, column);
       JTable table=new JTable(model);
       panel.add(new JScrollPane(table));
       panel.revalidate();
    }
});

注意JPanel的默认布局是FlowLayout。第二件事-如果你想在JTable中有标题和滚动,你需要用JScrollPane来包装它。接下来,您应该在添加/删除/等后重新验证面板。

第二个问题是从JTable中删除行。我通常写一个方法来处理它:

protected void removeRows(final int[] rows) {
    int modelRows[] = new int[rows.length];
    for(int i = 0; i < rows.length; ++i) {
        modelRows[i] = table.convertRowIndexToModel(rows[i]);
    }
    Arrays.sort(modelRows);
    for(int i = modelRows.length - 1; i >= 0; --i) {
        int row = modelRows[i];
        model.removeRow(row);
    }
    model.fireTableDataChanged();
}

convertRowIndexToModel方法将JTable#getSelectedRows()JTable#getSelectedRow()返回的索引(它们是可见索引)转换为模型索引。如果您将RowSorter设置为JTable,或者您将其留给标准实现:

table.setAutoCreateRowSorter(true);

您直接将表添加到面板中,而不使用JScrollPane。如果这样做,表头将不可见。所以不用这个

JPanel panel=new JPanel();
    panel.add(table);

,

JPanel panel=new JPanel();
panel.add(new JScrollPane(table));

为什么要使用JScrollPane ?读这。

当用户选择一行并单击delete时,则获取选中的行并将其从表列表中删除。由于您使用的是AbstractTableModel,那么您必须编写自定义的removeRow(..)方法来执行此操作。

例子:

private boolean removeSelectedRow(int row) {
    // Remove the row from the list that the table is using.
    dataList.remove(row);
    // You need to call fireXXX method to refresh the table model.
    fireTableDataChanged();
    return true;
   // If fail return false;
}

如果delete是操作,那么首先获取选中的行,然后像下面这样调用removeSelectedRow(int),

private void deleteRow() {
  int selectedRow = table.getSelectedRow();
  boolean deleteStatus = removeSelectedRow(selectedRow);
  // Only if the deletion is success then delete from the file.
  if(deleteStatus) {
    // Delete it from the file too.
  }
}

首先,您必须确保某些内容已被选中:当有某些内容已被选中时,请启用删除按钮。请查阅JTable java源代码@

http://developer.classpath.org/doc/javax/swing/JTable-source.html

和以下代码:

1331: /**
1332: * Receives notification when the row selection changes and fires
1333: * appropriate property change events.
1334: *
1335: * @param event the list selection event
1336: */
1337: public void valueChanged(ListSelectionEvent event)
1338: {
1339: firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
1340: Boolean.FALSE, Boolean.TRUE);
1341: int r = getSelectedRow();
1342: int c = getSelectedColumn();
1343: if (r != lastSelectedRow || c != lastSelectedColumn)
1344: {
1345: Accessible o = getAccessibleAt(lastSelectedRow,lastSelectedColumn);
1347: Accessible n = getAccessibleAt(r, c);
1348: firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, o, n);
1350: lastSelectedRow = r;
1351: lastSelectedColumn = c;
1352: }
1353: }

您需要注册最后一个事件,以便在所选行的更改时得到通知。添加您自己的侦听器,以根据是否选中一行来启用deletebutton,如您在事件本身中所看到的。

请使用DefaultTableModel开始,因为它将在90%的情况下工作。

并且任何更改都应用于tabledata模型,它将自动传播到JTable视图:通常你永远不会改变视图,因为所有的选择和滚动信息都丢失了,这是你不想要的。

当delete按钮被触发时,方法是直接的:有一行被选中,否则不可能单击它:从defaultTableModel中删除选中的行号,最后但并非最不重要的是,我将简单地将数据模型模型的整个内容写入指定文件,因为表的模型包含确实显示在视图中的实际行。

所以请从模型和模型的角度来考虑:视图只实例化一次,打包滚动等,然后你让它们保持原样。模型通常也不会被更改:您可以通过添加或删除行来更改模型的内容。另一个提示:使用always渲染器:在我看来,那些不使用渲染器的人不理解如何使用JTables。

是的,您可以省略第一部分以侦听选择更改:当然,并弹出警告以指出问题。在稍后的阶段添加侦听选择更改的功能,以启用或禁用JButton删除行。