JPanel内容面板混淆问题

5
我正在学习Java Swing并将一个menuBar添加到frame中。默认情况下应该调用jframe.getContentPane().add(child)。运行脚本后,没有看到menubar的出现。但是按钮位于顶部“y = 0”,如果理解的话。

后来我意识到我的错误,实际上必须在menubar中插入menu。然后menubar出现了。这让我想到...... "menubar" "contentpane"实际上是2个面板吗?这让我非常困惑。因为它的行为很像一个面板。但是getContentPane()返回的是Container而不是JPanel对象,所以我很困惑。

如果是这样,那么直接放置在框架中的唯一东西就是Jpanel对象吗?因此,JButtons、JLabels不是直接放在框架中的......

这是否意味着jpanels是“嵌套”的?还有一件事让我感到困惑。如果jpanel可以控制位置,那么LayoutManager是做什么用的?谢谢,请像回答一个两岁小孩问天空为什么是蓝色一样简单易懂哈 ;)


看起来JPanel继承了Container。http://download.oracle.com/javase/6/docs/api/javax/swing/JPanel.html - Bhesh Gurung
如果一个JPanel可以控制事物的位置,那么LayoutManager的作用是什么呢?实际上,JPanel无法直接控制事物的位置,这正是LayoutManager所做的工作。 - Nate W.
我猜这更多是关于事物如何显示或组织,而不是屏幕上组件的位置。 - Lews Therin
1
请参阅JRootPane,这是用于JFrame等轻量级容器的。 - trashgod
@trashgod回答了我的一部分问题。啊,看来JRootPane充当了JFrame不是的JComponent的角色......我仍然不知道为什么它单独实现了setJMenuBar,我相信有一个原因..该死。 - Lews Therin
1
点击此处进入如何使用根面板教程。 - trashgod
4个回答

10

一些随机想法:

  • 是的,JPanels和其他组件经常是"嵌套"的。这就需要对Swing/AWT布局管理器有深刻的理解。
  • 虽然JFrame的getContentPane()返回的类型从技术上讲是Container,但它也是一个JPanel(最终继承自Container)。
  • 我认为你可以将任何派生自Container的东西作为contentPane,但你需要确保它是不透明的。

2
开始时有一个JPanel。如果你添加了一个JMenuBar,那么就会有同样的JPanel和一个JMenuBar,而不是两个JPanels。我不明白你最后一个问题的意思——为什么布局管理器不同。 - Hovercraft Full Of Eels
@Hovercraft Full Of Eels(不确定)也许是CardLayout? - mKorbel
1
一个JPanel和一个布局管理器是两个完全不同的东西。JPanel和任何从Component派生出来的组件都使用布局管理器。JPanel是在GUI中显示的组件,而布局是容器(包括JPanel)排列它们所持有的组件的方式。因此,如果您的JPanel持有其他组件,最好熟悉它使用的布局管理器以及该布局管理器的工作原理。 - Hovercraft Full Of Eels
@Lews Therin,您能否将您的问题拆分到不同的区域中,请勿跳跃... - mKorbel
@mKorbel 当然,我会的。我还是不太理解LayoutManagers,所以也许可以学一下。 - Lews Therin
显示剩余2条评论

3

因为有方法

frame.setJMenuBar(menuBar);

对于今天的Java Swing GUI,不必声明 ContentPane ,从Java5开始,默认使用BorderLayout作为LayoutManager

然后frame.add(myPanel); //与frame.add(myPanel,BorderLayout.CENTER)相同,并占用整个容器

如何使用LayourManagers的基本知识


我可能更快,但这个答案比我的更好。1+1 - Hovercraft Full Of Eels

1

getContentPane() 总是返回一个 Container 实例。但是,您应该注意到 JPanel 对象也是 Container 实例,以及 Swing 框架中的其他类。返回实例的实际类是无关紧要的,因为您无法控制使用哪个 Container 的实现作为 contentPane(除非您已经强制指定了特定的 contentPane),大多数情况下这不应该是问题。

您可以在 JFrame 中添加许多 GUI 小部件,例如 JButtonJLabel 等。但是,它们将自动添加到相关联的 contentPane 中。

JPanel 不处理对象的定位,与面板关联的 LayoutManager 处理;自动基于其自己的一组规则(例如 FlowLayout)或使用您在将对象添加到容器时指定的约束(GridBagLayout 布局管理器是一个很好的例子)。有关 LayoutManagers 的 JavaDoc 通常包含足够的信息,可帮助您开始使用它们。

你可以使用嵌套的面板。一个Container可以包含其他Container实例。虽然这似乎是一个复杂的解决方案,但它确实让你能够精确控制GUI的显示方式。根据你使用的LayoutManager、用户界面需要满足的需求以及作为开发者自己的喜好/习惯,你可能需要更少或更多的嵌套面板。

困惑了...我们什么时候应该使用setcontentpane和getContentPane()?它们是指JFrame中的字段还是其他什么东西? - Lews Therin
setContentPane() 很少被使用,至少我从未使用过。每当您想要添加GUI小部件到 JFrame 时,应该使用 getContentPane()。它们确切地指的是什么是实现细节,不应影响您的工作。重要的是要记住,调用 getContentPane() 将使您获得用于显示您的UI的 Container - Laf
我在查看API,发现setContentPane返回对getContentPane引用的同一对象,至少我是这么认为的。但是我还有一个问题不太明白...我不太喜欢在这么短的时间内创建线程,所以我可以在这里问吗? 为什么我必须调用setJMenuBar来显示一个框架呢?没有哪个网站能回答这个问题。还有,什么意思是一个JFrame有很多层次?这让人感到困惑。 - Lews Therin
1
@LewsTherin javadoc中的setContentPane()方法提到返回类型为void,因此不会返回对内容面板的引用(链接)。而且你必须调用setMenuBar()方法,因为JFrame处理菜单栏的显示,所以你不必担心它。Java教程包含了一个关于顶级容器(如JFrame)的好文章(链接)。 - Laf
我是指getContentPane()和setContentPane(),我写反了:(好发现:P 感谢提供链接。 - Lews Therin

0

你需要查看这个API文档来了解JComponent

如果你查看继承层次结构,你会发现JComponent扩展了Component,所以JComponent是一个Component。

此外,在直接已知的子类下,你可以看到所有扩展JComponent的类的列表,包括JMenuBarJPanel

因此,JMenuBarJPanelJComponent(或Container)的两个更专业化的版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接