Java 教程是针对 JDK 8 编写的。本页面中描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
请参阅 Java 语言变更,了解 Java SE 9 及后续版本中更新的语言功能的概述。
请参阅 JDK 发行说明,了解有关所有 JDK 发行版的新功能、增强功能以及已删除或已弃用选项的信息。
一般来说,您不直接创建JRootPane
对象。相反,当您实例化JInternalFrame
或其中一个顶级Swing容器(例如JApplet
、JDialog
和JFrame
)时,您会获得一个JRootPane
对象(不管您是否需要)。
使用顶级容器介绍了使用根面板的基础知识,包括获取内容面板、设置其布局管理器以及向其添加Swing组件。本节将更详细地介绍根面板,包括组成根面板的组件以及您如何使用它们。
如上图所示,根面板由四个部分组成:
paintComponent
方法,使其执行某些操作,并且它可以拦截根面板的输入事件。在下一节中,您将看到使用玻璃面板的示例。
setJMenuBar
方法将菜单栏放置在适当的位置。有关使用菜单和菜单栏的更多信息,请参见如何使用菜单。
当您希望能够捕获事件或在已包含一个或多个组件的区域上进行绘制时,玻璃面板很有用。例如,您可以通过使玻璃面板拦截事件来禁用多组件区域的鼠标事件。或者,您可以使用玻璃面板在多个组件上显示图像。
下面是一个演示玻璃面板功能的应用程序的图片。它包含一个复选框,可以设置玻璃面板是否“可见” - 是否可以接收事件并在屏幕上绘制自己。当玻璃面板可见时,它会阻止所有输入事件传递到内容面板中的组件。它还会在最后检测到鼠标按下事件的位置绘制一个红点。
以下代码来自GlassPaneDemo.java
,它显示和隐藏玻璃板。此程序创建自己的玻璃板。但是,如果玻璃板不进行任何绘制,程序可以简单地将侦听器附加到默认玻璃板,即通过getGlassPane
返回的玻璃板。
myGlassPane = new MyGlassPane(...); changeButton.addItemListener(myGlassPane); frame.setGlassPane(myGlassPane); ... class MyGlassPane extends JComponent implements ItemListener { ... //响应更改按钮点击事件。 public void itemStateChanged(ItemEvent e) { setVisible(e.getStateChange() == ItemEvent.SELECTED); } ... }
下一个代码片段实现了玻璃板的鼠标事件处理。如果鼠标事件发生在复选框上方,玻璃板会重新分发该事件,以便复选框接收到它。
... //在玻璃板的鼠标监听器的实现中: public void mouseMoved(MouseEvent e) { redispatchMouseEvent(e, false); } ... /* mouseDragged, mouseClicked, mouseEntered, * mouseExited和mousePressed方法的实现与mouseMoved相同。 */... public void mouseReleased(MouseEvent e) { redispatchMouseEvent(e, true); } private void redispatchMouseEvent(MouseEvent e, boolean repaint) { Point glassPanePoint = e.getPoint(); Container container = contentPane; Point containerPoint = SwingUtilities.convertPoint( glassPane, glassPanePoint, contentPane); if (containerPoint.y < 0) { //不在内容窗格中 //可能有特殊代码来处理菜单栏或非系统窗口装饰上的鼠标事件, //例如Java外观提供的装饰。 } else { //鼠标事件可能发生在内容窗格上。 //确定准确位于哪个组件上。 Component component = SwingUtilities.getDeepestComponentAt( container, containerPoint.x, containerPoint.y); if ((component != null) && (component.equals(liveButton))) { //将事件转发到复选框上。 Point componentPoint = SwingUtilities.convertPoint( glassPane, glassPanePoint, component); component.dispatchEvent(new MouseEvent(component, e.getID(), e.getWhen(), e.getModifiers(), componentPoint.x, componentPoint.y, e.getClickCount(), e.isPopupTrigger())); } } //如果需要,更新玻璃板。 if (repaint) { glassPane.setPoint(glassPanePoint); glassPane.repaint(); } }
这是MyGlassPane
中实现绘制的代码。
protected void paintComponent(Graphics g) { if (point != null) { g.setColor(Color.red); g.fillOval(point.x - 10, point.y - 10, 20, 20); } }
分层窗格是一个带有深度的容器,使得重叠的组件可以相互覆盖。有关分层窗格的一般信息在如何使用分层窗格中。本节讨论了根窗格如何使用分层窗格的细节。
每个根窗格都将菜单栏和内容窗格放在JLayeredPane
的实例中。层次结构提供的Z排序功能使得可以在其他组件上方显示弹出菜单等行为。
您可以选择将组件放在根窗格的层次结构中。如果这样做,您应该注意某些深度被定义为用于特定功能,并且应按照预期使用这些深度。否则,您的组件可能无法与其他组件协同工作。下面是一个显示功能层次结构及其关系的图表:
下表描述了每个层次结构的预期用途,并列出与每个层次结构对应的JLayeredPane
常量:
层次名称 | 值 | 描述 |
---|---|---|
FRAME_CONTENT_LAYER |
new Integer(-30000) |
根窗格将菜单栏和内容窗格添加到此深度的层次结构中。 |
DEFAULT_LAYER |
new Integer(0) |
如果在将组件添加到层次结构时未指定其深度,层次结构会将其放在此深度。 |
PALETTE_LAYER |
new Integer(100) |
此层次结构适用于浮动工具栏和调色板。 |
MODAL_LAYER |
new Integer(200) |
模态内部框对话框属于此层次结构。 |
POPUP_LAYER |
new Integer(300) |
弹出窗口位于此层次结构中,因为它们需要出现在几乎所有组件之上。 |
DRAG_LAYER |
new Integer(400) |
在拖动组件时使用的层次结构。组件在放下时应返回其常规层次。 |
这是RootLayeredPaneDemo的图片,它是LayeredPaneDemo的一个版本,使用了根窗格的层次结构,而不是创建一个新的层次结构。
下表列出了使用根窗格、玻璃窗格和内容窗格的 API。有关使用内容窗格的更多信息,请参阅使用顶层容器。本节中的表格如下:
其他根窗格部分的 API 在其他地方描述:
方法 | 目的 |
---|---|
JRootPane getRootPane() (在 JApplet , JDialog , JFrame , JInternalFrame 和 JWindow 中) |
获取 applet、dialog、frame、internal frame 或 window 的根窗格。 |
static JRootPane getRootPane(Component) (在 SwingUtilities 中) |
如果组件包含根窗格,则返回该根窗格。否则,返回包含该组件的根窗格(如果有)。 |
JRootPane getRootPane() (在 JComponent 中) |
调用 JComponent 的 SwingUtilities getRootPane 方法。 |
void setDefaultButton(JButton) JButton getDefaultButton() |
设置或获取根窗格中的默认按钮(如果有)。外观相关的操作,如按下 Enter 键,会执行按钮的动作。 |
方法 | 目的 |
---|---|
void setGlassPane(Component) Component getGlassPane() |
设置或获取玻璃窗格。 |
void setLayeredPane(JLayeredPane) Container getLayeredPane() |
设置或获取分层窗格。 |
void setContentPane(Container) Container getContentPane() |
设置或获取内容窗格。 |
void setJMenuBar(JMenuBar) JMenuBar getJMenuBar() (在 JWindow 中未定义) |
设置或获取菜单栏。 |
每个Swing程序都有一个根窗格,但很少直接引用它。下面的示例演示了如何使用JRootPane
或玻璃窗格的特性。还可以参考以下列表:
示例 | 所述位置 | 注释 |
---|---|---|
GlassPaneDemo |
本节 | 使用绘制和重新分派事件的玻璃窗格。 |
RootLayeredPaneDemo |
本节 | 将LayeredPaneDemo适配为使用根窗格的分层窗格。 |
ListDialog |
如何使用列表 | 设置JDialog 的默认按钮。 |
FrameDemo2 |
如何制作窗体 | 设置JFrame 的默认按钮。 |