如何设置JSplitPane-Divider折叠/展开状态?

问题描述:

我有一个JSplitPane是OneTouchExpandable的JFrame。 我想记住JFrame上JSplitPane的最后一个分隔符位置,如果重新打开JFrame,则处理并恢复位置。如何设置JSplitPane-Divider折叠/展开状态?

它工作的很好,但是如果用户通过oneTouchExpandable UI-Widget扩展一边,那么我只在'dispose'中存储'int'-position,并将'int'-position再次设置为JFrame-调整JSplitPane-Divider的大小以跳转到折叠的组件preferredSize。

如何获取/设置折叠/展开状态?

编辑

现在:调整大小 - 行为是确定的,但它不是完全一样的第一次打开相同的行为 - 因为现在我没有MinimumDividerLocation。我想要管理单元,但进一步崩溃状态。

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

我发现,可以通过组件的最小尺寸设置为new Dimension()崩溃在将splitPane的一侧,然后设置分隔条的位置:

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

您可以使用这些设置播放存储和恢复崩溃/展开状态。

+0

呀,调整大小,行为是确定的,但它不是完全一样的相同的行为第一次开放的原因现在我没有MinimumDividerLocation。我想要管理单元,但进一步崩溃状态。 – oliholz 2011-02-28 15:43:18

+0

尝试各种建议的解决方案后,我发现以下解决方案可以工作:''pane.getRightComponent()。setMinimumSize(new Dimension()); ';' – 2014-06-20 09:48:45

调整JSplitPane有一个方法setDividerLocation(双),它设置分隔的位置为JSplitPane的大小的百分比。 前段时间我试图创建类似的功能。我有同样的问题。但即使当我使用setDividerLocation(double)方法时,它也不能正常工作。我相信这只是JSplitPane的错误。

隐藏你的对话框/框架的选项?

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

}); 

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

我改进切换功能的版本:

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

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

空隙javax.swing.JSplitPane.setDividerLocation(双proportionalLocation)

设置分隔位置为百分比JSplitPane大小的 的年龄。这个方法的实现依据 setDividerLocation(int)。此方法立即根据当前大小更改分割窗格的大小。如果拆分窗格不是 正确实现并在屏幕上,此方法将不起作用(新 分隔符位置将成为(当前大小*比例位置) 这是0)。

所以基本上你需要有主的JFrame 创建你的整个UI,称为.pack()之后,你可以使用JSplitPane.setDividerLocation(双)。如果你在UI布局和所有的东西完成之前做了这个,那么这个方法就不会做任何事情,因为它在文档中陈述并且你已经经历过。

将divider位置强制为非常小/大的值以隐藏顶部/底部组件工作,但由于组件最小大小而导致拆分窗格被重新调整大小时会失败。将该大小设置为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