基本设置是这样的:我有一个垂直的 JSplitPane,我想要一个固定大小的底部组件和一个调整大小的顶部组件,我通过调用setResizeWeight(1.0)
. 在这个应用程序中有一个按钮可以恢复“默认”窗口配置。窗口的默认高度是桌面高度,默认分隔线位置是距拆分窗格底部 100 像素。
要将分隔线位置设置为 100 像素,我将 JSplitPane 高度设置为 100。问题是,就在此之前,我调整了 JFrame 的大小,并且由于代码在按钮回调中,因此 JSplitPane 已失效但尚未调整大小。所以分频器位置设置不正确。
这是一个SSCCE。单击该按钮两次以查看问题。第一次单击将调整窗口大小,但分隔线位置保持不变(相对于窗口底部)。第二次单击会正确移动分隔线,因为窗口大小没有改变。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSplitPane;
public class SSCCE {
/**
* @param args unused
*/
public static void main(String[] args) {
new SSCCE();
}
private final JFrame f = new JFrame("JSplitPane SSCE");
private final JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT,true);
public SSCCE() {
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sp.add(new JLabel("top"));
sp.add(new JLabel("bottom"));
sp.setResizeWeight(1.0);
f.getContentPane().add(sp);
f.getContentPane().add(new JButton(new AbstractAction("Resize to Default") {
@Override
public void actionPerformed(ActionEvent e) {
restoreDefaults();
}
}),BorderLayout.PAGE_END);
f.setSize(400,300);
f.setVisible(true);
}
void restoreDefaults() {
f.setSize(f.getWidth(), getDesktopRect(f.getGraphicsConfiguration()).height);
sp.setDividerLocation(sp.getSize().height - 100); // Does not work on first button press
}
Rectangle getDesktopRect(GraphicsConfiguration gc) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension size = toolkit.getScreenSize();
Insets insets = toolkit.getScreenInsets(gc);
return new Rectangle(insets.left, insets.top, size.width - (insets.left + insets.right), size.height - (insets.top + insets.bottom));
}
}
我已经想到了一些可以解决这个问题的方法,但它们看起来都有些骇人听闻。到目前为止,我最好的想法是f.validate()
在设置帧大小和设置分隔线位置之间进行调用,但我担心早期强制验证可能会产生副作用。
我想到的另一个选项是用于EventQueue.invokeLater()
将调用设置为事件队列末尾的分隔符位置。但这对我来说似乎有风险——我假设 JSplitPane 将在那时得到验证,我担心这可能是一个错误的假设。
有没有更好的办法?