Как установить JSplitPane-Divider развал / развернуть состояние? - PullRequest
6 голосов
/ 08 февраля 2011

У меня есть JFrame с JSplitPane, который OneTouchExpandable. Я хочу запомнить последнюю позицию Разделителя JSplitPane на JFrame и восстановить Позицию, если JFrame будет вновь открыт.

Это работает хорошо, но если пользователь расширяет одну сторону с помощью oneTouchExpandable UI-Widget, то Я сохраняю только «int»-Position при утилизации и снова устанавливаю «int»-Position с последующим изменением JFrame изменения размера JSplitPane-Divider при переходе к свернутому компоненту предпочитаемого размера.

Как я могу получить / установить состояние свертывания / расширения?

EDIT

Теперь: поведение resize-Behavior в порядке, но оно не совсем такое же, как при первом открытии - потому что теперь у меня нет MinimumDividerLocation. Я хотел SnapIn, но в дальнейшем свернул состояние.

public class SplitPaneState {
    public static void main( String[] args ) {
        SwingUtilities.invokeLater( new Runnable() {
            @Override
            public void run() {
                new SplitPaneState().createAndSowGUI();
            }
        });
    }

    private int position = -1;
    private Dimension size = new Dimension( 500, 300 );

    private void createAndSowGUI() {
        final JFrame frame = new JFrame("frame");
        frame.setSize( 200, 100 );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setLocationRelativeTo( null );
        frame.getContentPane().add( new JButton( new AbstractAction(){
           {
               putValue( Action.NAME, "Open Dialog" );
           }
            @Override
            public void actionPerformed( ActionEvent e ) {
                final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JLabel( "left Component" ), new JLabel( "right Component" ));
                splitPane.setContinuousLayout( true );
                splitPane.setOneTouchExpandable( true );
                if(position != -1) {
                    boolean LeftIsCollapsed = position < splitPane.getMinimumDividerLocation();
                    if(LeftIsCollapsed) {
                        splitPane.getLeftComponent().setMinimumSize(new Dimension()); // fix by Martijn Courteaux
                        splitPane.setDividerLocation(0.0d);                           // fix by Martijn Courteaux
                    }else {
                        splitPane.setDividerLocation(position);
                    }
                }
                JDialog dialog = new JDialog(frame,"dialog"){
                    @Override
                    public void dispose() {
                        position = splitPane.getDividerLocation();
                        size = this.getSize();
                        super.dispose();
                    }
                };
                dialog.setSize( size );
                dialog.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
                dialog.setLocationRelativeTo( frame );
                dialog.getContentPane().add( splitPane );
                dialog.setVisible( true );
                }
           }
       ));
       frame.setVisible( true );
    }
}

Ответы [ 7 ]

12 голосов
/ 26 февраля 2011

Я обнаружил, что можно свернуть одну сторону разделенной панели, установив минимальный размер компонента на new Dimension(), а затем установить расположение разделителя:

// Hide left or top
pane.getLeftComponent().setMinimumSize(new Dimension());
pane.setDividerLocation(0.0d);

// Hide right or bottom
pane.getRightComponent().setMinimumSize(new Dimension());
pane.setDividerLocation(1.0d);

Вы можете поиграть с этими настройками, чтобы сохранить и восстановить состояние свертывания / развертывания.

1 голос
/ 01 июля 2016

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

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

К сожалению, этот метод является закрытым для пакета, но установка связанного поля keepHidden может быть выполнена с помощью самоанализа, , как показано в другом ответе :

sp.setDividerLocation(<0 or 999999>); // Divider is positioned at the top/bottom
Field m = BasicSplitPaneUI.class.getDeclaredField("keepHidden");
m.setAccessible(true);
m.set(sp.getUI(), true); // Divider position will stick
1 голос
/ 01 июля 2012

Я улучшил версию функции переключения:

