Эффективный способ отображения счетчика времени в ячейке JTable

StackOverflow https://stackoverflow.com/questions/609492

  •  03-07-2019
  •  | 
  •  

Вопрос

Счетчик времени показывает возраст строки в таблице в секундах.В идеале он должен обновляться один раз в секунду.Я знаю, что могу просто увеличить соответствующие данные в табличной модели, запустить события (по одному на строку) и т.д.Это кажется излишеством!Есть ли лучший, более легкий способ?

Это было полезно?

Решение

Все, что вам нужно, это:

  • способ смоделировать "возраст" строки в вашей табличной модели.Лучше всего это делать неявно, поэтому вы просто сохраняете время создания строки один раз и вычисляете возраст при запросе значения ячейки (Object getValueAt(строка, столбец)).
  • Поток (демона), который каждую секунду запускает событие изменения таблицы.Вам не обязательно запускать по одному событию на строку, но вместо этого вы можете запустить событие, сигнализирующее об обновлении всего столбца.

Вот некоторый псевдокод для табличной модели:

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 
}

Затем табличная модель должна также предлагать метод для потока, чтобы он мог запускать событие изменения для столбца "возраст строки":

открытый класс MyTableModel реализует 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);
          }
   }

Затем поток просто запускал бы метод updateColumn (..) каждую секунду для столбца "возраст строки".Вызов этого метода должен быть выполнен в EventDispatchThread, это делается с помощью SwingUtilities.invokeAndWait(..) или 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();

Пока детализация TableModelEvent охватывает только ячейки, которые необходимо обновить (в вашем случае:только столбец с возрастом строки), это наиболее эффективный способ реализовать это.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top