Nimbus TableHeader не был выделен как «нажатый»

JTableHaeder по умолчанию не имеет подсветки «нажато». (Нимбус)

NimbusDefaults говорит, что у него есть фоновый рисовальщик [Pressed] по умолчанию.

Что мне делать, чтобы увидеть это, когда я нажимаю на TableHeader?

NimbusDefaultPainter


ОБНОВЛЕНИЕ 1

NimbusStyle.getExtendedState правильно возвращает PRESSED на mouseDown. Но NimbusStyle.getBackgroundPainter(SynthContext) возвращает null, потому что в кеше NimbusStyle.Values есть null для "backgroundPainter$$instance" CacheKey с этим состоянием.

Что не так?


ОБНОВЛЕНИЕ 2

В моем примере показаны JTableHeader и JScrollBar с «нажатым поведением».

Для JScrollBar мой putClientProperty( "Nimbus.State" ) работает с проблемой перерисовки.

public class Header extends JPanel{

    public Header() {
        super(new BorderLayout());
        JTableHeader header = new JTable(5, 3).getTableHeader();
        JScrollBar   scroll = new JScrollBar(JScrollBar.HORIZONTAL);
        add(header, BorderLayout.NORTH);
        add(scroll, BorderLayout.SOUTH);
        scroll.addMouseListener( new PressedBehavior() );
        header.addMouseListener( new PressedBehavior() );
    }

    static public void main( String[] s ) {
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
            SwingUtilities.invokeLater( new Runnable() {
                @Override
                public void run() {
                    JFrame f = new JFrame("Nimbus Pressed Example");
                    f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                    f.setBounds( 150, 150, 300, 200 );
                    f.getContentPane().add( new Header() );
                    f.setVisible( true );
                }
            });
        } catch( Exception fail ) { /*ignore*/ }
    }
    private class PressedBehavior extends MouseAdapter {
        @Override
        public void mouseReleased( MouseEvent e ) {
            JComponent source = (JComponent)e.getComponent();
            source.putClientProperty( "Nimbus.State", null );
        }
        @Override
        public void mousePressed( MouseEvent e ) {
            JComponent source = (JComponent)e.getComponent();
            source.putClientProperty( "Nimbus.State", "Pressed" );
            //source.invalidate();
            //source.repaint();
        }
    }
}

person oliholz    schedule 27.04.2011    source источник


Ответы (1)


технически вам нужно это состояние в компоненте рендеринга, а не в самом JTableHeader:

    @Override
    public void mousePressed( MouseEvent e ) {
        JComponent source = (JComponent)e.getComponent();
        source.putClientProperty( "Nimbus.State", "Pressed" );
        if (source instanceof JTableHeader) {
            ((JComponent) ((JTableHeader) source).getDefaultRenderer())
                .putClientProperty("Nimbus.State", "Pressed");
        }
    }

Проблема заключается в том, что один и тот же экземпляр (компонента рендеринга) используется для всех столбцов, поэтому, если вы перетаскиваете столбец, все отображаются нажатыми...

Редактировать: не удержался и немного покопался... Nimbus оооочень... не хватает, мягко говоря ;-)

Оказывается, по умолчанию действительно есть стили для нажатия, чего не хватает, так это логики для его установки. Вероятно, это не совсем тривиально, потому что логика (также известная как MouseListener) находится в BasicTableHeaderUI, который не знает о состояниях рисовальщика подкласса. Единственное, что поддерживает логика (горячее исправление), — это осознание опрокидывания, но не нажатие.

Хотя мы не можем подключиться к логике (ну, мы могли бы... но это еще один трюк :-), мы можем искать изменения вторичного состояния, такие как свойства draggingColumn/resizingColumn (не связанные) в JTableHeader, и позволить пользовательскому рендереру обновлять себя. по мере необходимости. Вот краткая инструкция:

public static class WrappingRenderer implements TableCellRenderer {

    private DefaultTableCellHeaderRenderer delegate;
    private JTableHeader header;

    public WrappingRenderer(JTableHeader header) {
        this.header = header;
        this.delegate = (DefaultTableCellHeaderRenderer) header.getDefaultRenderer();
        header.setDefaultRenderer(this);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row,
            int column) {
        Component comp = delegate.getTableCellRendererComponent(table, 
                value, isSelected, hasFocus, row, column);
        TableColumn draggedColumn = table.getTableHeader().getDraggedColumn();
        if (draggedColumn != null) {
            if (table.convertColumnIndexToModel(column) == draggedColumn.getModelIndex()) {
                setNimbusState("Pressed");
            } else {
                setNimbusState(null);
            }

        } else {
            setNimbusState(null);
        }
        // do similar for resizing column
        return comp;
    }

    public void setNimbusState(String state) {
        delegate.putClientProperty("Nimbus.State", state);
    }
}
person kleopatra    schedule 04.05.2011
comment
В моем случае это не перетаскивается. ура - person oliholz; 04.05.2011
comment
Перетаскивание @oliholz ​​было просто примером повторного использования средства визуализации для рисования за пределами нажатого столбца ;-) Может произойти по любой причине. Чтобы сделать его наполовину надежным, вам понадобится что-то вроде wrappingRenderer в моем отредактированном ответе. - person kleopatra; 04.05.2011