ContentPane 和 JPanel 有啥关系?
Posted
技术标签:
【中文标题】ContentPane 和 JPanel 有啥关系?【英文标题】:What is the relation between ContentPane and JPanel?ContentPane 和 JPanel 有什么关系? 【发布时间】:2011-01-26 19:58:07 【问题描述】:我发现了一个示例,其中按钮被添加到面板(JPanel
的实例),然后面板被添加到容器(由getContentPane()
生成的实例),然后容器通过构造包含到 @ 987654323@(窗户)。
我尝试了两件事:
我摆脱了容器。更详细地说,我将按钮添加到面板(JPanel
的实例),然后将面板添加到窗口(@987654325@ 的实例)。效果很好。
我摆脱了面板。更详细地说,我直接将按钮添加到容器中,然后将容器添加到窗口中(JFrame
的实例)。
所以,我不明白两件事。
为什么我们有两种竞争机制来做同样的事情?
将容器与面板结合使用的原因是什么 (JPanel
)? (例如,我们在 JPanel 中包含按钮,然后在容器中包含 JPanel)。我们可以在JPanel
中包含JPanel
吗?我们可以在容器中包含一个容器吗?
添加:
也许我的问题的本质可以放在一行代码中:
frame.getContentPane().add(panel);
我们在两者之间放置getContentPane()
是为了什么?我只试过frame.add(panel);
,效果很好。
添加 2:
我想添加一些代码来更清楚我的意思。在这个例子中,我只使用了 JPane:
import java.awt.*;
import javax.swing.*;
public class HelloWorldSwing
public static void main(String[] args)
JFrame frame = new JFrame("HelloWorldSwing");
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(new JButton("W"), BorderLayout.NORTH);
panel.add(new JButton("E"), BorderLayout.SOUTH);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
在这个例子中,我只使用了内容窗格:
import java.awt.*;
import javax.swing.*;
public class HelloWorldSwing
public static void main(String[] args)
JFrame frame = new JFrame("HelloWorldSwing");
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(new JButton("W"), BorderLayout.NORTH);
pane.add(new JButton("E"), BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
两者都工作正常!我只是想知道这两种做事方式之间是否有一种更好(更安全)。
【问题讨论】:
【参考方案1】:这不是两个相互竞争的机制 - JPanel
是 Container
(只需查看JPanel javadocs 顶部的类层次结构)。 JFrame.getContentPane()
只返回一个Container
以将您要显示的Component
s 放置在JFrame
中。在内部,它使用JPanel
(默认情况下-您可以通过调用setContentPane()
来更改它)至于为什么它返回Container
而不是JPanel
-这是因为您应该program to an interface, not an implementation-在那个级别,您需要关心的只是您可以将Component
s 添加到某个东西上——即使Container
是一个类而不是一个接口——它也提供了执行此操作所需的接口。
至于为什么JFrame.add()
和JFrame.getContentPane().add()
都做同样的事情——JFrame.add()
被覆盖以调用JFrame.getContentPane().add()
。情况并非总是如此 - 在 JDK 1.5 之前,您总是必须明确指定 JFrame.getContentPane().add()
,如果您调用它,JFrame.add()
会抛出 RuntimeException
,但是由于许多投诉,这在 JDK 1.5 中进行了更改以执行什么操作你会期待的。
【讨论】:
@Nate,“在内部,它使用 JPanel”是什么意思。您的意思是 Container 正在使用 JPanel?你是什么意思?我认为 JPanel 是 Container 的子类。我可以通过“setContentPane”改变什么?好的。你说 Container 是一个类(我一直认为 Container 是一个类)。但是JPane也是一个类。为什么我们不能只使用 JPane 或只使用 Container?我只使用 JPane 就能做同样的事情。我也可以只使用容器来做同样的事情。JFrame
在内部使用JPanel
对象来支持getContentPane()
方法。这就是 Zachary 的回答有效的原因。实际的JPanel
引用隐藏在JFrame.rootPane
字段中。您可以在JFrame
上调用setContentPane()
- 例如,您可以将第一个示例中的第10 行从frame.add(panel)
更改为frame.setContentPane(panel)
。 Container
是一个类。 JPanel
是一个类(它是Container
的子类)。您将引用的类型与引用引用的对象的类型混淆了。想想Container container = new JPanel()
@Nate 源 (pragmaticjava.blogspot.com.ar/2008/08/…) 已被删除。
@Lucio 谢谢!将链接更改为 *** 上关于同一件事的问题。【参考方案2】:
this leepoint article 也详细讨论了这方面的历史和机制。特别注意:
getContentPane()
返回一个Container
对象。这实际上不是一个普通的Container
对象,但实际上是一个JPanel
!这是一个Container
作为层次结构的结果。所以如果我们得到预定义的内容窗格,它实际上是一个JPanel
,但我们真的无法利用JComponent
添加的功能。
和
他们在
JFrame
中定义了add()
方法,这些方法只是为内容窗格调用相应的add()
方法。现在添加此功能似乎很奇怪,特别是因为许多布局使用多个嵌套面板,因此您仍然必须对直接添加到JPanel
感到满意。并非您想要对内容窗格执行的所有操作都可以通过调用JFrame
来完成。
【讨论】:
【参考方案3】:有趣:jframe.setBackground(color)
对我不起作用,但 jframe.getContentPane().setBackground(color)
起作用。
【讨论】:
【参考方案4】:好问题。我发现理解“Swing 提供了三个通常有用的***容器类:JFrame
、JDialog
和 JApplet
.... 为方便起见,add 方法及其变体、remove 和 setLayout 具有被覆盖以根据需要转发到 contentPane。"—Using Top-Level Containers
【讨论】:
【参考方案5】:上个版本API doc写的都是JFrame.add()(现在)就够了。
您可以与较旧的 Java 版本进行比较 here。
【讨论】:
【参考方案6】:我相信原因是因为 Swing 是基于 AWT 构建的,而 Container 是*** AWT 对象。不过,这确实不是最好的设计选择,因为您通常不希望将 AWT(重量级)对象与 Swing(轻量级)混合。
我认为处理它的最佳方法是始终将 contentPane 转换为 JPanel。
JPanel contentPanel = (JPanel)aFrame.getContentPane();
【讨论】:
它没有混合 AWT 和 Swing 组件...看我的回答以上是关于ContentPane 和 JPanel 有啥关系?的主要内容,如果未能解决你的问题,请参考以下文章