• category: swing folder: UpdateComboBoxItem title: JComboBoxのドロップダウンリスト中にあるアイテムの状態を更新する tags: [JComboBox, JList, JCheckBox, BasicComboPopup, DefaultComboBoxModel] author: aterai pubdate: 2017-06-12T17:11:53+09:00 description: JComboBoxのドロップダウンリスト中に設定されたアイテムの状態と描画を更新します。 image: https://drive.google.com/uc?export=view&id=1R3XuZTHSo7KbYggs0QI2iKVrHHBawo6f2A

概要

JComboBoxのドロップダウンリスト中に設定されたアイテムの状態と描画を更新します。

サンプルコード

class CheckableComboBoxModel<E> extends DefaultComboBoxModel<E> {
  protected CheckableComboBoxModel(E[] items) {
    super(items);
  }
  public void fireContentsChanged(int index) {
    super.fireContentsChanged(this, index, index);
  }
}

class CheckedComboBox4<E extends CheckableItem> extends CheckedComboBox<E> {
  protected CheckedComboBox4(ComboBoxModel<E> aModel) {
    super(aModel);
  }
  @Override protected void updateItem(int index) {
    if (isPopupVisible()) {
      E item = getItemAt(index);
      item.selected ^= true;
      ComboBoxModel m = getModel();
      if (m instanceof CheckableComboBoxModel) {
        ((CheckableComboBoxModel) m).fireContentsChanged(index);
      }
    }
  }
}
View in GitHub: Java, Kotlin

解説

JComboBoxBasicComboPopupに表示されるリストはJListを使用しているため、マウスでクリックされたアイテムの状態を更新(上記のサンプルではJCheckBoxの選択状態の切替)しても、セルレンダラーでの描画は更新されません(同じアイテムがクリックされたときは再描画しないため)。このサンプルでは、JComboBoxのアイテムの更新を描画に反映させるために以下のような方法をテストしています。

  1. setSelectedIndex(-1/idx)
  2. contentsChanged(...)
  3. repaint()
    • アイテム更新後、JComboBoxBasicComboPopupから取得したJListの両方のrepaint()メソッドを実行して、全体を再描画
    • 参考: JComboBoxにAnimated GIFを表示する
      • list.repaint(list.getCellBounds(index, index));を使用して再描画範囲を限定することも可能
  4. (remove/insert)ItemAt(...)
    • JComboBox#removeItemAt(...)でアイテムを削除、JComboBox#insertItemAt(...)で状態を更新したアイテムを元の場所に挿入、JComboBox#setSelectedIndex(...)で挿入されたアイテムを再選択することで描画を更新
  5. fireContentsChanged(...)
    • DefaultComboBoxModel#fireContentsChanged(...)メソッドはprotectedで直接呼び出せないため、これを呼び出し可能するラッパーComboBoxModelを作成してJComboBoxに設定し、クリックされたアイテムのみ描画を更新

参考リンク

コメント