JTableセルに時間カウンターを表示する効率的な方法
質問
タイムカウンターは、表の行の経過時間を秒単位で示します。理想的には、毎秒1回更新されます。テーブルモデル内の適切なデータをインクリメントしたり、イベント(行ごとに1つ)を起動したりすることができることはわかっています。より良い、より軽い方法はありますか?
解決
必要なのは:
- テーブルモデルの行の「年齢」をモデル化する方法。これは暗黙的に行うのが最善であるため、行の作成時間を1回だけ保存し、セル値が要求されたときの経過時間を計算します(Object getValueAt(row、column))。
- 毎秒テーブル変更イベントを起動する(デーモン)スレッド。行ごとに1つのイベントを発生させる必要はありませんが、代わりに列全体の更新を通知するイベントを発生させることができます。
表モデルの擬似コードは次のとおりです。
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);
}
}
その後、スレッドは、 'row age'列に対して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の粒度が更新が必要なセルのみをカバーしている限り(あなたの場合:行経過時間の列のみ)、これを実現する最も効率的な方法です。
所属していません StackOverflow