在 Qt 中处理平台相关的底层事件Word下载.docx

上传人:b****8 文档编号:22957543 上传时间:2023-02-06 格式:DOCX 页数:15 大小:83.56KB
下载 相关 举报
在 Qt 中处理平台相关的底层事件Word下载.docx_第1页
第1页 / 共15页
在 Qt 中处理平台相关的底层事件Word下载.docx_第2页
第2页 / 共15页
在 Qt 中处理平台相关的底层事件Word下载.docx_第3页
第3页 / 共15页
在 Qt 中处理平台相关的底层事件Word下载.docx_第4页
第4页 / 共15页
在 Qt 中处理平台相关的底层事件Word下载.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

在 Qt 中处理平台相关的底层事件Word下载.docx

《在 Qt 中处理平台相关的底层事件Word下载.docx》由会员分享,可在线阅读,更多相关《在 Qt 中处理平台相关的底层事件Word下载.docx(15页珍藏版)》请在冰豆网上搜索。

在 Qt 中处理平台相关的底层事件Word下载.docx

Q_WS_WIN

Windows

Q_WS_X11

XWindow

Q_WS_MAC

Mac

如果项目中调用了平台相关的APIs,那么利用条件编译,使得源程序不用修改,就可以适用于不同的平台。

对于XWindow平台,代码片断如清单1所示:

清单1.

#ifdefined(Q_WS_X11)

//与XWindow相关的nativeAPIs

#endif

对于Windows平台,代码片断如清单2所示:

清单2.

#ifdefined(Q_WS_WIN)

//与Windows相关的nativeAPIs

对于MAC平台,代码片断如清单3所示:

清单3.

#ifdefined(Q_WS_MAC)

//与Mac相关的nativeAPIs

2.Xlib与XEvent

Xlib是XWindow提供的API集合,Xlib之上是XtIntrinsicslibrary,Xt采用面向对象的设计方法,提供了大量的widgets。

在Xt之上则是各种各样的toolkits,最常用的是Motif。

Qt没有对Xt进行封装,而是直接建立在Xlib之上。

Xlib用一个叫"

XEvent"

的结构来保存从X服务器那里接收到的事件。

Xlib提供了大量的事件类型。

XEvent包括事件的类型,以及与事件相关的数据。

Qt也定义了一组事件类。

其中QEvent是基类。

其他具体事件类,例如QMouseEvent、QKeyEvent、QFocusEvent、QPaintEvent、QMoveEvent、QResizeEvent等都是从QEvent继承而来。

多数情况下,利用Qt的事件机制,能够满足我们的需求。

但是,在某些特定的情况,我们需要能够截获XWindow的底层事件,并对其进行处理。

本文介绍了两种截获XEvent的方法,一种是重载QApplication的x11EventFilter()方法;

另一种是重载QWidget的x11Event()方法。

文中提供的例子基于Qt4.3,并在FedoraCore6上调试通过。

3.QApplication:

:

x11EventFilter()如何工作

QApplication类管理Qt应用程序的控制流和主要设置。

它包含了主事件循环,对来自窗口系统的所有事件进行处理和调度。

它也处理应用程序的初始化和结束,并且提供对话管理。

QApplication中定义了针对XWindow平台的虚函数,如清单4所示:

清单4.

boolQApplication:

x11EventFilter(XEvent*)

创建QApplication的子类,并且重新实现函数x11EventFilter(),那么所有底层的XEvent会首先被函数x11EventFilter()截获。

如果希望在函数x11EventFilter()中针对某事件进行响应,那么在响应结束后返回TRUE,表示该事件不会被分派到QApplication的Qt主事件循环中。

如果函数返回FALSE,那么该事件会被继续分派到QApplication的Qt主事件循环中,由Qt包装成Qt事件。

此外,针对Windows平台,QApplication定义了类似的虚函数,如清单5所示:

清单5.

boolQCoreApplication:

winEventFilter(MSG*msg,long*result)

针对Mac平台,QApplication定义了类似的虚函数,如清单6所示:

清单6.

macEventFilter(EventHandlerCallRefcaller,EventRefevent)

下面通过一个例子说明,如何在Qt中处理XEvent。

该例子包括两个可执行程序,一个是xclient,另一个是qtx11filter。

xclient基于Xlib,向qtx11filter发送XClientMessageEvent。

qtx11filter截获所有的XEvent,但只对XClientMessageEvent进行处理,将其它所有类型的XEvent都分派到QApplication的Qt主事件循环中。

3.1xclient的主要流程和源代码

xclient的主要流程如下:

1.用户通过命令行输入16进制的windowID。

2.向该windowID所在的窗口发送XClientMessageEvent。

该事件所携带的数据是一个长度为4的字符串”2008”。

xclient的完整源代码xclient.c如清单7所示:

清单7.

#include<

stdio.h>

X11/X.h>

X11/Xlib.h>

charline[80];

unsignedlongwinID,mask;

XEventev;

Display*disp;

Statusstatus;

