JTree: Set custom ouvert/fermé des icônes pour les différents groupes
- Je sais comment personnaliser les feuilles des icônes dans JTree
- Je sais comment personnaliser fermeture/ouverture des icônes pour tous les nœuds du groupe
Mais je ne peux pas définir personnalisé ouvert/fermé les icônes en fonction du groupe de noms de nœud, par exemple de nœud pourrait être appelé e-Mails (donc c'est agréable d'avoir une enveloppe icône) ou un groupe peut être appelé les tâches et ainsi de suite.
J'ai essayé de le faire en remplaçant la getTreeCellRendererComponent
méthode de classe DefaultTreeCellRenderer
Mais en changeant la icon
pour le courant node
affectera pour le prochain nœud seulement!
Comment personnaliser ouvert/fermé des icônes pour les différents groupes?
Veuillez jeter un oeil à mon code:
Employee.java
package com.ehsunbehravesh.swing;
import java.util.Random;
public class Employee {
public String name;
public int id;
public boolean isBoss;
public Employee[] employees;
public Employee(String name, boolean isBoss) {
this.name = name;
this.isBoss = isBoss;
this.id = new Random(System.currentTimeMillis()).nextInt(Integer.MAX_VALUE);
}
@Override
public String toString() {
return this.name;
}
static String randomName() {
String chars = "abcdefghijklmnopqrstuvwxyz";
StringBuilder builder = new StringBuilder();
Random r = new Random(System.currentTimeMillis());
int length = r.nextInt(10) + 1;
for (int i = 0; i < length; i++) {
builder.append(chars.charAt(r.nextInt(chars.length())));
}
return builder.toString();
}
}
CustomTreeNode.java
package com.ehsunbehravesh.swing;
import javax.swing.ImageIcon;
import javax.swing.tree.DefaultMutableTreeNode;
public class CustomTreeNode extends DefaultMutableTreeNode {
/**
* The icon which is displayed on the JTree object. open, close, leaf icon.
*/
private ImageIcon icon;
public CustomTreeNode(ImageIcon icon) {
this.icon = icon;
}
public CustomTreeNode(ImageIcon icon, Object userObject) {
super(userObject);
this.icon = icon;
}
public CustomTreeNode(ImageIcon icon, Object userObject, boolean allowsChildren) {
super(userObject, allowsChildren);
this.icon = icon;
}
public ImageIcon getIcon() {
return icon;
}
public void setIcon(ImageIcon icon) {
this.icon = icon;
}
}
CustomeTreeCellRenderer.java
package com.ehsunbehravesh.swing;
import java.awt.Component;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
class CustomeTreeCellRenderer extends DefaultTreeCellRenderer {
public CustomeTreeCellRenderer() {
}
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, leaf, expanded, leaf, row, hasFocus);
if (!leaf) {
CustomTreeNode node = (CustomTreeNode) value;
System.out.println(((Employee) node.getUserObject()).name);
if (node.getIcon() != null) {
System.out.println(node.getIcon().toString());
setClosedIcon(node.getIcon());
setOpenIcon(node.getIcon());
} else {
setClosedIcon(getDefaultClosedIcon());
setClosedIcon(getDefaultOpenIcon());
setOpenIcon(getDefaultOpenIcon());
}
}
return this;
}
}
Test1.java
package com.ehsunbehravesh.swing;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeModel;
class TreeSample {
public static void main(String args[]) {
JFrame f = new JFrame("JTree Sample");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel pnlMain = new JPanel(new BorderLayout());
pnlMain.setBackground(Color.white);
createTree(pnlMain);
f.setContentPane(pnlMain);
f.setSize(300, 200);
f.setVisible(true);
}
private static void createTree(JPanel pnlMain) {
Employee bigBoss = new Employee(Employee.randomName(), true);
Employee[] level1 = new Employee[5];
bigBoss.employees = level1;
for (int i = 0; i < level1.length; i++) {
level1[i] = new Employee(Employee.randomName(), true);
}
for (int i = 0; i < level1.length; i++) {
Employee employee = level1[i];
if (employee.isBoss) {
int count = 5;
employee.employees = new Employee[count];
for (int j = 0; j < employee.employees.length; j++) {
employee.employees[j] = new Employee(Employee.randomName(), false);
}
}
}
CustomTreeNode root = new CustomTreeNode(new ImageIcon("images/Circle_3.gif"), bigBoss);
DefaultTreeModel model = new DefaultTreeModel(root);
for (Employee employee : bigBoss.employees) {
CustomTreeNode boss = new CustomTreeNode(new ImageIcon("images/Circle_2.gif"), employee);
root.add(boss);
if (employee.isBoss) {
for (Employee employee1 : employee.employees) {
CustomTreeNode emp = new CustomTreeNode(new ImageIcon("images/Circle_1.gif"), employee1);
boss.add(emp);
}
}
}
JTree tree = new JTree(model);
tree.setCellRenderer(new CustomeTreeCellRenderer());
pnlMain.add(tree, BorderLayout.CENTER);
}
}
- Essayez quelque chose comme UIManager.put(“Arbre.openIcon”,employeeNodes);
- Pour mieux aider plus tôt, après une SSCCE.
- Si je ne me trompe pas
UIManager.put(“Tree.openIcon”,employeeNodes);
affectera sur tous les nœuds sont pas certains d'entre eux. - Le
DefaultTreeCellRenderer
va utiliser tout ce que vous avez définie, comme indiqué ici.
InformationsquelleAutor ehsun7b | 2012-12-31
Vous devez vous connecter pour publier un commentaire.
Dans votre
TreeCellRenderer
, vous pouvez utilisersetOpenIcon()
etsetClosedIcon()
comme nécessaire en conjonction avec les paramètres définis, et les prédicats liés à votre modèle. Étant donné un arbre ayant le défautJTree
modèle, laTreeRenderer
ci-dessous utilise laclosed
etopen
icônes pour lessports
nœud:Voir aussi cette exemple.
super.getTreeCellRendererComponent
au tout début de la version de remplacement?DefaultTreeCellRenderer
.super.getTreeCellRendererComponent
avant de me changer les icônes de sorte qu'il a été efficace pour la prochaine nœuds seulement. MerciException in thread "AWT-EventQueue-0" java.lang.ClassCastException: TreeRenderer cannot be cast to javax.swing.AbstractButton
. L'exception est interne à la Java, c'est à dire la trace de la pile ne s'est jamais fait mention d'une ligne de mon code où le problème réside, ce qui se passe?Icon
, pour exemple.Avoir vous exécutez le code, il semblerait que les images que vous essayez de charger sont "censés" être intégré au sein de l'application (qui est, qu'ils ne résident pas certains de l'endroit sur le disque à l'extérieur du contexte de l'application).
Donc au lieu de cela...
Essayer de faire quelque chose comme ça...
À la place. Ce sera la cause de Java pour regarder à l'intérieur c'est le chemin de classe (y compris toute BOCAL de ressources) afin de trouver les images.
Quand je vous exécutez le code, sans ce correctif, rien n'y fait, quand j'ai mis à jour pour utiliser cette fonction, il a bien fonctionné.
NB:
ImageIO#read
jette unIOException
donc regarder dehors pour elleMis à jour
Après beaucoup de casse-tête...j'ai changé le rendu de cellule ressemble à...
Il, il effacé tout ça...
Appel
setXxxIcon
n'est pas l'effet de l'actuel moteur de rendu, mais le futur moteur de rendu. Qui est. Si vous appelezsetOpenIcon
APRÈS que vous avez déjà appelésuper.getTreeCellRendererComponent
, il n'aura pas d'effet de l'actuel moteur de rendu, mais il sera en effet le prochain appel àsuper.getTreeCellRendererComponent
que la méthode de jeu est tout simplement le réglage de la valeur de la variable de classe.Supplémentaires
Trashgod a fait un précieux commentaire à propos en s'appuyant sur la mise en œuvre et la façon dont il fonctionne maintenant.
Au lieu de l'appeler
DefaultTreeCellRenderer#setXxxIcon
dans legetTreeCellRendererComponent
méthode, en fait, vous devez simplement appelerDefaultTreeCellRenderer#setIcon
, à l'aide de l'icône sur la base des paramètres transmis.Cela signifie que vous pouvez appeler
super.getTreeCellRendererComponent
d'abord, puis remplacer le comportement des icônes d'après elle.Vous pouvez également saisir une référence à
Object
valeur et de remplacer lesDefaultTreeCellRenderer#getXxxIcon
méthodes et basée sur la valeur, modifiez les valeurs de retour de ces méthodes. Personnellement, je n'en ferait pas le courage ce que ça change le comportement documenté de la fonctionnalité de renduUIManager
icône est une alternative pratique.DefaultTreeCellRenderer
est un peu laconique au sujet de "l'auto-utilisation de méthodes substituables."setXxxIcon
méthodes ferait qu'appliquer les icônes, mais compte tenu du fait que c'est un moteur de rendu, je pense qu'on ne devrait pas être surpisedleaf
etexpanded
paramètres." Merci pour le feedback.setXxxMethod
s dans le moteur de rendu lui-même, nous devrions en fait appel icône de jeu, sur la base de paramètres passés à la méthodeMap<String, IconPair>
d'avoir plusieurs différentes ouvert/fermé paires dans le même arbre.DefaultTreeCellRenderer
va changer le nœud de sélection de l'arrière-plan et la couleur de premier plan ,lorsque vous cliquez sur n'importe quel nœud le nœud de ne pas montrer grisé , ce problème, vous pouvez utiliserthis.selected = selected; this.hasFocus = hasFocus;
pour le fixer . Espérons que cela aide les autres.