2010-12-14 73 views
1

想象我们有一个客户端/服务器多用户架构。任何时候用户都可以在他的JTable中添加一个新的TableRow。服务器得到通知并向所有客户端发送消息,因此他们的数据(也就是他们的桌面视图)也得到更新。这工作得很好,除非用户当前正在编辑表中的一行,而成为updateEvent。如何在编辑行时处理JTable的传入数据?

当新的tableRow超出当前编辑的用户行时,相应的单元格也会发生变化,但tableEditor不会注意到这一点,因此错误的行现在正在编辑和更改。

我创建了一个小例子来打破这种问题下来的一些代码,所以它可能是更容易跟着我

public class TableEventHandlingExample extends JPanel 
{ 
    static JFrame frame; 
    JTable  table; 

    public TableEventHandlingExample() 
    { 
    table = new JTable(new StandardTableModel(createTestData())); 

    final Thread thread = new Thread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
     try 
     { 
      while (true) 
      { 
      Thread.sleep(5000); 
      ((StandardTableModel) table.getModel()).addRow(new Data(4, "Vier"), 0); 
      } 
     } 
     catch (InterruptedException e) 
     { 
      e.printStackTrace(); 
     } 
     } 
    }); 

    thread.start(); 

    add(new JScrollPane(table)); 
    } 

    private List<Data> createTestData() 
    { 
    Data data1 = new Data(1, "Eins"); 
    Data data2 = new Data(2, "Zwei"); 
    Data data3 = new Data(3, "Drei"); 

    List<Data> dataList = new ArrayList<Data>(); 

    dataList.add(data1); 
    dataList.add(data2); 
    dataList.add(data3); 

    return dataList; 
    } 

    public static void main(String[] args) 
    { 
    frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setLayout(new BorderLayout()); 
    frame.setBounds(400, 400, 500, 500); 
    frame.add(new TableEventHandlingExample()); 
    frame.setVisible(true); 
    } 
} 


class StandardTableModel extends AbstractTableModel 
{ 
    List<Data> dataList; 

    public StandardTableModel(List<Data> dataList) 
    { 
    this.dataList = dataList; 
    } 

    @Override 
    public int getColumnCount() 
    { 
    return 2; 
    } 

    @Override 
    public int getRowCount() 
    { 
    return dataList.size(); 
    } 

    @Override 
    public boolean isCellEditable(int rowIndex, int columnIndex) 
    { 
    return true; 
    } 

    @Override 
    public Class<?> getColumnClass(int columnIndex) 
    { 
    if (columnIndex == 0) 
     return Integer.class; 
    return String.class; 
    } 

    @Override 
    public Object getValueAt(int rowIndex, int columnIndex) 
    { 
    if (columnIndex == 0) 
     return dataList.get(rowIndex).getId(); 

    return dataList.get(rowIndex).getName(); 
    } 

    @Override 
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) 
    { 
    Data data = dataList.get(rowIndex); 

    if (columnIndex == 0) 
     data.setId((Integer) aValue); 
    else 
     data.setName((String) aValue); 
    } 

    public void addRow(Data data, int index) 
    { 
    if (index > dataList.size()) 
    { 
     return; 
    } 

    dataList.add(index, data); 
    fireTableRowsInserted(index, index); 
    } 
} 


class Data 
{ 
    private int id; 
    private String name; 

    public Data(int id, String name) 
    { 
    this.id = id; 
    this.name = name; 
    } 

    public int getId() 
    { 
    return id; 
    } 

    public void setId(int id) 
    { 
    this.id = id; 
    } 

    public String getName() 
    { 
    return name; 
    } 

    public void setName(String name) 
    { 
    this.name = name; 
    } 

    @Override 
    public String toString() 
    { 
    return getName(); 
    } 
} 

伪造传入数据事件我使用一个线程,它增加了每5秒在位置1上新增一行。足以证明问题所在。

你有什么建议如何处理?只要表被编辑并且之后执行updateEvents,我是否应该拒绝updateEvents?但是当用户停留在5分钟的编辑模式下时,我会做什么?执行所有更新 - 他错过的事件可能会有点痛苦。你有没有其他想法?

预先感谢您! ymene

回答

2

你有没有考虑只设置单元格正在编辑正确的?在您的例子是相当容易,因为你总是在0

while (true) { 
     Thread.sleep(5000); 
     table.setEditingRow(table.getEditingRow() + 1); 
     ((StandardTableModel) table.getModel()).addRow(new Data(4, "Vier"), 0); } 

对于其中任意插入正在发生的情况下增加新的细胞(不是0行),你将不得不如果该行添加一个检查被插入的位置高于或低于当前正在编辑的位置

+0

不能相信这是简单的。非常感谢,这种解决方案将为我节省很多解决方法!不幸的是,我不能奖励你。它说我必须等待19个小时。但我不会忘记它! – crusam 2011-01-04 15:24:34

+0

不用担心。很高兴它对你有效 :) – 2011-01-05 10:23:11

0

我建议你使用SwingWorker!

它可以在EDT外执行一些工作,然后当其他用户添加行时,实时更新您的JTable!

问候

+0

谢谢您的回复。你会建议使用它们的时间点?为了刷新桌面,当事件发生时?把这些updateEvent放在swingworkers当然是有道理的,但我没看到这将如何解决这个问题,因为刷新表格时的编辑行仍然会改变,不是吗? – crusam 2011-01-04 11:14:42