intmain(intargc,char*argv[]){

disp=XOpenDisplay(NULL);

if(!

disp){

perror("

UnabletoopenXdisplay"

);

exit

(1);

}

do{

printf("

Enteraline:

"

fgets(line,80,stdin);

if(line[0]!

='

q'

){

winID=strtol(line,NULL,16);

Youentered%d:

0x%x\n"

winID,winID);

ev.xclient.type=ClientMessage;

ev.xclient.window=winID;

ev.xclient.message_type=0;

ev.xclient.format=8;

ev.xclient.data.b[0]='

2'

;

ev.xclient.data.b[1]='

0'

ev.xclient.data.b[2]='

ev.xclient.data.b[3]='

8'

ev.xclient.data.b[4]='

\0'

mask=0l;

status=XSendEvent(disp,winID,False,mask,&

ev);

TheXSendEventreturned:

%d\n"

status);

XFlush(disp);

}while(line[0]!

}

在FedoraCore6中,利用如下命令编译xclient:

清单8.

gccxclient.c–oxclient–lX11

3.2qtx11filter的主要流程和源代码

qtx11filter的主要流程如下:

1.创建QApplication的子类App,并实现虚函数x11EventFilter。

注意使用宏定义Q_WS_X11,因为x11EventFilter只适用于XWindow。

2.在x11EventFilter中,判断所截获的XEvent,如果事件类型为ClientMessage,那么打印出该事件发送者的windowID,并且打印出该事件所携带的数据。

3.在main()函数中,创建类App的实例,并且通过调用app.exec(),启动Qt主事件循环。

qtx11filter的完整源代码qtx11filter.c如清单9所示:

清单9.

qapplication.h>

qpushbutton.h>

qdialog.h>

classApp:

publicQApplication{

public:

App(intargc,char**argv):

QApplication(argc,argv){}

#ifdefined(Q_WS_X11)

boolx11EventFilter(XEvent*xe){

switch(xe->

type){

caseClientMessage:

CaughtClientMessageXEventfromWindow%d\n"

xe->

xclient.window);

Receivemessage:

%s\n"

xclient.data.s);

returntrue;

returnfalse;

#endif

};

classDialog:

publicQDialog{

Dialog(QWidget*parent=0):

QDialog(parent){

QPushButton*done=newQPushButton("

Done"

this);

connect(done,SIGNAL(clicked()),qApp,SLOT(quit()));

intmain(intargc,char**argv){

Appapp(argc,argv);

Dialogdialog;

app.setMainWidget(&

dialog);

dialog.show();

returnapp.exec();

在FedoraCore6中,用以下命令编译qtx11filter:

清单10.

g++qtx11filter.c-L/usr/lib/qt-3.3/lib-I/usr/lib/qt-3.3/include

-lqt-mt–lX11-oqtx11filter

3.3演示xclient和qtx11filter

1.在终端启动qtx11filter

清单11.

./qtx11filter

弹出仅包含一个按钮的窗口,如图1所示:

图1.qtx11filter窗口

2.在终端启动xwininfo,如图2所示:

图2.xwininfo窗口

3.将光标移动到窗口qtx11filter,点击鼠标左键,xwininfo可以获取qtx11filter的windowID,如图3所示(截图中已经用红色方框标出)。

图3.获取qtx11filter的windowID

4.在终端启动xclient,并输入qtx11filter的windowID,如图4所示。

然后,xclient会向qtx11filter发送XClientMessageEvent,该事件携带一个四字节的字符串”2008”。

图4.输入qtx11filter的windowID

5.打开运行qtx11filter的终端,qtx11filter已经从windowID为39845889的窗口接收到一个XClientMessageEvent,并读取出该事件所携带的数据”2008”,如图5所示:

图5.qtx11filter处理XClientMessageEvent

4.QWidget:

x11Event()如何工作

QWidget是Qt所有用户界面对象的基类。

它从窗口系统接收鼠标、键盘和其它事件,并且在屏幕上绘制自己。

QWidget定义了针对XWindow平台的虚函数:

清单12.

boolQWidget:

x11Event(XEvent*)

创建QWidget或者其已有派生类的子类,并且重新实现函数x11Event(),那么所有发送到该Widget的XEvent首先被函数x11Event()截获。

如果希望在函数x11Event()中针对某事件进行响应,那么在响应结束后返回TRUE。

如果函数返回FALSE,那么该事件会被包装成Qt事件,发送给Widget。

QWidget:

x11Event(XEvent*)和QApplication:

x11EventFilter(XEvent*)的区别在于:

前者在XEvent发送到特定QtWidget之前,被该Widget截获;

后者在XEvent发送到整个程序的主事件循环之前,被QApplication截获。

5.Qt中其它与平台相关的APIs

在每个平台上,Qt都为QWidget提供了一个winId()函数,返回该QtWidget的windowID;

QWidget还提供了一个静态函数find(),该函数可以返回一个特定windowID所对应的QtWidget。

我们可以将获得的windowID传递给NativeAPI来执行平台特定的操作。

此外,针对XWindow,Qt提供了类X11Info,用以获取XWindow平台的信息。

例如,通过调用静态成员函数X11Info:

display()可以获取Qt程序与Xserver建立的连接句柄。

参考资料

∙Qt官方网站

∙Xorg官方网站

∙Qt兴趣邮件列表

∙Qt的信号与槽机制介绍

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1