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.