如何基于列表突出显示JTree中的多个节点

时间:2019-06-19 16:05:14

标签: java swing awt rendering jtree

我正在构建一个使用JTree的应用程序。我无法根据列表中的结果突出显示多个节点。

我尝试使用DefaultTreeRenderer进行渲染,但是它突出显示了列表中的最后一项。每次遍历列表时,我都会调用JTree setcellrenderer。

import java.awt.*;
import java.util.ArrayList;
import java.util.Objects;
import javax.swing.*;
import javax.swing.tree.DefaultTreeCellRenderer;


public final class MainPanel extends JPanel {
  private final JTree tree = new JTree();
  private final HighlightTreeCellRenderer renderer = new HighlightTreeCellRenderer();
  private ArrayList<String> list = new ArrayList<String>();

  public MainPanel() {
    super(new BorderLayout(5, 5));
    list.add("football");
    list.add("soccer");

    JPanel n = new JPanel(new BorderLayout());

    n.setBorder(BorderFactory.createTitledBorder("Highlight Search"));

    tree.setCellRenderer(renderer);
    for(String str:list)
    renderer.setQuery(str);


    setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    add(n, BorderLayout.NORTH);
    add(new JScrollPane(tree));
    setPreferredSize(new Dimension(320, 240));
  }







  public static void main(String... args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGui();
      }
    });
  }

  public static void createAndShowGui() {
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
      ex.printStackTrace();
      Toolkit.getDefaultToolkit().beep();
    }
    JFrame frame = new JFrame("@title@");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MainPanel());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

class HighlightTreeCellRenderer extends DefaultTreeCellRenderer {
  private static final Color ROLLOVER_ROW_COLOR = new Color(0xDC_F0_FF);
  private String query;
  private boolean rollOver;

  @Override public void updateUI() {
    setTextSelectionColor(null);
    setTextNonSelectionColor(null);
    setBackgroundSelectionColor(null);
    setBackgroundNonSelectionColor(null);
    super.updateUI();
  }

  public void setQuery(String query) {
    this.query = query;
  }

  @Override public Color getBackgroundNonSelectionColor() {
    return rollOver ? ROLLOVER_ROW_COLOR : super.getBackgroundNonSelectionColor();
  }

  @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
    Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
    if (selected) {
      c.setForeground(getTextSelectionColor());
    } else {
      rollOver = Objects.nonNull(query) && !query.isEmpty() && Objects.toString(value, "").startsWith(query);
      c.setForeground(getTextNonSelectionColor());
      c.setBackground(getBackgroundNonSelectionColor());
    }

    return c;
  }
}

在“运动”节点下,“足球”和“足球”均应突出显示,但列表中仅最后一项:“足球”被突出显示。

2 个答案:

答案 0 :(得分:0)

您两次调用setQuery(),第二次调用只是替换了渲染器中的查询。使用查询集合或正则表达式来合并“ ^(football | soccer)。*”之类的模式

答案 1 :(得分:0)

我在renderer.setQuery()方法中以字符串形式发送了整个列表。然后,我检查查询是否包含“值”(getTreeCellRendererComponent()的参数)。

总共:

第26行:renderer.setQuery(list.toString()); 第93行:rollOver = Objects.nonNull(query)&&!query.isEmpty()&& query.contains(value.toString());