【问题标题】:Remove JTable row that read file records删除读取文件记录的 JTable 行
【发布时间】:2012-12-27 22:57:18
【问题描述】:

我是 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完全成功。

【问题讨论】:

  • “但有错误” 什么错误?复制/粘贴堆栈跟踪。

标签: java swing file jtable


【解决方案1】:

首先,您没有将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()(可见索引)返回的索引转换为模型索引。如果您为您的JTable 设置RowSorter 或者将其留给标准实现:

table.setAutoCreateRowSorter(true);

【讨论】:

  • 您是否在 removeRows 方法中使用默认表模型?还是手动写这个方法?
  • 非常感谢,一个问题,如果我们的桌子很小,是否需要使用jscroolpane?
【解决方案2】:

您正在将表格直接添加到面板,而不使用JScrollPane。如果您这样做,您的表格标题将不可见, 所以代替这个,

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

这样做,

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

为什么要使用JScrollPane?阅读this

当用户选择一行并单击删除时,然后获取选定的行并将其从表列表中删除。当您使用 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;
}

如果删除是操作,则首先获取选定的行,然后调用 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.
  }
}

【讨论】:

    【解决方案3】:

    首先,您必须确保选择了某些内容:选择某些内容时,启用删除按钮。请查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: }

    您需要注册最后一个事件,以便在所选行发生更改时收到通知。添加您自己的侦听器以根据是否选择了一行来启用删除按钮,正如您在事件本身中看到的那样。

    请使用 DefaultTableModel 开始,因为它适用于 90% 的情况。

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

    当删除按钮被触发时,方法很简单:选择了一行,否则无法单击它:从 defaultTableModel 中删除选定的行号,最后但并非最不重要的是,我会简单地写下全部内容将数据模型模型复制到指定文件,因为表的模型保存了视图中确实显示的实际行。

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

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

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多