gpt4 book ai didi

swing - 需要无效 Swing 组件的高度

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:56:55 29 4
gpt4 key购买 nike

基本设置是这样的:我有一个垂直的 JSplitPane,我希望它有一个固定大小的底部组件和一个调整大小的顶部组件,我通过调用 setResizeWeight(1.0) 来完成。在此应用程序中,有一个按钮可以恢复“默认”窗口配置。窗口的默认高度为桌面高度,默认分隔线位置为距拆分 Pane 底部 100 像素。

为了将分隔线位置设置为 100px,我将 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 将在此时得到验证,我担心这可能是一个错误的假设。

有没有更好的办法?

最佳答案

花了一段时间(可能是因为这里是清晨 :-) 才理解这个问题,所以只是为了确保我明白了:

  • 底部组件的大小可以随时由用户决定
  • 调整框架大小时,顶部组件的所有高度都应发生变化
  • 有一个选项可以恢复到默认大小,独立于之前的任何设置
  • “default”表示底部组件的高度必须固定为xx

如果是这样,解决方案是将调整框架大小与调整底部组件大小分开。您的第二个选择是正确的:调整框架大小并将底部 comp 调整大小包装到 invokeLater(EventQueue 或 SwingUtilities,无关紧要)。

void restoreDefaults() {
f.setSize(f.getWidth(), getDesktopRect(f.getGraphicsConfiguration()).height);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
sp.setDividerLocation(sp.getSize().height - 100);

}
});
}

这保证按预期工作,因为 invokeLater 将请求放在所有已排队事件之后:

 /**
* Causes <i>doRun.run()</i> to be executed asynchronously on the
* AWT event dispatching thread. This will happen after all
* pending AWT events have been processed. [...]
* If invokeLater is called from the event dispatching thread --
* for example, from a JButton's ActionListener -- the <i>doRun.run()</i> will
* still be deferred until all pending events have been processed.

关于swing - 需要无效 Swing 组件的高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6946880/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com