• category: swing folder: TableHeaderFiller title: JTableHeaderの余白にヘッダを描画する tags: [JTableHeader, JTable, JScrollPane, JLayer] author: aterai pubdate: 2019-03-11T15:07:56+09:00 description: JTableHeaderの列幅を自動調整しない場合に発生する余白にダミーのヘッダを描画します。 image: https://drive.google.com/uc?id=1S2FqsLneoDTvkP2Xx-RLfsgLXGkFcduAaw

概要

JTableHeaderの列幅を自動調整しない場合に発生する余白にダミーのヘッダを描画します。

サンプルコード

class TableHeaderFillerLayerUI extends LayerUI<JScrollPane> {
  private final JTable tempTable = new JTable(
      new DefaultTableModel(new Object[] {""}, 0));
  private final JTableHeader filler = tempTable.getTableHeader();
  private final TableColumn fillerColumn = tempTable.getColumnModel().getColumn(0);

  @Override public void paint(Graphics g, JComponent c) {
    super.paint(g, c);
    if (c instanceof JLayer) {
      JScrollPane scroll = (JScrollPane) ((JLayer<?>) c).getView();
      JTable table = (JTable) scroll.getViewport().getView();
      JTableHeader header = table.getTableHeader();

      int width = header.getWidth();
      TableColumnModel cm = header.getColumnModel();
      for (int i = 0; i < cm.getColumnCount(); i++) {
        width -= cm.getColumn(i).getWidth();
      }

      Point pt = SwingUtilities.convertPoint(header, 0, 0, c);
      filler.setLocation(pt.x + header.getWidth() - width, pt.y);
      filler.setSize(width, header.getHeight());
      fillerColumn.setWidth(width);

      SwingUtilities.paintComponent(g, filler, tempTable, filler.getBounds());
    }
  }

  @Override public void installUI(JComponent c) {
    super.installUI(c);
    if (c instanceof JLayer) {
      ((JLayer<?>) c).setLayerEventMask(AWTEvent.COMPONENT_EVENT_MASK);
    }
  }

  @Override public void uninstallUI(JComponent c) {
    if (c instanceof JLayer) {
      ((JLayer<?>) c).setLayerEventMask(0);
    }
    super.uninstallUI(c);
  }

  @Override protected void processComponentEvent(
      ComponentEvent e, JLayer<? extends JScrollPane> l) {
    Component c = e.getComponent();
    if (c instanceof JTableHeader) {
      l.repaint(((JTableHeader) c).getBounds());
    }
  }
}
View in GitHub: Java, Kotlin

解説

  • 上: デフォルト
    • AUTO_RESIZE_OFFを設定し、列幅の自動調整を無効にしたJTable
  • 下: TableHeaderFiller
    • AUTO_RESIZE_OFFを設定し列幅の自動調整を無効にしたJTableJTableHeaderに余白が発生する場合、そこにダミーのヘッダ列を描画
    • ダミーヘッダの描画にはJLayerを使用
    • JLayerJTableJTableHeaderではなく親のJScrollPaneに設定
    • JLayerでダミーヘッダへのMouseEventなどは無効化、JTableHeaderがリサイズされてComponentEventが発生した場合はLayerUI#processComponentEvent(...)をオーバーライドしてダミーヘッダの幅を更新

参考リンク

コメント