我是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的读取记录非常成功。
答案 0 :(得分: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
包装它。
接下来 - 您应该在添加/删除/ etc。
第二个问题是从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);
答案 1 :(得分: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.
}
}
答案 2 :(得分:0)
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 View:通常你永远不会改变视图,因为所有选择和滚动信息都会丢失,这是你不想要的。
当触发删除按钮时,方法是直接的:选择了一行,否则无法单击它:从defaultTableModel中删除所选的行号,最后但并非最不重要的是我只会写出整个内容数据模型模型对指定文件的影响,因为表的模型包含实际显示在视图中的实际行。
因此,请考虑模型模型和模型:视图仅实例化一次,打包滚动等,而不是按原样保留。通常也不会更改模型:通过添加和/或删除行来更改模型的内容。另外一个提示:总是使用渲染器:那些不这样做的人,在我看来,不了解如何使用JTables。
是的,您可以省略第一部分来监听选择更改:确定并弹出警告以指示问题。在稍后阶段添加侦听选择更改的功能,以启用和/或禁用JButton删除行。
希望这有帮助。