2
  1. JTreeでカスタムリーフアイコンを設定する方法を知っています
  2. すべてのグループノードにカスタムの閉じた/開いたアイコンを設定する方法を知っています

ただし、グループノード名に基づいてカスタムの開閉アイコンを設定することはできません。たとえば、ノードを電子メールと呼んだり(エンベロープアイコンがあると便利です)、1つのグループをタスクと呼んだりできます。

getTreeCellRendererComponentクラスのメソッドをオーバーライドしてこれを実行しようとしましたDefaultTreeCellRenderer

ただしicon、現在のnodeを変更すると、次のノードにのみ影響します。

個々のグループにカスタムの開いた/閉じたアイコンを設定するにはどうすればよいですか?

私のコードを見てください:

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

3 に答える 3

10

では、モデルに関連する定義済みのパラメーターと述語と組み合わせて、必要に応じて使用TreeCellRendererできます。デフォルトモデルのツリーがある場合、以下ではノードのアイコンとアイコンを使用します。setOpenIcon()setClosedIcon()JTreeTreeRendererclosedopensports

iamge

private static class TreeRenderer extends DefaultTreeCellRenderer {

    private static final Icon closed =
        (Icon) UIManager.get("InternalFrame.maximizeIcon");
    private static final Icon open =
        (Icon) UIManager.get("InternalFrame.minimizeIcon");

    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value,
        boolean sel, boolean exp, boolean leaf, int row, boolean hasFocus) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
        String s = node.getUserObject().toString();
        if ("sports".equals(s)) {
            setOpenIcon(open);
            setClosedIcon(closed);
        } else {
            setOpenIcon(getDefaultOpenIcon());
            setClosedIcon(getDefaultClosedIcon());
        }
        super.getTreeCellRendererComponent(
            tree, value, sel, exp, leaf, row, hasFocus);
        return this;
    }
}

この関連するも参照してください。

于 2012-12-31T03:59:01.660 に答える
5

コードを実行すると、ロードしようとしているイメージは、アプリケーション内に埋め込まれる「意味がある」ように見えます(つまり、アプリケーションコンテキストの外部のディスク上のどこかに存在しません)。

だからこれをする代わりに...

CustomTreeNode root = new CustomTreeNode(new ImageIcon("images/Circle_3.gif"), bigBoss); 

このようなことをしてみてください...

CustomTreeNode root = new CustomTreeNode(new ImageIcon(ImageIO.read(getClass().getResource("/images/Circle_3.gif"))), bigBoss); 

その代わり。これにより、Javaはそのクラスパス(JARリソースを含む)内を調べて画像を見つけます。

この修正なしでコードを実行すると、何も機能しませんでした。この機能を使用するようにコードを更新すると、正常に機能しました。

注意:ImageIO#readスローするIOExceptionので注意してください

更新しました

頭をひっかいた後...セルレンダラーを次のように変更しました...

class CustomeTreeCellRenderer extends DefaultTreeCellRenderer {

    public CustomeTreeCellRenderer() {
    }

    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {

//            if (!leaf) {
        CustomTreeNode node = (CustomTreeNode) value;

        if (node.getIcon() != null) {
            System.out.println(node + " - " + node.getIcon());
            setClosedIcon(node.getIcon());
            setOpenIcon(node.getIcon());
            setLeafIcon(node.getIcon());
        } else {
            System.out.println(node + " - default");
            setClosedIcon(getDefaultClosedIcon());
            setLeafIcon(getDefaultLeafIcon());
            setOpenIcon(getDefaultOpenIcon());
        }
//            }

        super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);

        return this;
    }
}

それはそれをすべてクリアしました...

ここに画像の説明を入力してください

呼び出しsetXxxIconは現在のレンダラーには影響しませんが、将来のレンダラーには影響します。あれは。setOpenIconすでに呼び出したAFTERを呼び出すとsuper.getTreeCellRendererComponent、現在のレンダラーには影響しませんがsuper.getTreeCellRendererComponent、setメソッドはクラス変数の値を設定するだけなので、次の呼び出しには影響します。

追加

Trashgodは、実装とそれが現在どのように機能するかに依存することについて貴重なコメントをしました。

DefaultTreeCellRenderer#setXxxIconメソッド内で呼び出すのではなく、渡されたパラメーターに基づいて必要なアイコンを使用して、getTreeCellRendererComponent実際に単に呼び出す必要があります。DefaultTreeCellRenderer#setIcon

super.getTreeCellRendererComponentこれは、最初に呼び出してから、その後のアイコンの動作をオーバーライドできることを意味します。

また、値への参照をObject取得してメソッドをオーバーライドDefaultTreeCellRenderer#getXxxIconし、値に基づいてこれらのメソッドの戻り値を変更することもできます。私は個人的に、レンダラーの文書化された動作を変更するので、これを勇気づけません

于 2012-12-31T07:05:16.683 に答える
0

コンポーネントが必要な場合(最初のステップでスーパーレンダラーを呼び出す必要があるため)、正しく機能させるために、すべてのツリーアイコン(開く、閉じる、葉)を設定することが重要です。

public java.awt.Component getTreeCellRendererComponent(javax.swing.JTree tree, Object value, boolean selected, boolean expanded, boolean isLeaf, int row, boolean focused) {
    Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, isLeaf, row, focused);

    DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
    MyTreeNodeWrapper treeNodeWrapper = (MyTreeNodeWrapper) node.getUserObject();
    Icon icon = treeNodeWrapper .getIcon();

    setOpenIcon(icon);
    setClosedIcon(icon);
    setLeafIcon(icon);

    if (!tree.isEnabled()) {
        if (isLeaf) {
            setDisabledIcon(getLeafIcon());
        } else if (expanded) {
            setDisabledIcon(getOpenIcon());
        } else {
            setDisabledIcon(getClosedIcon());
        }
    }
    else {
        if (isLeaf) {
            setIcon(getLeafIcon());
        } else if (expanded) {
            setIcon(getOpenIcon());
        } else {
            setIcon(getClosedIcon());
        }
    }
    
         
return c;

        
}

そうでない場合は、上記のように、3つのアイコンタイプを設定するだけで済みます。

public java.awt.Component getTreeCellRendererComponent(javax.swing.JTree tree, Object value, boolean selected, boolean expanded, boolean isLeaf, int row, boolean focused) {

    DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
    MyTreeNodeWrapper treeNodeWrapper = (MyTreeNodeWrapper ) node.getUserObject();
    Icon icon = treeNodeWrapper .getIcon();

    setOpenIcon(icon);
    setClosedIcon(icon);
    setLeafIcon(icon);

    
Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, isLeaf, row, focused);
         
return c;

        
}
于 2020-12-31T05:28:39.900 に答える