8

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

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

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

编辑

现在:resize-Behavior 没问题,但它与第一​​次打开时的行为不完全相同——因为现在我没有 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 );
    }
}
4

7 回答 7

13

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

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

于 2011-02-26T15:54:40.493 回答
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();
    }
}
于 2012-07-01T15:53:58.753 回答
1

将分隔线位置强制设置为非常小/大的值以隐藏顶部/底部组件有效,但在调整拆分窗格的大小时会失败,因为组件的最小尺寸。将该大小设置为 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
于 2016-07-01T11:06:41.993 回答
0

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

无效 javax.swing.JSplitPane.setDividerLocation(双比例位置)

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

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

于 2014-07-31T23:35:14.620 回答
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);
    }

});
于 2011-02-28T16:28:03.290 回答
-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();
        }
    }
于 2012-04-13T08:36:51.533 回答
-1

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

于 2011-02-08T15:09:27.563 回答