7

在一个JSplitPane,你有一个setOneTouchExpandable方法,它为你提供了 2 个按钮来快速完全隐藏或完全显示JSplitPane

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

我可能错误地解释了自己。我希望拆分窗格在开始时仅显示 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.01.0不会隐藏正确的组件。这是我的问题!

4

6 回答 6

6
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,你就会明白我的问题

阅读精美的手册并解决问题。

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

拆分窗格默认

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);
            }
        });
    }
}
于 2012-02-07T13:54:32.187 回答
4

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

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

以及如何使用它的示例:

public class SplitPaneDemo extends JFrame implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new SplitPaneDemo());
    }

    ExtOneTouchJSplitPane hSplitPane;
    ExtOneTouchJSplitPane vSplitPane;

    public SplitPaneDemo() {
        createView();
    }

    public void createView() {
        setTitle("SplitPane-Demo");
        setLayout(new BorderLayout(0, 0));

        hSplitPane = new ExtOneTouchJSplitPane();
        JButton jBLeft = new JButton("<html><body> &nbsp;<br>Left Component<br> &nbsp;</body></html>");
        JButton jBRight = new JButton("<html><body> &nbsp;<br>Right Component<br> &nbsp;</body></html>");
        jBLeft.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                hSplitPane.oneTouchClickLeft();
            }
        });
        jBRight.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                hSplitPane.oneTouchClickRight();
            }
        });
        hSplitPane.setLeftComponent(jBLeft);
        hSplitPane.setRightComponent(jBRight);

        add(hSplitPane, BorderLayout.CENTER);

        vSplitPane = new ExtOneTouchJSplitPane(JSplitPane.VERTICAL_SPLIT);
        JButton jBUp = new JButton("<html><body> &nbsp;<br>Up Component<br> &nbsp;</body></html>");
        JButton jBDown = new JButton("<html><body> &nbsp;<br>Down Component<br> &nbsp;</body></html>");
        jBUp.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                vSplitPane.oneTouchClickUp();
            }
        });
        jBDown.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                vSplitPane.oneTouchClickDown();
            }
        });
        vSplitPane.setTopComponent(jBUp);
        vSplitPane.setBottomComponent(jBDown);

        add(vSplitPane, BorderLayout.SOUTH);
    }

    @Override
    public void run() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(400, 400);
        setVisible(true);

        hSplitPane.oneTouchClickLeft();
    }
}
于 2018-05-31T21:03:37.023 回答
3

你可以简单地使用这个:

public void setDividerLocation(double proportionalLocation)

splitPane.setDividerLocation(0.0d);

或者。

splitPane.setDividerLocation(1.0d);

取决于您是要先隐藏左侧组件还是右侧组件。

于 2012-02-07T13:53:17.450 回答
1

@0__ 的回答暗示您应该使用AncestorListener来设置分隔线位置,并将其考虑在内ComponentListener还不够,我不知道为什么)。

然而,这还不够:如果分割平面以某种方式被调整大小(例如,因为它的布局管理器决定它应该,当框架被调整大小时),你想要隐藏的组件的一小部分仍然会显示。这是因为组件的最小尺寸不为零。可以通过将其归零来解决setMinimumSize(new Dimension())(如其他答案中所述),但如果这不是一个选项,您可以侵入拆分窗格 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) { }
});
于 2016-06-29T13:07:59.577 回答
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 = ()
})
于 2016-05-06T00:38:03.713 回答
0

结合其他答案,doClick延迟通过AncestorListener对我有用。见说明:

if (wantHiddenPane) {
  // The splitPane's "onload" event approximation =
  // the hierarchy ancestor changes when the pane gets packed/made visible on screen
  // Which is when the splitPane dimensions have been initialized based on available screen space
  // So that edits to the divider location can take effect after that.
   splitPane.addAncestorListener(new AncestorListener() {
       public void ancestorAdded(AncestorEvent ev) {
          // Pressing the oneTouch button shows/hides a pane while remembering the last custom dragged size
          BasicSplitPaneUI ui = (BasicSplitPaneUI) splitPane.getUI();
          JButton neededOneTouchBtn = (JButton) ui.getDivider().getComponent(isHiddenPaneLeftTop ? 0 : 1);
          neededOneTouchBtn.doClick();
        }
        // only run once
         splitPane.removeAncestorListener(this);
       }

       public void ancestorRemoved(AncestorEvent ev) {
       }

       public void ancestorMoved(AncestorEvent ev) {
       }
     });
 }
于 2021-09-13T20:39:40.223 回答