2011-02-08 4 views
6

У меня есть JFrame с JSplitPane, который является OneTouchExpandable. Я хочу помнить, что последнее положение разделителя JSplitPane на JFrame уничтожает и восстанавливает позицию, если JFrame снова открывается.Как установить JSplitPane-Divider свернуть/развернуть состояние?

Он работает хорошо, но если пользователь расширяет одну сторону через oneTouchExpandable UI-Widget, то Я сохраняю только «int'-Position on dispose» и снова устанавливаю «int'-Position» с последствием на JFrame- изменение размера JSplitPane-Divider переходит к свернутому Component preferredSize.

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

EDIT

Сейчас: изменения размера, поведение в порядке, но это не точно такое же поведение, как в первый раз открыть - Потому что сейчас у меня нет MinimumDividerLocation. Мне нужен SnapIn, но дальше - collapsedState.

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

ответ

11

Я обнаружил, что можно свернуть одну сторону splitpane, установив минимальный размер компонента 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); 

Вы можете играть с этими настройками для хранения и восстановить состояние collapse/expand.

+0

да, изменение размера, поведение в порядке, но это не точно такое же поведение как впервые открытое - причина теперь у меня нет MinimumDividerLocation. Мне нужен SnapIn, но дальше - collapsedState. – oliholz

+0

После того, как вы попробовали различные предлагаемые решения, я нашел следующее решение для работы: '' pane.getRightComponent(). SetMinimumSize (new Dimension()); pane.setResizeWeight (1.0d); '' –

+0

Это сработало для меня (спасибо! :)), но позиция разделителя не прилипает при изменении размера, особенно когда вы не можете переопределить минимальный размер компонента. См. Мой ответ, чтобы взломать его, если вы используете 'BasicSplitPaneUI'. – Matthieu

0

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

0

Спрятал ваш диалог/фрейм вариант?

// 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
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(); 
     } 
    } 
+1

, пожалуйста, предоставьте краткое объяснение вашего ответа. –

1

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

/** 
* 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

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

недействительными javax.swing.JSplitPane.setDividerLocation (двойной proportionalLocation)

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

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

1

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

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

К сожалению, этот метод является пакет-частные, но установить соответствующий keepHidden поле может быть сделано с помощью самоанализа, as shown in another answer:

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 
Смежные вопросы