当OneTouchExpandable设置为true时,如何以编程方式设置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); } }); } } 

但用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); sp.setDividerLocation(0.0); JOptionPane.showMessageDialog(null, sp); } }); } } 

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

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

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

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

你可以简单地使用这个:

 public void setDividerLocation(double proportionalLocation) splitPane.setDividerLocation(0.0d); 

要么。

 splitPane.setDividerLocation(1.0d); 

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

解决setDividerLocation(1.0)在帧可显示之前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 = () }) 

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

但是,这还不够 :如果分割平面以某种方式resize(例如,因为它的布局管理器决定它应该,当框架已经resize时),您想要隐藏的组件的一小部分仍将显示。 这是由于组件最小尺寸不为零。 它可以通过使用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) { } }); 

这是另一个解决方案,可能有点脏,但它的工作原理;)我希望代码说明一切。

 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("  
Left Component
 "); JButton jBRight = new JButton("  
Right Component
 "); 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("  
Up Component
 "); JButton jBDown = new JButton("  
Down Component
 "); 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(); } }