• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:RowFilterでJTableのページ分割
#navi(../)
*RowFilterでJTableのページ分割 [#sff7ad1c]
>編集者:[[Terai Atsuhiro>terai]]~
作成日:2007-11-05~
更新日:&lastmod;

#contents

**概要 [#p2b85520]
JDK 6 で導入されたRowFilterを使って、JTableの行をPagination風に分割して表示します。

#screenshot

**サンプルコード [#l576bdcf]
#code{{
void initLinkBox(Box box, TestModel m, final TableRowSorter<TestModel> sorter,
                 final int size, final int step) {
  m.setRowCount(0);
  for(int i=0;i<size;i++) {
    m.addTest(new Test("Name"+i, (i%2==0)?"":"comment..."));
  }
  box.removeAll();
  final ButtonGroup bg = new ButtonGroup();
  box.add(Box.createHorizontalGlue());
  box.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
  int page = 0;
  for(int i=0;i<size;i+=step) {
    page++;
    final int index = i;
    final JRadioButton rb = new JRadioButton(""+page);
    final RowFilter<TestModel,Integer> filter = new RowFilter<TestModel,Integer>() {
      @Override
      public boolean include(Entry<? extends TestModel, ? extends Integer> entry) {
        int ei = entry.getIdentifier();
        return (index<=ei && ei<index+step);
      }
    };
    rb.setForeground(Color.BLUE);
    rb.setUI(ui);
    rb.setAction(new AbstractAction(""+page) {
      @Override
      public void actionPerformed(ActionEvent e) {
        sorter.setRowFilter(filter);
      }
    });
    box.add(rb);
    bg.add(rb);
    if(i==0) {
      rb.setSelected(true);
      sorter.setRowFilter(filter);
private static int LR_PAGE_SIZE = 5;

private final TestModel model = new TestModel();
private final TableRowSorter<TestModel> sorter = new TableRowSorter<TestModel>(model);
private final Box box = Box.createHorizontalBox();
private void initLinkBox(final int itemsPerPage, final int currentPageIndex) {
    //assert currentPageIndex>0;
    sorter.setRowFilter(makeRowFilter(itemsPerPage, currentPageIndex-1));

    ArrayList<JRadioButton> l = new ArrayList<JRadioButton>();

    int startPageIndex = currentPageIndex-LR_PAGE_SIZE;
    if(startPageIndex<=0) startPageIndex = 1;

    int maxPageIndex = (model.getRowCount()/itemsPerPage)+1;
    int endPageIndex = currentPageIndex+LR_PAGE_SIZE-1;
    if(endPageIndex>maxPageIndex) endPageIndex = maxPageIndex;

    if(currentPageIndex>1)
      l.add(makePNRadioButton(itemsPerPage, currentPageIndex-1, "Prev"));
    for(int i=startPageIndex;i<=endPageIndex;i++) 
      l.add(makeRadioButton(itemsPerPage, currentPageIndex, i-1));
    if(currentPageIndex<maxPageIndex)
      l.add(makePNRadioButton(itemsPerPage, currentPageIndex+1, "Next"));

    box.removeAll();
    ButtonGroup bg = new ButtonGroup();
    box.add(Box.createHorizontalGlue());
    for(JRadioButton r:l) {
        box.add(r); bg.add(r);
    }
  }
    box.add(Box.createHorizontalGlue());
    box.revalidate();
    box.repaint();
    l.clear();
}
}}
#code{{
private JRadioButton makeRadioButton(final int itemsPerPage, final int current, final int target) {
    JRadioButton radio = new JRadioButton(""+(target+1));
    radio.setForeground(Color.BLUE);
    radio.setUI(ui);
    if(target+1==current) radio.setSelected(true);
    radio.addActionListener(new ActionListener() {
        @Override public void actionPerformed(ActionEvent e) {
            initLinkBox(itemsPerPage, target+1);
        }
    });
    return radio;
}
private JRadioButton makePNRadioButton(final int itemsPerPage, final int target, String title) {
    JRadioButton radio = new JRadioButton(title);
    radio.setForeground(Color.BLUE);
    radio.setUI(ui);
    radio.addActionListener(new ActionListener() {
        @Override public void actionPerformed(ActionEvent e) {
            initLinkBox(itemsPerPage, target);
        }
    });
    return radio;
}
private RowFilter<TestModel,Integer> makeRowFilter(final int itemsPerPage, final int target) {
    return new RowFilter<TestModel,Integer>() {
        @Override
        public boolean include(Entry<? extends TestModel, ? extends Integer> entry) {
            int ei = entry.getIdentifier();
            return (target*itemsPerPage<=ei && ei<target*itemsPerPage+itemsPerPage);
        }
    };
}
}}
-&jnlp;
-&jar;
-&zip;

**解説 [#uc3887af]
上記のサンプルは、検索サイトなどでよく使われている、PaginationをJTableで行っています。

ただし、ページ数が大量にある場合の処理や、前へ、次へなどの実装は無視して、ある位置から一定の行数だけ表示するフィルタを予め作成し、これを上部のJRadioButton((BasicRadioButtonUIを継承して見た目だけリンク風になるよう変更している))で切り替えるだけになっています。
%%ただし、ページ数が大量にある場合の処理や、前へ、次へなどの実装は無視して、%%

また、モデルのインデックス順でフィルタリングしているため、ソートを行っても、表示される行の順番が変化するだけになります。
ある位置から一定の行数だけ表示するフィルタを予め作成し、これを上部のJRadioButton((BasicRadioButtonUIを継承して見た目だけリンク風になるよう変更している))で切り替えています。

また、モデルのインデックス順でフィルタリングしているため、ソートを行っても表示される行の範囲内で変化します。

//**参考リンク
**コメント [#n7c8e61e]
- Prev、Next ボタンなどを追加して、Google風のPaginationを行うように変更しました。 -- [[terai]] &new{2008-03-26 (水) 20:28:31};

#comment