1

想象一下我们有一个客户端/服务器多用户架构。任何时候用户都可以在他的 JTable 中添加一个新的 TableRow。服务器收到通知并向所有客户端发送消息,因此他们的数据(意味着他们的表格视图)也得到更新。这工作得很好,除非用户当前正在编辑该表中的一行,同时成为一个更新事件。

当新的 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 分钟时,我该怎么办?执行他错过的所有更新事件可能会有点痛苦。您可能还有其他想法吗?

先感谢您!梅内

4

2 回答 2

2

您是否考虑过将正在编辑的单元格设置为正确的单元格?在您的示例中,这相当容易,因为您总是在 0 处添加新单元格。

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

对于发生任意插入的情况(不是在第 0 行),您必须添加检查插入的行是高于还是低于当前正在编辑的行

于 2011-01-04T12:03:10.523 回答
0

我建议你使用 SwingWorker !

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

最好的祝福

于 2010-12-22T11:48:06.093 回答