Domanda

Un contatore del tempo mostra l'età in secondi di una riga nella tabella. Idealmente, sarebbe aggiornato una volta al secondo. So di poter semplicemente incrementare i dati appropriati nel modello di tabella, attivare gli eventi (uno per riga), ecc. Sembra eccessivo! C'è un modo migliore e più leggero?

È stato utile?

Soluzione

Ciò di cui hai bisogno è:

  • un modo per modellare l '"età" della riga nel modello di tabella. Questa operazione viene eseguita in modo implicito, quindi è sufficiente memorizzare il tempo di creazione della riga una volta e calcolare l'età in cui viene richiesto il valore della cella (Object getValueAt (riga, colonna))
  • Un thread (daemon) che genera l'evento di cambio tabella ogni secondo. Non è necessario generare un evento per riga, ma è possibile generare un evento che segnala un aggiornamento di un'intera colonna.

Ecco alcuni pseudocodici per il modello di tabella:

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 
}

Il modello di tabella dovrebbe quindi offrire anche un metodo per il thread, in modo che possa generare un evento change per la colonna 'row age':

MyTableModel di classe pubblica implementa 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);
          }
   }

Il thread attiverà quindi il metodo updateColumn (..) ogni secondo per la colonna 'row row'. L'invocazione di questo metodo dovrebbe essere effettuata in EventDispatchThread, questo avviene usando SwingUtilities.invokeAndWait (..) o 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();

Finché la granularità di TableModelEvent copre solo le celle che devono essere aggiornate (nel tuo caso: solo la colonna con l'età della riga), è il modo più efficiente per realizzarlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top