JTableのPaginationとSwingWorkerでの逐次読み込み
Total: 6146
, Today: 2
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JTable
でRowFilter
を使ったPagination
とSwingWorker
での逐次読み込みを行います。
Screenshot
Advertisement
サンプルコード
worker = new SwingWorker<String, List<Object[]>>() {
private int max = 2013;
@Override public String doInBackground() {
int current = 1;
int c = max / itemsPerPage;
int i = 0;
while (i < c && !isCancelled()) {
current = makeRowListAndPublish(current, itemsPerPage);
i++;
}
int m = max % itemsPerPage;
if (m > 0) {
makeRowListAndPublish(current, m);
}
return "Done";
}
private int makeRowListAndPublish(int current, int size) {
try {
Thread.sleep(500);
} catch (Exception ex) {
ex.printStackTrace();
}
List<Object[]> result = new ArrayList<Object[]>(size);
int j = current;
while (j < current + size) {
result.add(new Object[] {j, "Test: " + j, j % 2 == 0 ? "" : "comment..."});
j++;
}
publish(result);
return j;
}
@Override protected void process(List<List<Object[]>> chunks) {
for (List<Object[]> list : chunks) {
for (Object[] o : list) {
model.addRow(o);
}
}
int rowCount = model.getRowCount();
maxPageIndex = (rowCount / itemsPerPage) + (rowCount % itemsPerPage == 0 ? 0 : 1);
initFilterAndButton();
}
@Override public void done() {
String text = null;
if (isCancelled()) {
text = "Cancelled";
} else {
try {
text = get();
} catch (Exception ex) {
ex.printStackTrace();
text = "Exception";
}
}
table.setEnabled(true);
}
};
worker.execute();
// ...
private static final int itemsPerPage = 100;
private int maxPageIndex;
private int currentPageIndex = 1;
private void initFilterAndButton() {
sorter.setRowFilter(new RowFilter<TableModel, Integer>() {
@Override public boolean include(
Entry<? extends TableModel, ? extends Integer> entry) {
int ti = currentPageIndex - 1;
int ei = entry.getIdentifier();
return ti * itemsPerPage <= ei && ei < ti * itemsPerPage + itemsPerPage;
}
});
first.setEnabled(currentPageIndex > 1);
prev.setEnabled(currentPageIndex > 1);
next.setEnabled(currentPageIndex < maxPageIndex);
last.setEnabled(currentPageIndex < maxPageIndex);
field.setText(Integer.toString(currentPageIndex));
label.setText(String.format("/ %d", maxPageIndex));
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、RowFilterでJTableのページ分割に以下の変更を追加しています。
JTextField
に数値を入力して指定ページにジャンプ可能First(|<)
、Prev(<)
、Next(>)
、Last(>|)
などのリンクにJRadioButton
ではなくJButton
を使用SwingWorker
を使ってページ単位での逐次読み込み(最大ページの表示を更新)
SwingWorker
を使ってsqlite
からJTable
にデータを読み込むテスト
class LoadTask extends SwingWorker<String, List<Object[]>> {
private final int max;
private final int itemsPerPage;
protected LoadTask(int max, int itemsPerPage) {
super();
this.max = max;
this.itemsPerPage = itemsPerPage;
}
@Override public String doInBackground() {
File file = new File(
"C:/Users/.../AppData/Roaming/Mozilla/Firefox/Profiles/xx.default/places.sqlite");
String db = "jdbc:sqlite:/" + file.getAbsolutePath();
try (Connection conn = DriverManager.getConnection(db);
Statement stat = conn.createStatement()) {
int current = 1;
int c = max / itemsPerPage;
int i = 0;
while (i < c && !isCancelled()) {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
// ex.printStackTrace();
return "Interrupted";
}
current = load(stat, current, itemsPerPage);
i++;
}
int surplus = max % itemsPerPage;
if (surplus > 0) {
load(stat, current, surplus);
}
} catch (SQLException ex) {
// ex.printStackTrace();
return "Error";
}
return "Done";
}
private int load(Statement stat, int current, int limit) throws SQLException {
List<Object[]> result = new ArrayList<>(limit);
String q = String.format(
"select * from moz_bookmarks limit %d offset %d", limit, current - 1);
ResultSet rs = stat.executeQuery(q);
int i = current;
while (rs.next() && !isCancelled()) {
result.add(new Object[] {i, rs.getInt("id"), rs.getString("title")});
i++;
}
publish(result);
return current + result.size();
}
}