изменение того, как Nimbus LaF обрабатывает выделение узлов JTree

Я работал над переводом Java-приложения с WindowsLookAndFeel на Nimbus, в основном успешно, несмотря на недостатки Nimbus. Моим пользователям в целом нравится Nimbus LaF, но не понравились некоторые детали, некоторые из которых я изменил, проконсультировавшись с предыдущими вопросами на этом сайте. Пример: я скопировал LeafIcon, ClosedIcon и OpenIcon из Windows LaF (который им понравился) и использовал их в версии Nimbus для хорошей комбинации LaF.

Застрял на последней (?) Проблеме.

У меня есть JTree с подклассом DefaultCellRenderer для создания соответствующих отображений узлов. Это отлично работает под WindowsLookAndFeel.

Проблема: В WindowsLaF при выборе узла текст узла выделяется, и эффект визуально легко понять. В Nimbus, когда узел выбран, выделение выполняется полосой (довольно темного) цвета, которая проходит по ширине окна дерева (а не только по ширине текста), и эффект сбивает с толку.

Итак: я просто хочу, чтобы WindowsLaF обработала выделение узла JTree в Nimbus LaF (т. Е. Цветной фон только по ширине текста и, желательно, лучшего цвета, который я могу выбрать). Я подозреваю, что это означает, что мне нужно назначить правильный тип Painter для «Tree: TreeCell [Focused + Selected] .backgroundPainter», но я не знаю, как это написать.

Предложения приветствуются.


ИЗМЕНИТЬ

Посмотрите на странное выделение выбранного узла в Java 7!

введите описание изображения здесь

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

person user1359010    schedule 26.04.2012    source источник
comment
Дополнение к моему посту: конечно, если бы есть более простой способ, чем рисовать, это было бы даже лучше. Пытался просто изменить Tree.selectionBackground на менее отвлекающий цвет, но Nimbus, похоже, игнорирует модификацию.   -  person user1359010    schedule 27.04.2012
comment
Продолжение моего комментария. Вы не можете установить Tree.selectionBackground напрямую, но этот цвет является производным от numbusSelectionBackground, поэтому nimbUID.put (nimbusSelectionBackground, new ColorUIResource (205,208,216)); производит желаемый эффект (более светлый Tree.selectionBackground). По-прежнему выделяется строка, а не только текст, поэтому помощь художника по-прежнему приветствуется.   -  person user1359010    schedule 28.04.2012
comment
@oliholz, пожалуйста, не могли бы вы прокомментировать свою награду, конечно, я никогда не видел этого вопроса, потому что классическая концепция Renderers перегружает свойства и настройки Nimbus в большинстве случаев   -  person mKorbel    schedule 17.12.2012
comment
@mKorbel eee Edit. С помощью DefaultTreeCellRenderer и Java7 я получил раздражающую подсветку под Nimbus.   -  person oliholz    schedule 17.12.2012
comment
Ошибка Nimbus исправлена ​​в Java 8, и исправление больше не работает.   -  person oliholz    schedule 22.01.2015


Ответы (1)


Изменить

Клавиша «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;
}

А вот пример изменения выделения на красный. Обратите внимание, что фон значка также будет выделен - это поведение по умолчанию и для не-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);
    }

Исходный ответ

Один из самых простых способов исправить это - сделать выбранный цвет фона прозрачным. Проблема в том, что он пытается нарисовать фон метки, в котором нет классного рисовальщика Nimbus, используемого выбором JTree. Итак, добавьте эту строку в метод getTreeCellRendererComponent:

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

Другой вариант - использовать рисовальщик нимбов для фона TreeCellRenderer, но в данной ситуации это кажется излишним.

person Nick Rippe    schedule 17.12.2012
comment
хм ... не совсем, насколько я понял, вопрос заключается в предотвращении окраски фона вне рендерера (при сохранении его внутри). Использование невидимого цвета (если у него есть любой эффект) предотвратит и то, и другое. - person kleopatra; 17.12.2012
comment
@kleopatra Хе-хе ... может быть, в следующий раз я прочитаю вопрос полностью. Хороший улов. - person Nick Rippe; 17.12.2012
comment
ОП здесь; только что зарегистрировался снова после долгого времени, был рад видеть ответ на вопрос, и это работает. Большое спасибо за код и информацию о том, как он обрабатывается на уровне дерева. - person user1359010; 24.02.2013
comment
больше не работает с Java 8. Но ошибка Nimbus исправлена. - person oliholz; 22.01.2015
comment
ОП здесь снова. @oliholz: Извините, но я не вижу, чтобы ошибка Nimbus была исправлена. Пытался построить тривиальное дерево; выбор получает различное поведение выделения в L&F по умолчанию и в Numbus. По умолчанию выделяется только текст узла, в то время как Nimbus выделяет ширину рамки дерева (что было моей первоначальной проблемой). Заимствовал идею в последнем ответе на stackoverflow.com/questions/28691272/ и использовал маляр, который просто осветил цвет, что выглядит лучше. По-прежнему хотелось бы ограничить выделение только текстом узла. Идеи приветствуются. - person user1359010; 23.06.2015
comment
OP добавление к моему комментарию выше. Интересная (?) Ирония: stackoverflow.com/questions/26724913/color-row-in-jtree задает, по сути, обратный вопрос - как получить полную полосу цвета в L&F по умолчанию вместо простого выделения текста узла. - person user1359010; 27.06.2015