这个题目起的有点难懂,但也实在想不出更好的题目来。所谓分层Pane结构是指JFrame/JApplet/JDialog等Swing顶层容器
的JRootPane/JLayeredPane/GlassPane/ContentPane结构。所谓Swing组件高级特性其实是指某些组件的特殊
功能的实现,比如弹出菜单、Tooltip、JComboBox的下拉窗口、Drag and Drop实现、Docking
Pallete窗口等等。这些特性同普通组件不同,它们往往需要动态的变化、覆盖其他组件,它们之间存在一定层次关系。那么Swing中是怎么样实现这些
功能呢?
一直以来想写一篇文章来描述这个关键结构,但每次总被自己的语言表达能力所限制。Swing这个精巧结构是我叹服的原因之一。虽然一般的
GUI系统设计原理我都知道,但是细节如此处精细却不是一开始就能清楚的。我在2000年以前曾经写过大量基于AWT
Canvas的自定义组件,当时认为Swing的自定义组件也不过如此,原理不过也是给我一个刷子,我给你画出来。但是上述所说的这些特性,却从来没能实
现过。我想过很多方法,做过很多实验,但终究没有想透这一层。之后某次偶然机会,看到了下面这张著名的图,使我豁然开朗。让我又一次理解了创新需要跳出旧
的思维模式勇气和智慧。
简单来说Swing中这些顶层容器的多Pane结构是实现这些特性的基础。这些Pane实际是一些特殊的JComponent,它们之间存在包含被包含、覆盖被覆盖的树状多层次结构。我重新画了上面这张图,使得其更具体、更直观,更容易理解些:
其实有了这张图,加上图形系统中Z-order的概念,就不难理解并实现上面提到的特性。Z-order概念和图形学中Z深度是一致
的。离观察点近的物体总是会遮挡离观察点远的物体。物体所在法平面离观察点的距离就是所谓Z深度。Swing中通过先画出Z-order远(小)的组件,
再画Z-order近(大)的组件的方法实现组件之间的遮挡关系。每个组件所在平面的都有一个数字描述其位置,这个位置同三维坐标系中的Z轴类似,离观察
者越近,坐标越大:
Swing的顶层容器都包含有一个JRootPane,该JRootPane是一切Swing组件起点。JRootPane中包含了一个
JLayeredPane和一个GlassPane。GlassPane和JLayeredPane都是充满JRootPane的。GlassPane缺
省情况下是不可见的,因此我们看到都是JLayeredPane。GlassPane如果是可见的,它Z-order大于任何其他组件,因此它会覆盖住整
个窗口,使得所有的鼠标事件都被它截获。另外通常可见情况下它是透明的,因此你能仍然看到JLayeredPane上面的一切,但是
JLayeredPane上面的组件都得不到鼠标事件。
GlassPane这个奇怪的组件主要是用来实现Drag &
Drop以及跨组件渲染用的。NetBeans和Eclipse中哪种常见的Docking
Frame的实现就和这种组件相关。这些工程、文件、源代码的窗口其实不过是普通的Swing组件,它们本身并不能实现这种拖拽功能。鼠标在它们上面标题
栏区域按下之后,标题栏组件会检测到这种事件,经过粘连性判断后,如果发现这些鼠标事件目的是拖拽窗口,这种Docking系统就会将拖拽区域(即所谓的
ClientArea)的GlassPane设置为可见,于是下面的一些列拖拽鼠标事件就被这个GlassPane所接管了过去。GlassPane是覆
盖于应用程序ClientArea的透明组件,它处理这些事件时计算出当前鼠标位置所蕴含着的拖拽动作,并根据这些动作画出相应的焦点矩形。
NetBeans的Docking
Framework一个拖拽过程如下图所示.注意GlassPane是背景透明的,所以可以在上面画背景透明的焦点矩形:
JLayeredPane是实现弹出式窗口或类似Pallete浮动窗口的主要组件。如同它的名字一样,它将自己的内部结构也分成许多
亚层。在使用它的add(Component,
Object)方法加入组件时,第二个参数是一个Integer值,这个值决定了加入的层。这个值相当于前面所说的Z-order值。目前主要有下面几个
预定义值:
public final static Integer DEFAULT_LAYER = new Integer(0);
这层加入的缺省层。
public final static Integer PALETTE_LAYER = new Integer(100);
这层是定义Palette窗口的层。那种浮动选项窗口属于这一层。
public final static Integer MODAL_LAYER = new Integer(200);
这层是模态对话框的层。这个模态对话框应该是指JInternalFrame的模态对话框,而不是JDialog。
public final static Integer POPUP_LAYER = new Integer(300);
这层是菜单、下拉框窗口、Tooltip等窗口浮动的层。
public final static Integer DRAG_LAYER = new Integer(400);
这一层是拖拽层,组件可以在这一层被托拽。
public final static Integer FRAME_CONTENT_LAYER = new Integer(-30000);
这一层是ContentPane和MenuBar所在的层。注意它非常小,前面所有层的组件都会覆盖这一层的组件。我们知道ContentPane是所有应用程序组件所在的地方。
JLayeredPane直接包含有ContentPane组件。应用程序如果定了MenuBar,JLayeredPane还包含
MenuBar。注意JLayeredPane本身没有布局管理器,它对组件的布局是由它的父容器JRootPane的布局管理器RootLayout来
完成的。简单来说,所在层数值小的组件有可能被高层组件所覆盖。Swing将不同类型的组件放置在不同层面上,就实现了文章一开始提到的特性:菜单、浮动
窗口、下拉框窗口和Tooltip等。当然这些窗口有可能不是JLayeredPane上的轻量级Swing组件,当它们的边界超过顶层容器的窗口时,这
些窗口的就变成了重量级AWT窗口。这在上一篇文章《
如何混排Swing和AWT组件
》
中已经提到过。
下面是这些Pane组件之间的树状包含关系图:
本文的目的是讲述Swing的这种组件层次结构,并不是讲述如何使用JLayeredPane和GlassPane来实现某中特殊的功
能。如果需要学习如何使用它们实现某些特殊效果,Java Tutorial的Swing部分提供了详尽的编程资料。Java
Tutorial的Swing部分编程在:
如何使用RootPane、GlassPane和JLayeredPane分别见下面的章节:
分享到:
相关推荐
分层介绍java Swing组件,详细说明rootPane,LayeredPane,rootPane,contentPane之间的关系
react-split-pane - React拆分面板组件
import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; ...
React Split Pane Split-Pane React组件,可以垂直或水平嵌套或拆分! 安装npm install react-split-pane#,或者如果您使用纱线,则添加react-split-pane ##示例用法```j React Split Pane Split-Pane React组件,...
Vue拆分器窗格演示vue-splitter-pane是Vuejs组件,它以可调节的拆分方式(垂直或水平)呈现两个插槽。 使用Vue拆分器窗格演示vue-splitter-pane是Vuejs组件,它以可调节的拆分方式(垂直或水平)呈现两个插槽。 使用...
NavigationPane使用实例 详细介绍了NavigationPane控件使用
从网上一个博文上搜集来的一些Swing特效的例子,如xp折叠效果_foldered_pane,鼠标悬停提示_tooltip,玻璃效果闪烁_glassbox,日历组件,环形右键弹出菜单等等.....绝对物超所值! 其中部分例子为jar形式,可直接运行......
面板分割组件(Vue) npm i npm start 具体详情
Split-Pane React组件,可以垂直或水平嵌套或拆分! 正在安装 npm install react-split-pane # or if you use yarn yarn add react-split-pane # # Example Usage ` ` ` jsx < /SplitPane > < ...
前端开源库-source-pane源窗格,实体兼容窗格:源编辑器
一、重要部分 1、 注意 <component is=item.content></component> :表明模板 (item) key=item.name label=item.title name=item.name > <component is=item.content></component> 2、content: ‘Jbxx’ ,...
前端开源库-contacts-pane联系人窗格,实体窗格:通讯簿、组和个人的联系人管理器。
前端开源库-folder-pane文件夹窗格,实体兼容窗格:文件浏览器
解决Vue对Element中的el-tab-pane添加@click事件无效
还可以轻松实现可停靠可拖动的工具栏、状态栏、toolbox、shortcutbar和pane等。 换肤组件 1. 支持所有PB控件的换肤 2. 使用简单一行代码即可实现换肤 3. 支持直接加载windows皮肤,网络上的皮肤资源可以任你所用。 ...
前端开源库-meeting-pane会议窗格,实体兼容窗格:会议协作工具
标签页组件,即实现选项卡切换,常用于平级内容的收纳与展示。 因为每个标签页的内容是由使用组件的父级控制的,即这部分内容为一个 slot。所以一般的设计方案是,在 slot 中定义多个 div,然后在接到切换消息时,...
Windows-7-Navigation-Pane-Customizer