1

カスタムモデルとカスタムレンダラーを備えたJTreeがあります。複数の子ノードを持つノードを展開すると、すべての子ノードが同じ長方形に描画されるため、最後のノードのみが表示されることを除いて、これらは正常に機能しているようです。子ノードを反復処理してコンソールに出力することはできますが、UIが異なります。

これはUIのスケッチです。

// for 1 child node:
ROOT
-- <rendered node>

//for 2 child nodes:
ROOT
|
-- <rendered node - the data of the 2nd node>

//for 3 child nodes:
ROOT
|
|
-- <rendered node - the data of the 3rd node>

BasicTreeUIがgetPathBounds()を使用して、特定のノードの境界を決定していることがわかりました。これが私がそれをチェックする方法です:

doStuffWithTree(JTree tree) {
   tree.expandNode(0);
   for (int i = 0; i < tree.getRowCount(); i++) {
       TreePath tp = tree.getPathForRow(i);
       tree.makeVisible(tp);
       System.out.println("Bounds of row " + i + ": " + tree.getPathBounds(tp));
   }
}

このチェックにより、ノード0を除くすべてのノードの境界が同じであることがわかります。

ツリーを拡張するいくつかのトリックを試しました。たとえば、最初からすべてのノードを拡張します。その後、最後から始めます-それらはすべて同じ効果があります。

最後に、質問:この動作を修正するためにどのクラスを変更できますか?既知の回避策はありますか?

アップデート

どうやら、TreeNodeの実装で何かを修正する必要があります。また、自分で修正する必要があります。カスタムモデルはありませんでしたが、カスタムのTreeNodeがありました。SSCCEは次のとおりです。

package com.example.jtree;

//lots of obvious imports

public class JTreeBoundsExample extends JFrame {

public static void main(String... args) {
    JTreeBoundsExample m = new JTreeBoundsExample();
    m.setSize(275, 300);
    m.setDefaultCloseOperation(EXIT_ON_CLOSE);
    m.setVisible(true);
}

public JTreeBoundsExample() {
    ValueTreeNode root = new ValueTreeNode(null, "root");
    ValueTreeNode category = new ValueTreeNode(root, "category");
    category.put("k1", new ValueTreeNode(category, "v1"));
    category.put("k2", new ValueTreeNode(category, "v2"));
    category.put("k3", new ValueTreeNode(category, "v3"));
    root.put("category", category);

    JTree tree = new JTree(root);
    tree.setCellRenderer(new ValueCellRenderer());

    tree.setRootVisible(false);
    tree.expandRow(0);
    for (int i = 0; i < tree.getRowCount(); i++) {
        TreePath tp = tree.getPathForRow(i);
        tree.makeVisible(tp);
        System.out.println("Bounds of row " + i + ": " + tree.getPathBounds(tp));
    }

    Container content = getContentPane();
    content.add(new JScrollPane(tree), BorderLayout.CENTER);
}

private static class ValueTreeNode extends HashMap<String, ValueTreeNode> implements TreeNode {

    private List<String> keys = new ArrayList<String>();
    private TreeNode parent;
    private String value;

    public ValueTreeNode(TreeNode parent, String value) {
        this.parent = parent;
        this.value = value;
    }

    @Override
    public ValueTreeNode put(String key, ValueTreeNode val) {
        ValueTreeNode old = super.put(key, val);
        if (old == null) {
            sortKeys();
        }
        return old;
    }

    private void sortKeys() {
        keys.clear();
        keys.addAll(keySet());
        Collections.sort(keys);
    }

    @Override
    public Enumeration children() {
        final Iterator<String> it = keys.iterator();
        return new Enumeration() {
            @Override
            public boolean hasMoreElements() {
                return it.hasNext();
            }
            @Override
            public Object nextElement() {
                return it.next();
            }
        };
    }

    @Override
    public boolean getAllowsChildren() {
        return true;
    }

    @Override
    public TreeNode getChildAt(int pos) {
        return get(keys.get(pos));
    }

    @Override
    public int getChildCount() {
        return size();
    }

    @Override
    public int getIndex(TreeNode arg0) {
        return -1;
    }

    @Override
    public TreeNode getParent() {
        return parent;
    }

    @Override
    public boolean isLeaf() {
        return size() == 0;
    }
}

private static class ValueCellRenderer extends DefaultTreeCellRenderer {
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
            boolean leaf, int row, boolean hasFocus) {
        super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
        if (value instanceof ValueTreeNode) {
            ValueTreeNode vtn = (ValueTreeNode) value;
            setText(vtn.value);
        }
        return this;
    }
}   
}
4

0 に答える 0