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

时间:2011-02-08 14:51:14

标签: java swing jsplitpane

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

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

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

修改

现在:调整大小行为是正常的,但它与第一​​次打开的行为不完全相同 - 因为现在我没有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 个答案:

答案 0 :(得分:12)

我发现可以通过将组件的最小大小设置为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 :(得分: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();
    }
}

答案 2 :(得分:1)

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

在查看BasicSplitPaneUI及相关课程后,结果显示&#34;触摸扩展&#34;按钮正在调用BasicSPlitPaneUI.setKeepHidden(true),因此分配器将在调整大小时粘在任一端。

不幸的是,该方法是包私有的,但可以使用内省as shown in another answer来设置关联的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

答案 3 :(得分: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);
    }

});

答案 4 :(得分:0)

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布局之前完成并完成所有这些工作,那么该方法将不会像文档中所说的那样做任何事情而你已经经历过。

答案 5 :(得分:-1)

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

答案 6 :(得分:-1)

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