4

私が必要なものと、私がどこまで来たかを説明しましょう:

カスタムモデルといくつJTreeかの素敵なアイコンがあり、すべてが正常に機能しますが、ツリーのデフォルトの色 (白) は、設計しようとしている GUI に適合しないため、できるようにしたいと考えています。背景色を変更します。

これはかなりの雑用であることが証明されています!

これについてはネット上で多くの説明を見てきましたが、それらは の拡張DefaultTreeCellRendererまたは の拡張を中心に展開しているようBasicTreeUIに見えますが、これらはハッキングであり、避けるべきであるという提案がいくつかあります。代わりに行う必要があります。

いずれにせよ、提案された方法はどれもうまく機能していないようです。

色はツリーに設定されていますが、ツリー ラベルの端とツリーの右側、ラベルとそのア​​イコン、およびツリーを展開するためのプラス/マイナス ウィジェットの間には厄介なギャップがあります。この場合、完全な行選択を実装することをお勧めします。

もう 1 つのシナリオでは、完全な行選択が実装されており、ノードは正しく色付けされ、完全な行選択が機能しますが、アイコンがプラス/マイナス ウィジェットと共に完全に欠落しているか、両方の周りに厄介な白い境界線が残っています。

これに対する私自身の試みは失敗し、現在、次のコードが残されています。これは、ツリーとノードに色を付けますが、ツリー ラベルの最後とすべてのアイコンの間に厄介な白い境界線を残します。

final Color MainBg = new Color(213,220,228);
KTree.setCellRenderer(new DefaultTreeCellRenderer()
{
    @Override
    public Component getTreeCellRendererComponent(JTree pTree, Object pValue, boolean pIsSelected, boolean pIsExpanded, boolean pIsLeaf, int pRow, boolean pHasFocus)
    {
            super.getTreeCellRendererComponent(pTree, pValue, pIsSelected, pIsExpanded, pIsLeaf, pRow, pHasFocus);
            setBackgroundNonSelectionColor(MainBg);
            setBackgroundSelectionColor(MainBg);
            setTextNonSelectionColor(Color.BLACK);
            setTextSelectionColor(Color.BLACK);
            ImageIcon tDoc = createImageIcon("images"  + File.separator + "document.gif","document");
            ImageIcon tOpen = createImageIcon("images"  + File.separator + "book_open.gif","book open");
            ImageIcon tClosed = createImageIcon("images"  + File.separator + "bookclosed.png","book closed");
            setClosedIcon(tClosed);
            setOpenIcon(tOpen);
            setLeafIcon(tDoc);
            putClientProperty("Tree.collapsedIcon", tDoc);
            putClientProperty("tree.expandedIcon", tOpen);
        return (this);
    }
});

私の質問:

1) 当然のことながら、カラー セットを取得するための助けをJTreeいただければ幸いです。また、提案をお待ちしております。 .

2) プロセスに何が含まれているかについての明確な説明をいただければ幸いです。JTree私は、私が探しているものであるツリーを完全に着色するという問題に長い間 (たとえあったとしても) 焦点を当てていないことに関する多くのチュートリアルを読みました。行選択の有無、サブクラス化の有無など。

また、特定のものが「ハック」と見なされる理由と、代替手段とは何かを理解したいと思います。


編集 - 解決策

このセクションを追加して、これを整理するための私の進捗状況を示し、おそらく他の人がかなり手間のかかるプロセスであったことに少し有利なスタートを切ることができるようにします. これを System L&F で適切に動作させるために何日も費やし、何度かサークルに参加しました。これの多くは間違いなく経験不足によるものです。これにより、他の誰かが数回の髪を引っ張るセッションを節約できれば、なおさらです。

ところで: ハックと見なされる何かを行った場合は、批判を聞くことができてうれしいですが、(機能する) 代替案と、ハックのラベルの背後にあるいくつかの明確な理由を提供してください.

