Question

imaginons que nous avons une architecture multi-utilisateur client / serveur. A chaque fois qu'un utilisateur est en mesure d'ajouter une nouvelle TableRow dans son JTable. Le serveur s'informe et envoie un message à tous les clients, de sorte que leurs données (ce qui signifie leur tableviews) OBTIENNENT mis à jour. Cela fonctionne parfaitement bien, à moins qu'un utilisateur est en train de modifier une ligne dans cette table, tout en devenant un UpdateEvent.

Lorsque la nouvelle tablerow est au-dessus de la ligne éditée de currenty de l'utilisateur, la cellule respective change aussi, mais l'avis ne marche pas tableEditor cela et donc la mauvaise ligne est beeing modifié et changé maintenant.

Je créé un petit exemple pour briser ce problème à quelques lignes de code, il pourrait être plus facile de me suivre:

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();
  }
}

Pour simuler les données-Events entrants j'ai utilisé un fil, ce qui ajoute une nouvelle ligne sur la position 1 toutes les 5 secondes. Assez bon pour montrer quel est le problème.

Avez-vous des suggestions pour gérer cette situation? Dois-je désavouer updateEvents aussi longtemps que la table sera éditée et exécuter les updateEvents plus tard? Mais que vais-je faire, quand les séjours de l'utilisateur en mode édition pour comme 5 minutes? Exectuting tous update-Events il pourrait obtenir un peu manqué douloureux. Avez-vous peut-être d'autres idées?

Merci d'avance! ymene

Était-ce utile?

La solution

Avez-vous envisagé de créer simplement la cellule en cours de modification à la bonne? Dans votre exemple, il est assez facile parce que vous êtes toujours à l'ajout de nouvelles cellules à 0.

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

Pour le cas où un insert arbitraire a lieu (non à la ligne 0), vous devez ajouter un contrôle si la ligne étant insérée est au-dessus ou en dessous de celle qui est actuellement en cours d'édition

Autres conseils

Je vous suggère d'utiliser SwingWorker!

Il permet de faire un travail en dehors du EDT, puis votre JTable est mis à jour en temps réel que d'autres utilisateurs ajoute la ligne!

Cordialement

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top