JTree 将节点的背景设置为不透明

Posted

技术标签:

【中文标题】JTree 将节点的背景设置为不透明【英文标题】:JTree set background of node to non-opaque 【发布时间】:2013-01-11 20:58:36 【问题描述】:

请查看 SSCCE。如何使未选择的树节点的背景透明。目前未选中节点的背景为白色。但是,如果未选中,我的单元格渲染器应该将其绘制为非透明(选中时为绿色……它的作用)。最后,我希望未选择的节点只是没有背景的文本,因为 SSCCE 中的红色区域在我的应用程序中具有渐变填充。

    import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;

public class SimpleTree extends JFrame

    public static void main(final String[] args)
    
        new SimpleTree();
    

    public SimpleTree()
    
        super("Creating a Simple JTree");
        final Container content = this.getContentPane();
        content.setBackground(Color.RED);
        final Object[] hierarchy =  "javax.swing", "javax.swing.border", "javax.swing.colorchooser", "javax.swing.event", "javax.swing.filechooser", new Object[]  "javax.swing.plaf", "javax.swing.plaf.basic", "javax.swing.plaf.metal", "javax.swing.plaf.multi" , "javax.swing.table",
                        new Object[]  "javax.swing.text", new Object[]  "javax.swing.text.html", "javax.swing.text.html.parser" , "javax.swing.text.rtf" , "javax.swing.tree", "javax.swing.undo" ;
        final DefaultMutableTreeNode root = this.processHierarchy(hierarchy);
        final JTree tree = new JTree(root);
        tree.setOpaque(false);
        tree.setCellRenderer(new MyCellRenderer());
        final JScrollPane scroller = new JScrollPane(tree);
        scroller.getViewport().setOpaque(false);
        scroller.setOpaque(false);
        content.add(scroller, BorderLayout.CENTER);
        this.setSize(275, 300);
        this.setVisible(true);
    

    /**
     * Small routine that will make node out of the first entry in the array,
     * then make nodes out of subsequent entries and make them child nodes of
     * the first one. The process is repeated recursively for entries that are
     * arrays.
     */

    private DefaultMutableTreeNode processHierarchy(final Object[] hierarchy)
    
        final DefaultMutableTreeNode node = new DefaultMutableTreeNode(hierarchy[0]);
        DefaultMutableTreeNode child;
        for (int i = 1; i < hierarchy.length; i++)
        
            final Object nodeSpecifier = hierarchy[i];
            if (nodeSpecifier instanceof Object[]) // Ie node with children
                child = this.processHierarchy((Object[]) nodeSpecifier);
            else
                child = new DefaultMutableTreeNode(nodeSpecifier); // Ie Leaf
            node.add(child);
        
        return (node);
    

    public class MyCellRenderer extends DefaultTreeCellRenderer
    
        @Override
        public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean sel, final boolean expanded, final boolean leaf, final int row, final boolean hasFocus)
        
            final Component ret = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);

            final DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (value));

            this.setText(value.toString());
            if (sel)
            
                this.setOpaque(true);
                this.setBackground(Color.GREEN);

            
            else
            
                this.setOpaque(false);
                this.setBackground(null);
            
            return ret;
        
    

【问题讨论】:

【参考方案1】:

您应该覆盖DefaultTreeCellRenderer 中的getBackgroundNonSelectionColorgetBackgroundSelectionColorgetBackground 并返回适当的值,如下所示:

public class MyCellRenderer extends DefaultTreeCellRenderer 

    @Override
    public Color getBackgroundNonSelectionColor() 
        return (null);
    

    @Override
    public Color getBackgroundSelectionColor() 
        return Color.GREEN;
    

    @Override
    public Color getBackground() 
        return (null);
    

    @Override
    public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean sel, final boolean expanded, final boolean leaf, final int row, final boolean hasFocus) 
        final Component ret = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);

        final DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (value));
        this.setText(value.toString());
        return ret;
    

这将产生:

其他建议:

在Event Dispatch Thread 上创建和操作 Swing 组件。 不要不必要地扩展JFrame,而是创建一个实例并使用它。 不要在JFrame 上调用setSize,而是使用正确的LayoutManager 和/或覆盖getPreferredSize() 并在JFrame 上调用pack(),然后再将其设置为可见,但在添加所有组件之后。 记得使用DISPOSE_ON_CLOSEEXIT_ON_CLOSE 调用JFrame#setDefaultCloseOperation(除非使用Timers,否则通常首选DISPOSE_XXX,因为这将允许main(String[] args) 在Gui 关闭后继续执行)。

【讨论】:

谢谢!那行得通。也感谢其他建议,但为了节省时间,我从这里复制了 JTree 示例:apl.jhu.edu/~hall/java/Swing-Tutorial/Swing-Tutorial-JTree.html 并稍作调整。所以这个人是罪魁祸首:-) @mKorbel 有什么理由解释为什么?我只用最新的java很难测试 @haferblues 只是出于好奇,你有没有试过我的答案,它有效吗? @David Kroukamp 不知道,顺其自然:-) @haferblues:在AquaLookAndFeel 上,UI 委托将文本设为白色以进行对比;你可能也想测试Color.*.darker()【参考方案2】:

为避免后台重新填充,只需将UIManager.put("Tree.rendererFillBackground", false); 放在new SimpleTree(); 之前或super("Creating a Simple JTree"); 之后。

【讨论】:

我添加了一个截图。我想要没有白色背景的节点文本。它应该是透明的,而不是白色,因此节点的文本只是绘制在内容窗格的红色背景上。在渲染器中将背景设置为 new Color(0,0,0) 没有帮助。 你试过我的解决方案了吗?我确实运行了你的程序,并且在我的答案中添加了UIManager.put("Tree.rendererFillBackground", false); 之后,现在节点的文本具有透明背景。这是你需要的吗? 没试过,因为我不喜欢通过 UIManager 设置属性。 David 的解决方案似乎适合这种情况。 它将完全禁用任何背景,例如选择项目时的不同颜色,这可能是不可取的。

以上是关于JTree 将节点的背景设置为不透明的主要内容,如果未能解决你的问题,请参考以下文章

图像背景后的黑色背景(不透明度 0.6),文本为不透明度 1

具有透明背景的 UIModalPresentationFormSheet?

React Native设置背景透明,文字不透明的控件

如何以编程方式将所有 <object> 设置为将 wmode 设置为不透明?

设置 WPF 标签内容 Alpha 透明度而不是整个控件的不透明度

css父集设置透明 里面的内容也透明怎么解决?