如何使用根窗格

通常,您不会直接创建JRootPane对象。而是实例化JInternalFrame或顶级 Swing 容器之一(例如JAppletJDialogJFrame)时,会得到JRootPane(无论是否想要!)。

使用顶层容器告诉您使用根窗格的基本知识—获取内容窗格,设置其布局 管理 器以及向其中添加 Swing 组件。本节介绍有关根窗格的更多信息,包括组成根窗格的组件以及如何使用它们。

如上图所示,根窗格包含四个部分:

玻璃窗格

当您希望能够catch事件或在已经包含一个或多个组件的区域上绘画时,玻璃窗格很有用。例如,您可以通过使玻璃窗格拦截事件来禁用多组件区域的鼠标事件。或者,您可以使用玻璃窗格在多个组件上显示图像。

这是演示玻璃窗格功能的应用程序的图片。它包含一个复选框,可让您设置玻璃窗格是否“可见”-它是否可以获取事件并在屏幕上进行绘制。当玻璃窗格可见时,它将阻止所有 Importing 事件到达内容窗格中的组件。它还在上次检测到鼠标按下事件的位置绘制了一个红点。

Try this:

  • 单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 GlassPaneDemo。另外,要自己编译和运行示例,请查阅example index

  • 点击按钮 1.
    该按钮的外观更改为显示已被单击。

  • 单击复选框,使玻璃窗格变为“可见”,然后再次单击按钮 1.
    由于玻璃窗格会拦截所有鼠标事件,因此无法单击该按钮。玻璃窗格在释放鼠标的位置绘制了一个红色的圆圈。

  • 再次单击复选框,以隐藏玻璃窗格。
    当玻璃窗格在复选框上检测到事件时,会将其转发到复选框。否则,该复选框将不响应点击。

GlassPaneDemo.java中的以下代码显示和隐藏玻璃窗格。该程序恰好创建自己的玻璃窗格。但是,如果玻璃窗格不做任何绘画,则该程序可能只是将侦听器附加到默认玻璃窗格,如getGlassPane返回。

myGlassPane = new MyGlassPane(...);
changeButton.addItemListener(myGlassPane);
frame.setGlassPane(myGlassPane);
...
class MyGlassPane extends JComponent
                  implements ItemListener {
    ...
    //React to change button clicks.
    public void itemStateChanged(ItemEvent e) {
        setVisible(e.getStateChange() == ItemEvent.SELECTED);
    }
...
}

下一个代码段实现了玻璃窗格的鼠标事件处理。如果在复选框上发生鼠标事件,则玻璃窗格将重新分发该事件,以便复选框接收该事件。

...//In the implementation of the glass pane's mouse listener:
public void mouseMoved(MouseEvent e) {
    redispatchMouseEvent(e, false);
}

