改变Nimbus LaF处理JTree节点突出显示的方式

时间:2012-04-26 19:28:28

标签: java swing jtree renderer nimbus

我一直在努力将Java应用程序从WindowsLookAndFeel转换为Nimbus,尽管Nimbus很容易,但已成功转发。我的用户总体上喜欢Nimbus LaF,但不喜欢一些细节,其中一些我通过咨询本网站上的问题而改变了。示例:我从Windows LaF(他们喜欢)复制了LeafIcon,ClosedIcon和OpenIcon,并在Nimbus版本中使用它们,以获得很好的LaF组合。

坚持最后一个(?)问题。

我有一个带有子类DefaultCellRenderer的JTree来创建适当的节点显示。这在WindowsLookAndFeel下工作正常。

问题: 在WindowsLaF下,当选择节点时,节点的文本会突出显示,并且效果在视觉上易于理解。在Nimbus下选择一个节点时,突出显示是用一条(相当深的)颜色条来完成的,该条颜色在树窗的宽度上运行(不仅仅是文本的宽度),效果令人不安。

所以:我只想在Nimbus LaF中对WindowsLaF处理JTree节点突出显示(即彩色背景只有文本的宽度,最好是我可以选择的更好的颜色)。我怀疑这意味着我需要分配正确的排序画家 “Tree:TreeCell [Focused + Selected] .backgroundPainter”,但我不知道如何写它。

建议最受欢迎。


修改

使用Java 7查看奇怪的选定节点突出显示!

enter image description here

public class TreeBorder {
    public static void main( String[] args ) {
        try{
            for( UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels() ) {
                if( "Nimbus".equals( info.getName() ) ) {
                    UIManager.setLookAndFeel( info.getClassName() );
                    break;
                }
            }
        } catch( Exception e ) {
            e.printStackTrace();
        }
        SwingUtilities.invokeLater( new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setLocationRelativeTo( null );
                f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                f.getContentPane().add( getJTree() );
                f.pack();
                f.setVisible( true );
            }
            private JTree getJTree() {
                JTree jTree = new JTree();
                jTree.setCellRenderer( new LocalRenderer() );
                return jTree;
            }
        } );
    }

    private static class LocalRenderer extends DefaultTreeCellRenderer {
        @Override
        public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasfocus ) {
            DefaultTreeCellRenderer result = (DefaultTreeCellRenderer)super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasfocus );
                if( true ) {
                    result.setFont( new JLabel().getFont() );
                    Icon icon = UIManager.getIcon("FileView.floppyDriveIcon");
                    result.setIcon( icon );
                }
            return(result);
        }
    }
}

1 个答案:

答案 0 :(得分:6)

修改

“Tree.selectionBackground”键控制JTree上的突出显示 - 它在树级别上完成,而不是在TreeCellRenderer级别上完成(这就是为什么管理有点混乱)。这段代码将为您提供一个树,您可以在其中控制突出显示:

private JTree getJTree() {

    JTree jTree = new JTree();
    jTree.setOpaque(true);
    jTree.setBackground(Color.white);
    UIDefaults paneDefaults = new UIDefaults();
    paneDefaults.put("Tree.selectionBackground",null);

    JTextPane pane = new JTextPane();
    jTree.putClientProperty("Nimbus.Overrides",paneDefaults);
    jTree.putClientProperty("Nimbus.Overrides.InheritDefaults",false);

    jTree.setCellRenderer( new LocalRenderer() );
    return jTree;
}

这是将突出显示更改为红色的示例。请注意,Icon的背景也会突出显示 - 这也是非nimbus L& F的默认行为。如果你不想突出显示图标,那么你将不得不使用比默认JLabel更漂亮的东西来渲染TreeCell:

    public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasfocus ) {
        DefaultTreeCellRenderer result = (DefaultTreeCellRenderer)super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasfocus );
        result.setOpaque(true);
            if( true ) {
                result.setFont( new JLabel().getFont() );
                Icon icon = UIManager.getIcon("FileView.floppyDriveIcon");
                result.setIcon( icon );
            }
            if(sel){
                result.setBackground(Color.red);
            } else{
                result.setBackground(Color.white);
            }
        return(result);
    }

原始答案

解决此问题的最简单方法之一是将所选背景颜色设置为透明。问题在于它正在尝试绘制标签的背景 - 它没有JTree选择使用的酷炫的Nimbus画家。因此,请将此行添加到getTreeCellRendererComponent方法:

result.setBackgroundSelectionColor(new Color(0,0,0,0));

另一个选择是使用nimbus painter作为TreeCellRenderer的背景 - 但在这种情况下看起来有点过分。