わかりました、始めましょう: システム L&F を設定したいのは、他のオプションがあまり好きではなく、ユーザーが慣れ親しんだものと一致するプログラムをユーザーに見てもらいたいからです。他のことをする前に、L&F を次のように設定します。

try
    {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
catch (Exception e) { return; }

これにより、JTree使用している OS の標準が設定されます。これには、ツリー自体の背景の設定だけでなく、ノード選択の背景などの設定も含まれているようです。あなたが望むのが標準JTreeであれば準備はできていますが、システムベースのスクロールバーなどを見たいのですが、背景に白以外の色も見たいです。

背景を次のような素敵な青色に設定します (この色はすぐに再び使用されることに注意してください。したがって、final宣言が行われます)。

final Color MainBg = new Color(213,220,228);
    KTree.setBackground(MainBg);

私が今持っているのはJTree、ノードを含まないツリーの領域のみをカバーする素敵な青色の背景を持つ で、L&F の設定に従って白色のままです。ノード自体に色を設定する必要があります。これを行うには、次のコードgetTreeCellRendererComponentでをオーバーライドする必要があります。DefaultTreeCellRenderer

final Color SellBg = new Color(232,235,237);
final Color HiliBg = new Color(150,196,246);

KTree.setCellRenderer(new DefaultTreeCellRenderer()
{

    @Override
    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);
        setBackgroundNonSelectionColor(MainBg);
        setBackgroundSelectionColor(SellBg);
        setTextNonSelectionColor(Color.BLACK);
        setTextSelectionColor(Color.BLACK);
        ImageIcon tDoc = createImageIcon("images"  + File.separator + "document.gif","document");
        ImageIcon tOpen = createImageIcon("images"  + File.separator + "book_open.gif","open");
        ImageIcon tClosed = createImageIcon("images"  + File.separator + "bookclosed.png","closed");
        setClosedIcon(tClosed);
        setOpenIcon(tOpen);
        setLeafIcon(tDoc);
        setBorderSelectionColor(HiliBg);
        return this;
    }
});

上記のcreateImageIconを次に示します。これはチュートリアルから直接得たものですが、これは完成する前に編集されていることに注意してください (したがって、このコードをコピーして貼り付けないでください!):

protected ImageIcon createImageIcon(String path, String description)
{
    java.net.URL imgURL = getClass().getResource(path);
    if (imgURL != null)
    {
        return new ImageIcon(imgURL, description);
    }
    else
    {
        System.err.println("Couldn't find file: " + path);
        return null;
    }
}

コードに従っている場合、この段階で、ツリー ノードにさまざまな色を設定し、いくつかのアイコンを追加していることがわかります。これはすべて非常にうまく機能しますが、ノード テキストの端とJTreeそれ自体の端の間、およびノー​​ド テキストとアイコン、およびツリーのプラス/マイナス ウィジェットの間に厄介な白いブロックができてしまいます。これらの白いブロックも、ツリーが拡大するにつれてツリーを通過します。

これは私が入ってきた場所であり、髪の引っ張りが始まりました. Jacob の提案と MadProgrammer のヒント (ありがとう) のおかげで、私は正しい軌道に乗っていましたが、ここで事態がおかしくなりJTreeました。コードを以前のバージョンにロールバックして、このセクションを再度開始することで、作業を進めることができました。

簡単なメモ: 間違った方法で行っている場合は、お知らせください。

の白い部分を変更するJTreeには、 をオーバーライドする必要があるように見えましたがBasicTreeUI、これは次のように行いました。

KTree.setUI(new javax.swing.plaf.basic.BasicTreeUI()
{
    @Override
    public Rectangle getPathBounds(JTree tree, TreePath path)
    {
        if(tree != null && treeState != null)
        {
            return getPathBounds(path, tree.getInsets(), new Rectangle());
        }
        return null;
    }
    private Rectangle getPathBounds(TreePath path, Insets insets, Rectangle bounds)
    {
        bounds = treeState.getBounds(path, bounds);
        if(bounds != null)
        {
            bounds.width = tree.getWidth();
            bounds.y += insets.top;
        }
        return bounds;
    }

});