.../* The mouseDragged, mouseClicked, mouseEntered,
    * mouseExited, and mousePressed methods have the same
    * implementation as 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) { //we're not in the content pane
        //Could have special code to handle mouse events over
        //the menu bar or non-system window decorations, such as
        //the ones provided by the Java look and feel.
    } else {
        //The mouse event is probably over the content pane.
        //Find out exactly which component it's over.
        Component component =
            SwingUtilities.getDeepestComponentAt(
                                    container,
                                    containerPoint.x,
                                    containerPoint.y);

        if ((component != null)
            && (component.equals(liveButton))) {
            //Forward events over the check box.
            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()));
        }
    }

    //Update the glass pane if requested.
    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常量:

Layer Name Value Description
FRAME_CONTENT_LAYER new Integer(-30000) 根窗格在此深度将菜单栏和内容窗格添加到其分层窗格中。
DEFAULT_LAYER new Integer(0) 如果在将组件添加到分层窗格中时未指定组件的深度,则分层窗格会将其置于该深度。
PALETTE_LAYER new Integer(100) 该层对于 Float 工具栏和调色板很有用。
MODAL_LAYER new Integer(200) 模态内部框架对话框将属于此层。
POPUP_LAYER new Integer(300) 弹出窗口位于此层,因为它们需要出现在几乎所有内容的上方。
DRAG_LAYER new Integer(400) 旨在在拖动组件时使用。组件在放下后应返回其常规层。

这是 RootLayeredPaneDemo 的图片,该图片是 LayeredPaneDemo使用根窗格的分层窗格,而不是创建新的分层窗格。

Try this:

  • 单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 RootLayeredPaneDemo。另外,要自己编译和运行示例,请查阅example index

  • 在窗口中四处移动光标,以便 Duke 在其他组件的顶部移动。
    请注意,当光标位于非标签组件的顶部时(无论是在内容窗格中还是在 Java 外观提供的标题栏中),Duke 的移动都将暂时停止。这是因为鼠标移动事件进入包含层次结构中最深的组件,并且对鼠标事件感兴趣。移动 Duke 的鼠标移动侦听器已注册在分层窗格中,并且该窗格中的大多数组件(标签除外)都具有鼠标移动侦听器。当鼠标移到分层窗格中的某个感兴趣的组件上时,分层窗格不会获取事件,而感兴趣的组件则会catch该事件。

  • 确保选中“在图层中的最高位置”复选框,然后将 Duke 的图层更改为“黄色”(-30000)。
    和以前一样,他出现在其他组件的顶部,洋红色(0)和青色(301)矩形除外。

  • 将 Duke 保留在 Yellow 层中,单击复选框以将 Duke 发送到-30000 层的背面。
    Duke 之所以消失,是因为内容窗格及其中的所有组件现在都在他上方。

  • 将 Duke 的图层更改为 Cyan(301),向下移动 Duke 一点,以便他站在 Yellow 矩形的顶部边缘,然后按 Space 弹出组合框的下拉列表。
    如果外观将下拉列表实现为轻量级弹出窗口,则 Duke 会出现在下拉列表的顶部。

根窗格 API

后面的表列出了用于使用根窗格,玻璃窗格和内容窗格的 API。有关使用内容窗格的更多信息,请转到使用顶层容器。以下是本节中的表格:

其他地方介绍了使用根窗格其他部分的 API:

使用根窗格

Method Purpose
JRootPane getRootPane()

(在JAppletJDialogJFrameJInternalFrameJWindow中)
获取 Servlets,对话框,框架,内部框架或窗口的根窗格。
静态 JRootPane getRootPane(Component)
(在SwingUtilities中)
如果组件包含一个根窗格,请返回该根窗格。否则,返回包含组件的根窗格(如果有)。
JRootPane getRootPane()
(在JComponent中)
JComponent调用SwingUtilities getRootPane方法。
void setDefaultButton(JButton)
JButton getDefaultButton()
设置或获取哪个按钮(如果有)是根窗格中的默认按钮。特定于外观的操作(例如按 Enter)将导致执行按钮的操作。

设置或获取根窗格的内容
除非另有说明,否则以下方法在JAppletJDialogJFrameJInternalFrameJRootPaneJWindow中定义.

Method Purpose
void setGlassPane(Component)

Component getGlassPane()
设置或获取玻璃窗格。
void setLayeredPane(JLayeredPane)
Container getLayeredPane()
设置或获取分层窗格。
void setContentPane(Container)
Container getContentPane()
设置或获取内容窗格。
void setJMenuBar(JMenuBar)
JMenuBar getJMenuBar()
(未在JWindow中定义)
设置或获取菜单栏。

使用根窗格的示例

每个 Swing 程序都有一个根窗格,但是很少有直接引用它。下表中的示例说明了如何使用JRootPane或玻璃窗格的功能。另请参阅以下列表:

Example Where Described Notes
GlassPaneDemo This section 使用绘制一点并重新分发事件的玻璃窗格。
RootLayeredPaneDemo This section 调整 LayeredPaneDemo 以使用根窗格的分层窗格。
ListDialog 如何使用清单 设置JDialog的默认按钮。
FrameDemo2 如何制作框架 设置JFrame的默认按钮。
首页