当OneTouchExpandable设置为true时,如何以编程方式设置JSplitPane以隐藏右/底组件?

时间:2012-02-07 13:34:40

标签: java swing jsplitpane

JSplitPane中,您使用setOneTouchExpandable方法为您提供了2个按钮,可以快速完全隐藏或完整显示JSplitPane

我的问题是如何以编程方式“点击”JSplitPane上的隐藏按钮?

我可能错误地解释了自己。我希望splitpane在开始时只显示2个组件中的一个(这就是我点击的意思)。

这有效:

import javax.swing.*;

class SplitPaneDefault {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JSplitPane sp = new JSplitPane(
                    JSplitPane.HORIZONTAL_SPLIT,
                    new JTree(),
                    new JTree());
                sp.setOneTouchExpandable(true);
                sp.setDividerLocation(0.0);
                JOptionPane.showMessageDialog(null, sp);
            }
        });
    }
}

但将0.0替换为1.0并不会隐藏正确的组件。这是我的问题!

5 个答案:

答案 0 :(得分:5)

import javax.swing.*;

class SplitPaneDefault {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JSplitPane sp = new JSplitPane(
                    JSplitPane.HORIZONTAL_SPLIT,
                    new JTree(),
                    new JTree());
                sp.setOneTouchExpandable(true);
                sp.setDividerLocation(0.0);
                JOptionPane.showMessageDialog(null, sp);
            }
        });
    }
}

  

用1.0替换0.0,你得到我的问题

阅读精细手册并解决问题。

  

此方法会立即根据其当前大小更改拆分窗格的大小。 如果拆分窗格未正确实现 并且在屏幕上,此方法将 无效 ... < / p>

SplitPaneDefault

import javax.swing.*;

class SplitPaneDefault {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JSplitPane sp = new JSplitPane(
                    JSplitPane.HORIZONTAL_SPLIT,
                    new JTree(),
                    new JTree());
                sp.setOneTouchExpandable(true);
                JFrame f = new JFrame("Split Pane To Right");
                f.add(sp);
                f.pack();
                // sp now has a non-zero size!
                sp.setDividerLocation(1.0);
                f.setLocationByPlatform(true);
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }
}

答案 1 :(得分:2)

你可以简单地使用它:

public void setDividerLocation(double proportionalLocation)

splitPane.setDividerLocation(0.0d);

splitPane.setDividerLocation(1.0d);

取决于您想要隐藏左侧组件的第一个或右侧组件。

答案 2 :(得分:1)

解决setDividerLocation(1.0)在框架变得可显示之前无效的问题,可以使用AncestorListener

sp.addAncestorListener(new AncestorListener {
  def ancestorAdded  (event: AncestorEvent): Unit = sp.setDividerLocation(1.0)

  def ancestorRemoved(event: AncestorEvent): Unit = ()
  def ancestorMoved  (event: AncestorEvent): Unit = ()
})

答案 3 :(得分:1)

@0__'s answer暗示您应该使用AncestorListener来设置分隔符位置并将其考虑在内ComponentListener是不够的,我不确定为什么。)

然而,这还不够:如果分割平面以某种方式调整大小(例如,因为它的布局管理器决定它应该,当框架已调整大小时),只有一小部分您想要隐藏的组件仍会显示。 这是由于组件最小尺寸不为零。可以通过将setMinimumSize(new Dimension())归零来解决问题(如that other answer中所述),但如果这不是一个选项,则可以入侵拆分窗格UI:

如果您正在使用标准BasicSplitPaneUI,则可以破解其keepHidden布尔字段并将其强制转换为true,因此分隔符将粘贴到任意一侧:

sp.addAncestorListener(new AncestorListener() {
    @Override
    public void ancestorAdded(AncestorEvent event) {
        sp.setDividerLocation(1.0); // Divider is positioned
        Field m = BasicSplitPaneUI.class.getDeclaredField("keepHidden");
        m.setAccessible(true);
        m.set(sp.getUI(), true); // Divider position will stick
        //sp.removeAncestorListener(this); // Uncomment for a one-shot event
    }

    @Override public void ancestorRemoved(AncestorEvent event) { }
    @Override public void ancestorMoved(AncestorEvent event) { }
});

答案 4 :(得分:1)

这是另一种解决方案,可能有点脏,但它有效;) 我希望代码能说明问题。

==== local: tried
[warn]   C:\Users\UserName\.ivy2\local\com.atlassian.jwt\jwt-core\1.6.1\ivys\ivy.xml
[warn] ==== public: tried
[warn]   https://repo1.maven.org/maven2/com/atlassian/jwt/jwt-core/1.6.1/jwt-core-1.6.1.pom
[warn] ==== local-preloaded-ivy: tried
[warn]   C:\Users\UserName\AppData\Local\Temp\sbt-global-pluginstub\preloaded\com.atlassian.jwt\jwt-core\1.6.1\ivys\ivy.xml
[warn] ==== local-preloaded: tried
[warn]   file:/C:/Users/UserName/AppData/Local/Temp/sbt-global-pluginstub/preloaded/com/atlassian/jwt/jwt-core/1.6.1/jwt-core-1.6.1.pom

以及如何使用它的示例:

public class ExtOneTouchJSplitPane extends JSplitPane {
    private static final long serialVersionUID = -2320161961382260438L;

    JButton jBLeftUp;
    JButton jBRightDown;

    public ExtOneTouchJSplitPane() {
        super();
        setOneTouchExpandable(true);
        extractDividerButtons();
    }

    public ExtOneTouchJSplitPane(int newOrientation) {
        super(newOrientation);
        setOneTouchExpandable(true);
        extractDividerButtons();
    }

    public ExtOneTouchJSplitPane(int newOrientation, boolean newContinuousLayout) {
        super(newOrientation, newContinuousLayout);
        setOneTouchExpandable(true);
        extractDividerButtons();
    }

    public ExtOneTouchJSplitPane(int newOrientation, boolean newContinuousLayout, Component newLeftComponent, Component newRightComponent) {
        super(newOrientation, newContinuousLayout, newLeftComponent, newRightComponent);
        setOneTouchExpandable(true);
        extractDividerButtons();
    }

    public ExtOneTouchJSplitPane(int newOrientation, Component newLeftComponent, Component newRightComponent) {
        super(newOrientation, newLeftComponent, newRightComponent);
        setOneTouchExpandable(true);
        extractDividerButtons();
    }

    private void extractDividerButtons() {
        BasicSplitPaneUI ui = (BasicSplitPaneUI) getUI();
        jBLeftUp = (JButton) ui.getDivider().getComponent(0);
        jBRightDown = (JButton) ui.getDivider().getComponent(1);
    }

    public void oneTouchClickLeft() {
        jBLeftUp.doClick();
    }

    public void oneTouchClickRight() {
        jBRightDown.doClick();
    }

    public void oneTouchClickUp() {
        jBLeftUp.doClick();
    }

    public void oneTouchClickDown() {
        jBRightDown.doClick();
    }
}