java 如何设置 JSplitPane-Divider 折叠/展开状态?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4934499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set JSplitPane-Divider collapse/expand State?
提问by oliholz
I have a JFrame with a JSplitPane that is OneTouchExpandable. I want to remember the last Divider position of the JSplitPane on JFrame dispose and restore the Position if the JFrame is reopened.
我有一个 JFrame 和一个 JSplitPane,它是 OneTouchExpandable。我想记住 JFrame 上 JSplitPane 的最后一个分隔线位置,如果重新打开 JFrame,则恢复位置。
It works well, but if the User expand one Side via the oneTouchExpandable UI-Widget then I store only the 'int'-Position on dispose and set the 'int'-Position back again with the consequence on JFrame-resizing the JSplitPane-Divider jumps to the collapsed Component preferredSize.
它运行良好,但如果用户通过 oneTouchExpandable UI-Widget 扩展一侧,那么我只存储 'int'-Position on dispose 并再次设置 'int'-Position,结果是 JFrame 调整 JSplitPane-Divider 的大小跳转到折叠的组件 preferredSize。
How can I get/set the collapse/expand State?
如何获取/设置折叠/展开状态?
EDIT
编辑
Now: the resize-Behavior is OK, but it is not exactly the same behavior like the first-time-open - cause now I have no MinimumDividerLocation. I wanted the SnapIn but further the collapsedState.
现在: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 );
}
}
回答by Martijn Courteaux
I found that it is possible to collapse one side of the splitpane by setting the minimum size of the component to new Dimension()
and then set the divider location:
我发现可以通过将组件的最小尺寸设置为new Dimension()
然后设置分隔位置来折叠 splitpane 的一侧:
// 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);
You can play with these settings to store and restore the collapse/expand state.
您可以使用这些设置来存储和恢复折叠/展开状态。
回答by Marko Kotar
I improved version of toggle function:
我改进了切换功能的版本:
/**
* 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();
}
}
回答by Matthieu
Forcing the divider position to a very small/large value to hide the top/bottom component works, but is defeated when the split pane gets resized, because of the component minimum size. Setting that size to 0 (as proposed in the accepted answer) works, but there are cases when you cannot/don't want to override that.
将分隔符位置强制设置为非常小/大的值以隐藏顶部/底部组件是可行的,但是当拆分窗格调整大小时会失败,因为组件的最小尺寸。将该大小设置为 0(如已接受的答案中所建议的)有效,但在某些情况下您不能/不想覆盖它。
After looking into the BasicSplitPaneUI
and associated classes, it turns out the "one touch expanding" buttons are calling BasicSPlitPaneUI.setKeepHidden(true)
, so the divider will stick to either end when resized.
在查看BasicSplitPaneUI
和关联的类之后,事实证明“一键扩展”按钮正在调用BasicSPlitPaneUI.setKeepHidden(true)
,因此在调整大小时分隔线将粘在任一端。
Unfortunately, that method is package-private but setting the associated keepHidden
field can be done using introspection, 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
回答by SpeedProg
http://docs.oracle.com/javase/7/docs/api/javax/swing/JSplitPane.html
http://docs.oracle.com/javase/7/docs/api/javax/swing/JSplitPane.html
void javax.swing.JSplitPane.setDividerLocation(double proportionalLocation)
Sets the divider location as a percentage of the JSplitPane's size. This method is implemented in terms of setDividerLocation(int). This method immediately changes the size of the split pane based on its current size. If the split pane is not correctly realized and on screen, this method will have no effect (new divider location will become (current size * proportionalLocation) which is 0).
无效javax.swing.JSplitPane.setDividerLocation(双比例位置)
将分隔符位置设置为 JSplitPane 大小的百分比。这个方法是根据 setDividerLocation(int) 实现的。此方法会根据当前大小立即更改拆分窗格的大小。如果拆分窗格没有正确实现并在屏幕上,则此方法将无效(新的分隔符位置将变为(当前大小 * 比例位置)为 0)。
So basically you need to have created your whole UI, called .pack() on the main JFrame AND after that you can use JSplitPane.setDividerLocation(double). If you do it before UI layouting and all that stuff is done, the method will just do nothing as it states in the documentation and you already experienced.
所以基本上你需要在主 JFrame 上创建你的整个 UI,称为 .pack(),然后你可以使用 JSplitPane.setDividerLocation(double)。如果您在 UI 布局之前执行此操作并且所有这些都已完成,则该方法将不会执行文档中所述且您已经体验过的任何操作。
回答by Martijn Courteaux
Is hiding your dialog/frame an option?
隐藏您的对话框/框架是一种选择吗?
// 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);
}
});
回答by kac-
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();
}
}
回答by Highlander
JSplitPane has a method setDividerLocation(double), which sets the divider location as a percentage of the JSplitPane's size. I tried to create similar functionality some time ago. I had the same problem. But even when I use the setDividerLocation(double) method, it didn't work properly. I believe that it's just JSplitPane bug.
JSplitPane 有一个方法 setDividerLocation(double),它将分隔符位置设置为 JSplitPane 大小的百分比。前段时间我尝试创建类似的功能。我有同样的问题。但即使我使用 setDividerLocation(double) 方法,它也无法正常工作。我相信这只是 JSplitPane 错误。