Question

Un compteur de temps indique l’âge en secondes d’une ligne du tableau. Idéalement, il serait mis à jour une fois par seconde. Je sais que je peux simplement incrémenter les données appropriées dans le modèle de table, déclencher les événements (un par ligne), etc. Il semble exagéré! Y a-t-il un moyen meilleur et plus léger?

Était-ce utile?

La solution

Ce dont vous avez besoin est:

  • une façon de modéliser "l'âge" de la ligne dans votre modèle de table. Ceci est mieux fait implicitement. Vous ne devez donc enregistrer que l'heure de création de la ligne et calculer l'âge auquel la valeur de la cellule est demandée (Object getValueAt (ligne, colonne)).
  • Un thread (démon) qui déclenche l'événement de changement de table toutes les secondes. Vous n'avez pas besoin de déclencher un événement par ligne, mais vous pouvez déclencher un événement qui signale une mise à jour complète de la colonne.

Voici un pseudocode pour le modèle de table:

public Object getValueAt (int rowIndex, int columnIndex) {

    // if it's the column with the 'row age', calculate the age and return it
    long rowAgeMs = System.currentTimeMs() - getCreationTime(rowIndex);

   // return the age in milliseconds, or a date, or a formatted time string 
}

Le modèle de table devrait alors également proposer une méthode pour le thread, de sorte qu'il puisse déclencher un événement change pour la colonne "age de la ligne":

La classe publique MyTableModel implémente TableModel {

   private final List<TableModelListener> listeners = new LinkedList<TableModelListener>();

   public void addTableModelListener (TableModelListener l) {
          listeners.add(l);
   }

   public void removeTableModelListener (TableModelListener l) {
          listeners.remove(l);
   }

   public void updateColumn (int column) {
          TableModelEvent evt = new TableModelEvent(this, 0, Math.max(0, getRowCount() - 1), column);
          for (TableModelListener listener : listeners) {
                 listener.tableChanged(evt);
          }
   }

Le thread ne déclencherait alors que la méthode updateColumn (..) chaque seconde pour la colonne "âge de la ligne". L'appel de cette méthode doit être effectué dans EventDispatchThread, à l'aide de SwingUtilities.invokeAndWait (..) ou de SwingUtilities.invokeLater (..).

Thread rowAgeUpdater = new Thread() {

        @Override
        public void run () {
            while (isAlive()) {
                try {

                    long time = System.currentTimeMillis();
                    long sleepTime = (time / 1000 + 1) * 1000 - time;
                    Thread.sleep(sleepTime);

                    SwingUtilities.invokeAndWait(new Runnable() {
                        public void run () {
                            model.updateColumn(ROW_AGE_COLUMN_INDEX);
                        }
                    });

                } catch (Exception e) {
                    return;
                }

            }
        }
    };
    rowAgeUpdater.setDaemon(true);
    rowAgeUpdater.setPriority(Thread.MIN_PRIORITY);
    rowAgeUpdater.start();

Tant que la granularité de TableModelEvent ne couvre que les cellules qui doivent être mises à jour (dans votre cas, seule la colonne avec l'âge de la ligne), c'est le moyen le plus efficace de le réaliser.

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