• category: swing folder: StandingsTables title: JTableの水平罫線を描画する位置とその色をソート条件に応じて変更する tags: [JTable, JLayer] author: aterai pubdate: 2023-09-18T02:49:36+09:00 description: JTableで順位表を作成し、上位と下位のグループ分けを表す水平罫線をJLayerを使用して描画するよう設定します。 image: https://drive.google.com/uc?id=1UqHCznb6MioPHeaYVnk1_lj3IKz4EM5w

概要

JTableで順位表を作成し、上位と下位のグループ分けを表す水平罫線をJLayerを使用して描画するよう設定します。

サンプルコード

class BorderPaintLayerUI extends LayerUI<JScrollPane> {
  @Override public void paint(Graphics g, JComponent c) {
    super.paint(g, c);
    JTable table = getTable(c);
    RowSorter<? extends TableModel> sorter = table == null ? null : table.getRowSorter();
    if (Objects.nonNull(sorter)) {
      List<? extends RowSorter.SortKey> keys = sorter.getSortKeys();
      int column = keys.isEmpty() ? -1 : keys.get(0).getColumn();
      if (column <= 0 || column == 9) {
        Graphics2D g2 = (Graphics2D) g.create();
        boolean b1 = column == 0 && keys.get(0).getSortOrder() == SortOrder.ASCENDING;
        boolean b2 = column == 9 && keys.get(0).getSortOrder() == SortOrder.DESCENDING;
        if (column < 0 || b1 || b2) {
          g2.setPaint(Color.GREEN.darker());
          g2.draw(makeUnderline(c, table, 2));
          g2.setPaint(Color.BLUE.darker());
          g2.draw(makeUnderline(c, table, 6));
          g2.setPaint(Color.RED.darker());
          g2.draw(makeUnderline(c, table, 20));
        } else {
          g2.setPaint(Color.GREEN.darker());
          g2.draw(makeUnderline(c, table, 22 - 2));
          g2.setPaint(Color.BLUE.darker());
          g2.draw(makeUnderline(c, table, 22 - 6));
          g2.setPaint(Color.RED.darker());
          g2.draw(makeUnderline(c, table, 22 - 20));
        }
        g2.dispose();
      }
    }
  }

  private static JTable getTable(Component c) {
    JTable table = null;
    if (c instanceof JLayer) {
      Component c1 = ((JLayer<?>) c).getView();
      if (c1 instanceof JScrollPane) {
        table = (JTable) ((JScrollPane) c1).getViewport().getView();
      }
    }
    return table;
  }

  private static Line2D makeUnderline(JComponent c, JTable table, int idx) {
    Rectangle r0 = table.getCellRect(idx - 1, 0, false);
    Rectangle r1 = table.getCellRect(idx - 1, table.getColumnCount() - 1, false);
    Rectangle r = SwingUtilities.convertRectangle(table, r0.union(r1), c);
    return new Line2D.Double(r.getX(), r.getMaxY(), r.getMaxX(), r.getMaxY());
  }
}
View in GitHub: Java, Kotlin

解説

  • JTableで順位表を作成し、デフォルトの罫線を非表示化
  • JTableを配置するJScrollPaneJLayerでラップし、LayerUI#paint(...)をオーバーライド
    • ソートなし、または0列目(順位)が昇順ソート、9列目(勝ち点)が降順ソートされている場合、1行目(2位)セル、5行目(6位)セル、、19行目(20位)セルの下部に罫線を描画
    • 0列目(順位)が降順ソート、または9列目(勝ち点)が昇順ソートされている場合、2行目(21位)セル、16行目(6位)セル、、20行目(2位)セルの上部に罫線を描画
    • それ以外がソートされている場合は罫線を描画しない

  • セルの背景色はJLayerではなくJTable#prepareRenderer(...)をオーバーライドして順位、奇数・偶数行などに応じて変更
  • 8列目の得失点は正の値の先頭に+を付けて文字列で表示するセルレンダラーを設定
  • たとえば勝点が同じ場合は得失点でソートするような処理には未対応

参考リンク

コメント