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

我有一个带有JSplitPane的JFrame,它是OneTouchExpandable。 我想记住JFlitPane在JFrame上的最后一个Divider位置处理并在重新打开JFrame时恢复Position。

它运行良好,但是如果用户通过oneTouchExpandable UI-Widget扩展一侧,那么我只存储处理中的’int’-Position并再次设置’int’-Position,结果是JFrame调整JSplitPane-Divider的大小跳转到折叠的Component preferredSize。

如何获取/设置崩溃/展开状态?

编辑

现在: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 ); } } 

我发现通过将组件的最小大小设置为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); 

您可以使用这些设置来存储和恢复折叠/展开状态。

我改进了切换function的版本:

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

将分隔符位置强制为非常小/较大的值以隐藏顶部/底部组件,但由于组件的最小大小,在分割窗格resize时会失败。 将该大小设置为0(在接受的答案中建议)有效,但有些情况下您不能/不想覆盖它。

在查看BasicSplitPaneUI和相关类之后,事实certificate“单触扩展”按钮正在调用BasicSPlitPaneUI.setKeepHidden(true) ,因此分配器将在resize时粘在任一端。

不幸的是,该方法是包私有的,但设置相关的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 

JSplitPane有一个方法setDividerLocation(double),它将分隔符位置设置为JSplitPane大小的百分比。 我不久前尝试创建类似的function。 我有同样的问题。 但即使我使用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(); } } 

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

void javax.swing.JSplitPane.setDividerLocation(double proportionalLocation)

将分隔符位置设置为JSplitPane大小的百分比。 此方法是根据setDividerLocation(int)实现的。 此方法会立即根据其当前大小更改拆分窗格的大小。 如果未正确实现拆分窗格并且在屏幕上,此方法将无效(新的分隔符位置将变为(当前大小* proportionalLocation),即0)。

所以基本上你需要创建你的整个UI,在主JFrame上调用.pack()然后你可以使用JSplitPane.setDividerLocation(double)。 如果你在UI布局之前完成所有这些工作,那么该方法将无需执行任何操作,因为它在文档中已经说明并且您已经体验过。