これは私のコードではないことを述べなければなりません - 私はこれを多くのチュートリアル サイトの 1 つで見つけましたJTree

上記のコード内からこれらのウィジェットを設定する簡単な方法がある可能性が最も高いですが、私は、L&F を設定した直後にBasicTreeUIのコードを配置したので、Jacob のいじりについての警告に気をつけていました。

ImageIcon clapsed = createImageIcon("images"  + File.separator + "plus.gif","closed");
ImageIcon clopen = createImageIcon("images"  + File.separator + "minus.gif","open");
UIManager.getLookAndFeelDefaults().put("Tree.collapsedIcon",clapsed);
UIManager.getLookAndFeelDefaults().put("Tree.expandedIcon",clopen);
UIManager.getLookAndFeelDefaults().put("Tree.paintLines", true);
UIManager.getLookAndFeelDefaults().put("Tree.leftChildIndent",7);
UIManager.getLookAndFeelDefaults().put("Tree.lineTypeDashed",true)

これにより、プラス/マイナスのウィジェット アイコンが独自のものに設定され、ツリー内の要素間に必要な線の種類が設定されます。この時点で、以前の非静的createImageIconにアクセスできなかったため、エラーが発生したことに注意してください。このメソッドへの両方の呼び出しを許可するには、次のようにコードを編集する必要がありました。

protected static ImageIcon createImageIcon(String path, String description)
{
    Class<?> cl=new Object(){}.getClass().getEnclosingClass();
        java.net.URL imgURL = cl.getResource(path);
        if (imgURL != null)
        {
            return new ImageIcon(imgURL, description);
        }
        else
        {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
}

私は今(ついに!)JTreeシステムL&Fセットと、ツリーのすべての要素の色セットを備えた を持っています。

まだ未解決の問題があります:

私は (まだ)BasicTreeUI()コードを完全には理解していません。ただし、選択色を距離全体に広げることができませんでした。後でこれで遊ぶつもりですが、ジェイコブの警告のおかげで用心深くなります - 誰かがこれに関して厳格で迅速なルールを持っているなら、私はそれらを聞いてうれしいです.

また、L&F を意図的に設定して、色は異なりますが、ユーザーが見慣れたものを見ることができるようにしました。ただし、プラス/マイナス ツリー ウィジェットに独自のアイコンを追加することを余儀なくされました。これは実際には問題ではなく、少し面倒です。これは後でクリアされる可能性があります。

私のもう1つの懸念は、値を設定するとUIManager、特定のキーしか設定できず、他のキーは明らかに無視されることです。MadProgrammer は、Nimbus を使用するとこれらのキーが少し台無しになる可能性があることを指摘しました。

とにかく、それが私の努力の現在の結果です。この投稿が長くなってしまったことをお詫び申し上げますが、これが他の誰かの助けになることを願っています。

よろしく

MVK

4

2 に答える 2

3

ツリー項目が希望の色になるように既にオーバーライドgetTreeCellRendererComponentしている場合は、次を使用できます

UIManager.getLookAndFeelDefaults().put("Tree.background", new ColorUIResource(aColor);

ツリーの「占有されていない」スペースの色を変更します。これは、将来のすべてのツリーに影響することに注意してください。コンポーネント UI クラスはこのプロパティを使用し、多くのコンポーネントを描画するときにこのプロパティを使用します。どのキーが存在するかを調べるには、次のようにします。

for (Entry<Object, Object> entry : UIManager.getLookAndFeelDefaults().entrySet()) {
    System.out.println(entry.getKey() + " : " + entry.getValue());
}

他の質問に関しては、オーバーライドgetTreeCellRendererComponentをハックとは考えていませんが、不注意に拡張BasicTreeUIすると、一部のルック アンド フィールで予期しない動作が発生する可能性があります。

于 2012-07-14T12:33:28.213 に答える