/**
 * toggle JSplitPane
 * @param sp - splitpane to toggle
 * @param upLeft - is it left or top component to collapse? or button or right
 * @param collapse - true component should be collapsed
 */
public void toggle(JSplitPane sp, boolean upLeft, boolean collapse) {
    try {
        //get divider object
        BasicSplitPaneDivider bspd = ((BasicSplitPaneUI) sp.getUI()).getDivider();
        Field buttonField;

        //get field button from divider
        if (upLeft) {
            if (collapse != (sp.getDividerLocation() < sp.getMinimumDividerLocation())) {
                return;
            }
            buttonField = BasicSplitPaneDivider.class.getDeclaredField(collapse ? "rightButton" : "leftButton");
        } else {
            if (collapse != (sp.getDividerLocation() > sp.getMaximumDividerLocation())) {
                return;
            }

            buttonField = BasicSplitPaneDivider.class.getDeclaredField(collapse ? "leftButton" : "rightButton");
        }
        //allow access
        buttonField.setAccessible(true);
        //get instance of button to click at
        JButton button = (JButton) buttonField.get(((BasicSplitPaneUI) sp.getUI()).getDivider());
        //click it
        button.doClick();
        //if you manage more dividers at same time before returning from event,
        //you should update layout and ui, otherwise nothing happens on some dividers:
        sp.updateUI();
        sp.doLayout();


    } catch (Exception e) {
        e.printStackTrace();
    }
}
0 голосов
/ 01 августа 2014

http://docs.oracle.com/javase/7/docs/api/javax/swing/JSplitPane.html

void javax.swing.JSplitPane.setDividerLocation (двойное пропорциональное расположение)

Устанавливает расположение делителя в процентах от Размер JSplitPane. Этот метод реализован с точки зрения setDividerLocation (INT). Этот метод сразу меняет размер разделенная панель на основе ее текущего размера. Если разделенная панель не правильно реализованный и на экране, этот метод не будет иметь никакого эффекта (новый расположение делителя станет (текущий размер * пропорциональное расположение) что 0).

Таким образом, в основном вам нужно создать весь пользовательский интерфейс, называемый .pack () на основном JFrame. И после этого вы можете использовать JSplitPane.setDividerLocation (double). Если вы сделаете это до макета пользовательского интерфейса и все это будет сделано, метод просто ничего не сделает, как указано в документации, и вы уже испытали это.

0 голосов
/ 13 апреля 2012
public static void toggle(JSplitPane sp, boolean collapse) {
        try {
            BasicSplitPaneDivider bspd = ((BasicSplitPaneUI) sp.getUI()).getDivider();
            Field buttonField = BasicSplitPaneDivider.class.
                    getDeclaredField(collapse ? "rightButton" : "leftButton");
            buttonField.setAccessible(true);
            JButton button = (JButton) buttonField.get(((BasicSplitPaneUI) sp.getUI()).getDivider());
            button.getActionListeners()[0].actionPerformed(new ActionEvent(bspd, MouseEvent.MOUSE_CLICKED,
                    "bum"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
0 голосов
/ 28 февраля 2011

Является ли опция скрытия вашего диалогового окна / фрейма?

// Create the dialog/frame which contains the JSplitPane
final JFrame frame = new JFrame("JSplitPane Problem");
frame.setCloseOperation(JFrame.HIDE_ON_CLOSE);
// ...
myButton.addActionListener(new ActionListener()
{
    public void actionPerformed(ActionEvent ae)
    {
        if (!frame.isVisible())
           frame.setVisible(true);
    }

});
0 голосов
/ 08 февраля 2011

JSplitPane имеет метод setDividerLocation (double), который устанавливает расположение делителя в процентах от размера JSplitPane. Я пытался создать подобную функциональность некоторое время назад. У меня такая же проблема. Но даже когда я использую метод setDividerLocation (double), он не работает должным образом. Я считаю, что это просто ошибка JSplitPane.

...