当前位置: 首页 > 面试题库 >

需要无效的Swing组件的高度

齐承泽
2023-03-14
问题内容

基本设置是这样的:我有一个垂直的JSplitPane,我想具有一个固定大小的底部组件和一个调整大小的顶部组件,这可以通过调用来实现setResizeWeight(1.0)。在此应用程序中,有一个按钮可以还原“默认”窗口配置。窗口的默认高度是桌面高度,默认的分隔线位置是从拆分窗格底部起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将在那时进行验证,并且我担心这可能是一个错误的假设。

有没有更好的办法?


问题答案:

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

  • 底部组件的大小可以是用户始终决定的大小
  • 调整框架大小时,顶部组件应发生所有高度变化
  • 有一个还原为默认大小的选项,与之前的任何设置无关
  • “默认”表示底部组件的固定高度必须为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.


 类似资料:
  • 问题内容: 我想使一个组件占据Container的maximumAvailableHeight。例如,在下面粘贴的代码中,我将根框架定为800,600。我只想设置该框架的高度/宽度(并且我不想尝试对其子像素进行像素化)。如果运行此命令,则会看到UI对齐不良。 首先,我希望面板(位于根框架内)占据框架的100%的高度(在这种情况下,为800px减去用于绘制框架标题的空间)。 其次,在面板内部,我有一

  • 我只是试图通过本教程springboot,但当我运行它显示一个错误。我不明白这个错误。 ”描述: com.mii.tugas.中setEmf方法的参数0。Mahasiswao需要一个无法找到的'javax.persistence.EntityManagerFactory'类型的bean。 措施: 考虑定义“javax”类型的bean。坚持不懈配置中的EntityManagerFactory。" 这

  • 我为即将到来的愚蠢问题提前道歉。 是否有JPanel用于javaFX的油漆组件方法的替代品?或者我应该只使用嵌入了Swing的JFXPanel? 例如,我认为时间轴与Swing中的计时器相同,面板/油漆组件对应的是什么? 编辑:例如,我们如何制作一个从x-y坐标到另一个坐标的圆的动画?(当然,不使用TranslateTransition) 我试着用canvas画画,但我不知道如何不断更新画布,比如

  • 问题内容: 我从一个教程中获取了以下代码: 将被突出显示,并显示两个错误: 容器类型中的方法add(Component)不适用于参数(JLabel) 无法解析类型javax.swing.JComponent。从所需的.class文件间接引用它 作为Java的新手,我不太了解Eclipse试图告诉我什么。我该怎么做才能使其正常工作? 编辑:代码运行时没有一行,因此问题不在于找不到JFrame或JLa

  • 当我尝试使用Xcode将我的应用程序提交到商店时,我一直遇到这个错误: 错误ITMS-90475:“包无效。iPad多任务支持需要在包'com.companyname.appname'中启动情节提要。” 有人知道这个错误的真正含义吗?

  • 问题内容: 我正在寻找一个高效的Swing Java组件,可以将其插入应用程序UI。我已经尝试使用Swing中的类,例如JTextArea,但是没有用;它们根本不够高性能,并且具有任何严重的缺点。此外,如果它具有标准的控制台功能,如滚动锁定,清晰的控制台,颜色等,那就太好了。 编辑:忘了说了,这个控制台将有很多调试信息流入其中,并且它需要完全可滚动。 克里斯,干杯 问题答案: 我看不到使用JTex