简体   繁体   中英

How to highlight multiple nodes in JTree based on a list

I am building an app which uses JTree. I am unable to highlight multiple Nodes based on results from a list.

I have tried rendering using DefaultTreeRenderer but it is highlighting the last item in list. I am calling JTree setcellrenderer each time iteratting through the list.

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;
  }
}

Under "Sports" node both "soccer" and "football" should be highlighted but only last item from list:"soccer" is getting highlighted.

You call setQuery() twice, the second call just replaces query in renderer. Use collection of queries or maybe regular expressions to merge patterns like "^(football|soccer).*"

I sent the whole list as string in renderer.setQuery() method. Then I checked if the query contained the "value"(an argument of getTreeCellRendererComponent()).

In all:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM