概要

JComboBoxのセルレンダラーにJTextFieldを使用して、エディタで入力中の文字列とマッチするリストアイテム内の文字列をハイライト表示します。

スクリーンショット

Swing/ComboBoxHighlightFilter.png

サンプルコード

Highlighter.HighlightPainter highlightPainter =
    new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
JComboBox<String> combo = new JComboBox<String>(model) {
  @Override public void updateUI() {
    super.updateUI();
    JTextField field = new JTextField(" ");
    field.setOpaque(true);
    field.setBorder(BorderFactory.createEmptyBorder());
    ListCellRenderer<? super String> renderer = getRenderer();
    setRenderer((list, value, index, isSelected, cellHasFocus) -> {
      String pattern = ((JTextField) getEditor().getEditorComponent()).getText();
      if (index >= 0 && !pattern.isEmpty()) {
        Highlighter highlighter = field.getHighlighter();
        highlighter.removeAllHighlights();
        String txt = Objects.toString(value, "");
        field.setText(txt);
        addHighlight(highlighter, Pattern.compile(pattern).matcher(txt));
        field.setBackground(isSelected ? new Color(0xAA_64_AA_FF, true) : Color.WHITE);
        return field;
      }
      return renderer.getListCellRendererComponent(
          list, value, index, isSelected, cellHasFocus);
    });
  }

  private void addHighlight(Highlighter highlighter, Matcher matcher) {
    int pos = 0;
    try {
      while (matcher.find(pos) && !matcher.group().isEmpty()) {
        int start = matcher.start();
        int end = matcher.end();
        highlighter.addHighlight(start, end, highlightPainter);
        pos = end;
      }
    } catch (BadLocationException ex) {
      // should never happen
      RuntimeException wrap = new StringIndexOutOfBoundsException(ex.offsetRequested());
      wrap.initCause(ex);
      throw wrap;
    }
  }
};
view all

解説

  • JComboBoxを編集可能に設定し、そのエディタで入力中の文字列からPatternを生成
  • ListCellRendererでリストアイテム文字列を上記のパターンで検索
    • 一致する場合はJTextField#getHighlighter().addHighlight(...)でハイライトを追加したJTextFieldをセルレンダラーコンポーネントとして返す
    • 一致しない場合はデフォルトのJLabelをセルレンダラーコンポーネントとして返す

参考リンク

コメント