Pregunta

Un contador de tiempo muestra la edad en segundos de una fila en la tabla. Idealmente, se actualizaría una vez por segundo. Sé que solo puedo incrementar los datos apropiados en el modelo de tabla, disparar los eventos (uno por fila), etc. ¡Parece una exageración! ¿Hay alguna forma mejor y más ligera?

¿Fue útil?

Solución

Lo que necesitas es:

  • una forma de modelar la 'edad' de la fila en su modelo de tabla. Esto se hace mejor de manera implícita, así que solo almacena el tiempo de creación de la fila una vez y calcula la edad en que se solicita el valor de la celda (Objeto getValueAt (fila, columna)).
  • Un hilo (daemon) que activa el evento de cambio de tabla cada segundo. No tiene que desencadenar un evento por fila, sino que puede desencadenar un evento que indique una actualización de toda la columna.

Aquí hay algunos pseudocódigo para el modelo de tabla:

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 
}

El modelo de tabla también debería ofrecer un método para el hilo, de modo que pueda activar un evento de cambio para la columna "edad de la fila":

la clase pública MyTableModel 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);
          }
   }

El hilo solo activará el método updateColumn (..) para la columna "edad de la fila". La invocación de este método debe hacerse en EventDispatchThread, esto se hace 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();

Mientras la granularidad de TableModelEvent solo cubra las celdas que necesitan actualizarse (en su caso: solo la columna con la antigüedad de la fila), es la forma más eficiente de realizar esto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top