QT显示机制(一)

来源:互联网 发布:nginx配置http和https 编辑:程序博客网 时间:2024/05/03 03:21
原文地址:QT显示机制(一)作者:blackdream2

QT显示机制

              -------AlbertChen

QT被Nokia收购了,我们以后的项目用QT做UI开发的可能性也不大,这些都无所谓,嵌入式系统的UI开发包大体架构应该还是相通的,深入了解QT对以后理解新的平台应该是有帮助的,QT有很多免费的版本在网上很容易找到并下载,这样的话大家都可以参看源代码共同学习。我不是个技术水平高的人,所以大家不要给我扔砖头。

 

QT的窗体系统的管理,窗体事件是如何派发的,在前一篇《QT窗体事件底层派发机制》中已经作了简要的分析,QT的显示机制算是对上一篇文章的补充。

 

了解QT显示机制,最重要的就是要了解QT是如何管理窗体的显示区域的,这里有个重要的类:QRegion, 在QT中可以通过QRegion定义一个窗体的显示区域,也可以通过QRegion定义窗体的可修改区域,比如在QPainter()中通过QPainter::setClipRect设定一个区域,我们绘图则只能在这个区域,此区域外绘图都是无效的。通过QRegion可以作一系列的逻辑运算,如两个区域相加,相减等。QRegion定义的区域不一定是连续的,但一定是由封闭的区域组成的,我们常会碰到一个窗体的显示区域被其他窗体分割为几块的情况。QT对这些显示区域的管理,类似于对窗体的管理,也是通过服务器与客户端的方式。参照以前的说法Server表示为全局的Global ,客户端为本地得Local。那么WindowsServer管理一个全局的显示区域即所有的Top-Level widget显示区域。而其他的child windget 的管理则在每一个QT应用程序中由QWSRegionManager管理,Top_Level widget 显示区域也会加载在其中,这个不难理解,因为Server只是负责将窗体事件发送到客户端,具体处理还是由客户端来操作。具体的流程还是来看代码吧。

 

显示区域管理者QWSRegionManager的初始化

服务器:

通过调用openDisplay()。

客户端:   

在QWSDisplayData类的构造函数中通过调用QWSDisplayData::init()完成。

 

考虑一个比较简单的情况,我们要显示的widget 是一个Top_Leverl widget。在调用Show()函数中,这个widget将通过showWindows()向服务器请求做三件事:(以下窗体是指在global windows statck 中的TOP_Level widget)

1:调用QWSDisplay::requestRegion向服务器请求窗体显示区域。

2:调用QWSDdisplay::setAltitude向服务器请求设置窗体的优先级。此优先级是指在windows statck中的位置,而不是指QWSWidow 中的窗体优先级属性。Windows statck 中的第一个窗体就是显示在LCD上最前面的窗体。

3:调用QWSDisplay::requestFocus 向服务器请求设置窗体为焦点窗体。焦点窗体能接收Key, Mouse 事件,但不是所有的焦点窗体都能接收Key,Mouse 事件,如果有窗体设置为GrabKey 或则GrabMouse 则Key, Mouse 事件将分别传递至此窗体。

下面将通过代码分析winddows Server对这三个请求的处理过程:

 一: QWSDisplay::requestRegion的处理

void QWSServer::invokeRegion( QWSRegionCommand *cmd, QWSClient *client )

{

    ................

    QRegion region;

    region.setRects(cmd->rectangles, cmd->simpleData.nrectangles);

    if !region.isEmpty() )

changingw->setNeedAck( TRUE );

    bool isShow !changingw->isVisible() && !region.isEmpty();

    setWindowRegionchangingw, region ); //***设置窗体显示区域 

    syncRegions( changingw );                //***通知客户端 刷新显示区域

    if isShow )

emit windowEvent( changingw, Show );

    if !region.isEmpty() )

emit windowEvent( changingw, Geometry );

    else

emit windowEvent( changingw, Hide );

    if focusw == changingw && region.isEmpty() )

setFocus(changingw,FALSE);

    .................

}

invokeRegion调用setWindowRegion设置窗体显示区域,调用syncRegions通知客户端 刷新显示区域,并产生一些窗体事件如:Show, GeometryHide 

 

 

0 0