2012-12-27 96 views
-3

我是新的java,我有一个JTable,可以从txt文件中读取记录,并显示他们完美。 我想给我的JFrame添加一本新书,当用户在表上选择一行并点击“删除”按钮时,该行应该删除,删除的行记录也必须从txt文件中删除。 我的代码是这样的,但它有错误,没有看到JTable! :删除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中是完全成功的。

+1

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

回答

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()(它们是可见的索引)返回到模型索引。如果设置RowSorterJTable,或者你把它留给标准执行:

table.setAutoCreateRowSorter(true); 
+0

您是否在removeRows方法中使用默认表模型?或者手动编写此方法? – Sajad

+0

非常感谢,有一个问题,如果我们的桌子很小,是否需要使用jscroolpane? – Sajad

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. 
    } 
} 
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删除行的功能。

希望这会有所帮助。

+0

我不明白ValueChanged()方法... – Sajad