【问题标题】:JPanel.getBounds() unexpected returns 0JPanel.getBounds() 意外返回 0
【发布时间】:2015-02-21 21:24:36
【问题描述】:

我有一个从 JFrame 扩展而来的类。 在它的构造函数中,我生成了一个 JPanel:

    JPanel contentPane = new JPanel();
    contentPane.setBackground(Color.BLACK);
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);
    JOptionPane.showMessageDialog(contentPane, contentPane.getBounds());

我认为使用 setContentPane,我会填满 JFrame 中的整个可用空间。所以它会自动设置 JPanel 的边界。

我需要获取 JPanel 的边界,但 getBounds() 返回 x = 0, y = 0, width = 0, height = 0。 JPanel 的其他与大小相关的方法(如 getWidth() 等)也返回 0。如果我显式地设置 JPanel 的 setBounds(),这些方法将返回我给定的值。

有趣的是,setBackground 填充了我的 JFrame 中的整个可用空间。因此,我的 JPanel 的大小必须与我的 JFrame 的大小完全相同。但似乎并非如此。

也许这个问题是由布局管理器引起的,就像大多数与容器相关的问题一样。但是使用布局管理器,我也得到 0。

我认为这是一个非常愚蠢的问题,可以轻松解决,但我无法弄清楚问题所在。 我没有在网上找到这个问题的答案,所以希望没有复制一些帖子。

【问题讨论】:

    标签: java swing jpanel size


    【解决方案1】:

    有趣的是,setBackground 填充了我的 JFrame 中的整个可用空间。因此,我的 JPanel 的大小必须与我的 JFrame 的大小完全相同。但似乎并非如此。

    实际上不,内容窗格会比框架小,因为它包含在框架装饰中。这意味着可视空间是窗口的大小 - 装饰的大小。

    此外,组件在其大小超过 0x0 之前不会被绘制

    contentPane 知道它有多大之前,它需要被它的父容器布局。为了让父容器布局子容器,它需要知道它们可能想要的大小。

    正如你所说,这与布局管理器有关,为了让容器知道它可以有多大,它需要知道它的父容器会给它多少空间。

    可能这个问题是由布局管理器引起的,就像大多数与容器相关的问题一样。但是使用布局管理器,我也得到 0。

    容器,即使在布局管理器的管理下,也不会被分配大小,直到父容器的大小适当。

    虽然有几种方法可以克服这个问题,但问题是为什么?您将 contentPane 的布局管理器设置为 null 的事实令人担忧,这表明您现在需要重新发明轮子并替换布局管理器为您所做的工作。

    我建议在您尝试获取组件大小之前调用pack,但是,再次,因为您已经否定了布局管理器,这不会导致您满意的值...

    【讨论】:

      【解决方案2】:

      大概是因为这是在您的主frames 构造函数中,当您调用JOptionPane.showMessageDialog 时,您没有在主框架(顶层窗口)上调用setVisible(true)

      如果是,那么 GUI 组件还没有被渲染,所以它们的边界是 [0, 0]。如果您将JOptionPane.showMessageDialog 移动到setVisible 之后,您将获得一个维度。

      或者,您也可以致电pack 进行安排。根据我在下面的评论,您可以在执行此操作之前致电 contentPane.setPreferredSize(new Dimension(width, height));

      【讨论】:

      • 是的,你是对的。但是我不能在 setVisible 之后调用它,因为现在为时已晚。所以 pack() 听起来不错,但如果我调用它,它会将我的框架设置为首选大小,而不是我预设的大小。如何处理?
      • @veritas。这在很大程度上取决于您的最终目标是什么,以及您的面板将包含什么,但一种方法是在顶层窗口上调用 frame.pack() 之前运行 contentPane.setPreferredSize(new Dimension(width, height));
      • @那就不用担心了。使用JPanel 中的getPreferredSize 返回所需可视区域的大小。使用JFrame#setResiazableJFrame#pack 确保窗口的大小可以满足内容窗格的需要。当调用paintComponent 时,使用getWidthgetHeight 来确定面板的当前大小。如果您想在调用paint 之前知道尺寸,也可以使用ComponentListener
      • @veritas。这正是我之前建议的。如果它可以满足您的需求,那么它对于您的用例来说是完美的。无论您是在顶层窗口(框架)还是面板上调用setPreferredSize,都取决于您希望如何计算尺寸的数学。
      • @veritas 请记住两件事,1- 您无法控制绘制过程,因此所有绘制都需要在绘制组件的上下文中完成; 2- Swing 不是线程安全的,请确保绘制方法可能依赖的任何内容都是同步的,这样您就不会得到脏绘制。根据您的需要,您在调整大小的事件之后。您还可以延迟启动线程,直到显示和调整大小的事件发生...setPreferredSize 也可能产生不良副作用,请小心它...
      猜你喜欢
      • 2020-12-07
      • 1970-01-01
      • 2017-04-03
      • 2015-08-18
      • 1970-01-01
      • 2020-04-21
      • 2020-12-08
      • 2018-03-24
      • 1970-01-01
      相关资源
      最近更新 更多