-3

我是 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 的读取记录非常成功。

4

3 回答 3

3

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

table.setAutoCreateRowSorter(true);
于 2012-12-27T23:09:35.667 回答
2

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

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

做这个,

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

为什么要使用JScrollPane?读这个

当用户选择一行并单击删除时,然后获取所选行并将其从表列表中删除。当您使用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.
  }
}
于 2012-12-28T02:57:20.040 回答
0

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

希望这可以帮助。

于 2012-12-30T11:52:15.627 回答