Java ContentPane 和 JPanel 之间是什么关系?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2432839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:34:36  来源:igfitidea点击:

What is the relation between ContentPane and JPanel?

javaswinguser-interfacejframejpanel

提问by Roman

I found one example in which buttons are added to panels (instances of JPanel) then panels are added to the the containers (instances generated by getContentPane()) and then containers are, by the construction, included into the JFrame(the windows).

我发现了一个示例,其中将按钮添加到面板(的实例JPanel),然后将面板添加到容器(由 生成的实例getContentPane()),然后通过构造将容器包含到JFrame(窗口)中。

I tried two things:

我尝试了两件事:

  1. I got rid of the containers. In more details, I added buttons to a panel (instance of JPanel) and then I added the panel to the windows (instance of JFrame). It worked fine.

  2. I got rid of the panels. In more details, I added buttons directly to the container and then I added the container to the window (instance of JFrame).

  1. 我摆脱了容器。更详细地说,我将按钮添加到面板(实例JPanel),然后将面板添加到窗口(实例JFrame)。它工作得很好。

  2. 我摆脱了面板。更详细地说,我直接将按钮添加到容器中,然后将容器添加到窗口(实例JFrame)。

So, I do not understand two things.

所以,我不明白两件事。

  1. Why do we have two competing mechanism to do the same things?

  2. What is the reason to use containers in combination with the panels (JPanel)? (For example, what for we include buttons in JPanels and then we include JPanels in the Containers). Can we include JPanelin JPanel? Can we include a container in container?

  1. 为什么我们有两个相互竞争的机制来做同样的事情?

  2. 将容器与面板 ( JPanel)结合使用的原因是什么?(例如,我们在 JPanels 中包含按钮,然后在容器中包含 JPanels)。我们可以包括JPanelJPanel?我们可以在容器中包含一个容器吗?

ADDED:

添加:

Maybe essence of my question can be put into one line of code:

也许我的问题的本质可以放在一行代码中:

frame.getContentPane().add(panel);

What for we put getContentPane()in between? I tried just frame.add(panel);and it works fine.

我们getContentPane()中间放什么?我试过了frame.add(panel);,效果很好。

ADDED 2:

添加 2:

I would like to add some code to be more clear about what I mean. In this example I use only JPane:

我想添加一些代码以更清楚我的意思。在这个例子中,我只使用了 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);
    }
}

And in this example I use only Content Pane:

在这个例子中,我只使用了内容窗格:

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);
    }
}

Both work fine! I just want to know if between these two ways to do things one is better (safer).

两者都工作正常!我只想知道在这两种做事方式之间是否更好(更安全)。

采纳答案by Nate

It's not two competing mechanisms - a JPanelis aContainer(just look at the class hierarchy at the top of the JPanel javadocs). JFrame.getContentPane()just returns a Containerto place the Components that you want to display in the JFrame. Internally, it's using a JPanel(by default - you can change this by calling setContentPane()) As for why it's returning a Containerinstead of a JPanel- it's because you should program to an interface, not an implementation- at that level, all that you need to care about is that you can add Components to something - and even though Containeris a class rather than an interface - it provides the interface needed to do exactly that.

这不是两种相互竞争的机制 - aJPanel是 aContainer(只需查看JPanel javadocs顶部的类层次结构)。 JFrame.getContentPane()只需返回 aContainer即可将Component要显示的s 放入JFrame. 在内部,它使用 a JPanel(默认情况下 - 您可以通过调用来更改它setContentPane())至于为什么它返回 aContainer而不是 a JPanel- 这是因为您应该对接口进行编程,而不是实现- 在那个级别,所有您需要关心的是你可以将Components添加到某物上——即使Container是一个类而不是一个接口——它提供了完全做到这一点所需的接口。

As for why both JFrame.add()and JFrame.getContentPane().add()both do the same thing - JFrame.add()is overridden to call JFrame.getContentPane().add(). This wasn't always the case - pre-JDK 1.5 you always had to specify JFrame.getContentPane().add()explicitly and JFrame.add()threw a RuntimeExceptionif you called it, but due to many complaints, this was changed in JDK 1.5 to do what you'd expect.

至于为什么都JFrame.add()JFrame.getContentPane().add()都做同样的事情-JFrame.add()被覆盖到的呼叫JFrame.getContentPane().add()。情况并非总是如此 - 在 JDK 1.5 之前,您总是必须JFrame.getContentPane().add()明确指定并JFrame.add()RuntimeException调用它时抛出 a ,但是由于许多抱怨,这在 JDK 1.5 中进行了更改以实现您的期望。

回答by Zachary Wright

I believe the reason is because Swing was built off of AWT, and Container is a top level AWT object. It really isn't the greatest design choice, though, since you generally don't want to mix AWT (heavyweight) objects with Swing (lightweight).

我相信原因是因为 Swing 是基于 AWT 构建的,而 Container 是顶级 AWT 对象。不过,它确实不是最好的设计选择,因为您通常不希望将 AWT(重量级)对象与 Swing(轻量级)混合使用。

I think the best way to handle it is to always cast the contentPane to a JPanel.

我认为处理它的最好方法是始终将 contentPane 转换为 JPanel。

JPanel contentPanel = (JPanel)aFrame.getContentPane();

回答by PeterMmm

It is all written in the last version API docthat JFrame.add() (nowerdays) is enough.

这是所有写在最后的版本API文档是JFrame.add()(nowerdays)就足够了。

You may compare to older Java versions here.

您可以在此处与较旧的 Java 版本进行比较。

回答by trashgod

Good question. I found it helpful to understand that "Swing provides three generally useful top-level container classes: JFrame, JDialog, and JApplet. ... As a convenience, the add method and its variants, remove and setLayout have been overridden to forward to the contentPane as necessary."—Using Top-Level Containers

好问题。我发现理解“Swing 提供了三个通常有用的顶级容器类:JFrame,JDialogJApplet.... 为方便起见,已覆盖 add 方法及其变体 remove 和 setLayout 以根据需要转发到 contentPane 很有帮助.”——使用顶级容器

回答by DanPB

interesting: jframe.setBackground(color)does not work for me, but jframe.getContentPane().setBackground(color)works.

有趣:jframe.setBackground(color)对我不起作用,但jframe.getContentPane().setBackground(color)有效。

回答by Pops

The history and mechanics of this are also discussed in some detail at this leepoint article. Note in particular:

这篇 leepoint 文章也详细讨论了它的历史和机制。特别注意:

getContentPane()returns a Containerobject. This isn't really a plain Containerobject, but is actually a JPanel! This is a Containeras a consequence of the hierarchy. So if we get the predefined content pane, it turns out it's actually a JPanel, but we really can't take advantage of the functionality that was added by JComponent.

getContentPane()返回一个Container对象。这不是一个真正的普通Container对象,但实际上是一个JPanel! 这是Container层次结构的结果。因此,如果我们获得预定义的内容窗格,就会发现它实际上是一个JPanel,但我们确实无法利用JComponent.

and

They defined add()methods in JFramewhich simply call the corresponding add()methods for the content pane. It seems strange to add this feature now, especially since many layouts use multiple nested panels so you still have to be comfortable with adding directly to a JPanel. And not everything you want to do with the content pane can be done through calls to the JFrame.

他们定义了add()方法,在JFrame其中简单地调用add()内容窗格的相应方法。现在添加此功能似乎很奇怪,尤其是因为许多布局使用多个嵌套面板,因此您仍然必须习惯于直接添加到JPanel. 并非您想要对内容窗格执行的所有操作都可以通过调用JFrame.