- 浏览: 3449301 次
- 性别:
- 来自: 苏州
文章分类
最新评论
-
sonichy:
Qt5改动很多,要改改了。
基于QItemDelegate的例子1 SpinBoxDelegate -
我的主页6:
楼主,2.2子查询的分页方式:SELECT * FROM ar ...
Mysql 分页语句Limit用法 -
liguoqi:
非常感谢楼主的用心指导,工具以及图片例子都提供了 赞!
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载 -
liguoqi:
问下这个图片怎么解压损坏呀
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载 -
liguoqi:
楼主讲解的非常详细,还附带工具和图片例子,非常感谢
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载
一、元对象
元对象被称做是meta object.在运行时刻(runtime),能够提供对象的运行时信息。
MFC的实现方式是宏定义:如
QT的实现方式是宏定义加moc编译,定义宏Q_OBJECT,并对语言本身做了部分扩展,因此需要用QT的moc编译器特殊处理一下,产生一个moc_XXX.cpp的文件,然后就可以使用通用C++编译器编译了。
Q_OBJECT的定义如下:
#define Q_OBJECT \ public: \ virtual QMetaObject *metaObject() const { \ return staticMetaObject(); \ } \ virtual const char *className() const; \ virtual void* qt_cast( const char* ); \ virtual bool qt_invoke( int, QUObject* ); \ virtual bool qt_emit( int, QUObject* ); \ QT_PROP_FUNCTIONS \ static QMetaObject* staticMetaObject(); \ QObject* qObject() { return (QObject*)this; } \ QT_TR_FUNCTIONS \ private: \ static QMetaObject *metaObj;
从定义上看,QT的元对象信息主是通过QMetaObject对象来管理的,每一个类都会增加一个static QMetaObject *metaobj。QMetaObject中包含三部分信息:
(1)className,superclassname
这是用来判断对象的继承关系的,是实现QObject::isA(const char *classname)和QObject::inherits(const char *classname)的基础。
(2)用来实现Q_PROPERTY的property信息。
(3)用来实现signal/slot的信息
二、 signal/slot
signal/slot机制是QT最具特色的特性。signal/slot巧妙的简单的实现了面向对象编程中经常使用的观察者模式(observer,或称为消息预定模式)。同时也封装了callback机制,一定程度上保证了callback函数的类型安全。
从实现上来看,signal/slot需要QMetaObject和moc编译器的支持。signal和slot实际上是两种类函数,分别需要在类函数声明前面加signals和slots两个宏。以QButton的一个signals和slots为例说明实现过程:
class Q_EXPORT QButton : public QWidget { Q_OBJECT ......... signals: void pressed(); ................ public slots: void animateClick(); };
(1)signal/slot机制需要增加Q_OBJECT声明,signal/slot是元对象信息,需要QMetaObject的支持。
(2)signals、slots、emit都是宏,从定义上看,都是空值。对C++编译器编译没有任何影响。实际上,这三个宏都是给QT的moc编译器使用的。moc编译器会对标记为signals和slots的函数编号,方便的实现(编号,函数名字,函数地址)三者之间的转换。同时实现了标记为signals的函数。因此pressed()函数的是由moc编译器实现的,不需要用户实现,具体内容在moc_qbutton.cpp中。
(3)connect/disconnect这两个函数的定义如下:
QObject::connect( const QObject *sender, const char *signal, const QObject *receiver, const char *member )
QObject::disconnect( const QObject *sender, const char *signal, const QObject *receiver, const char *member )
QMetaObject中会为每一个signal建立一个QConnectList列表,记录着连接到这个signal的所有receiver和其slot函数。 connect就是在QConnectList中增加一项,让sender的QMetaObject记住。disconnect的作用相反。
(4)emit pressed()
emit是一个宏,但是一个空值,因此emit pressed()==pressed()。pressed()是由moc编译器实现的。 QButton::pressed()就是把通过QConnectList把所连接的receiver和其member函数找出来,然后按先后顺序调用receiver->member(),由于是一个list,所以是先连接的slot先执行。这与Observer模式中的实现是一致的。
从上面的分析来看,signal/slot是同步直接调用。实现有些复杂,效率上比callback函数也慢一些,但是对于面向对象编程来说,非常符合对象之间低耦合的思想,减少了对象之间的依赖。使用起来也灵活。函数接口也可以任意组合。的确是QT的特色。
使用过程中,也需要注意如下几点:(1)QT的signal和unix操作系统的signal是不同的,unix的signal是进程之间的一种通讯方式,QT的signal是对象之间的一种消息传递方式,不是一个层面的概念。
(2)slot函数的返回值是没有意义的,signal函数是由moc编译器实现的,从具体实现来看,不关心slot函数的返回值。
(3)根据目前的实现,slot函数的被执行是有顺序的,但是这要依赖于目前的实现,以后或许会变
(4)signal/slot和(public,protected,private)没有冲突,private的函数也可以是signal/slot
(4)slot函数可以是虚函数吗?
(5)signal函数可以是虚函数吗?
三、 event机制
在面象对象编程中,对象是核心。对象之间的需要通讯,对象A需要给对象B发消息。A对象向怎么才能向B对象发消息message? 一般需要把message定义成B对象的一个函数,然后由A对象调用b->message.这种实现不灵活,每个message都要定义函数。
在UI系统中,不同的widget会经常发各种消息,要用上面的方式肯定是不行的。通常UI系统都会把这些消息和消息参数规范化。QT把消息类型和消息参数都封装到QEvent及其子类中,同时定义了QObject::event(QEvent *e)函数来处理各种QEvent,并且在此基础上实现了消息钩子和消息拦截等功能。这就是QT的event机制,下面详细介绍一下具体实现。
1.QEvent
QEvent封装了消息类型和消息参数,还有一些属性。下面是其实现代码:
class Q_EXPORT QEvent: public Qt // event base class { public: enum Type { None = 0, // invalid event Timer = 1, // timer event MouseButtonPress = 2, // mouse button pressed MouseButtonRelease = 3, // mouse button released MouseButtonDblClick = 4, // mouse button double click MouseMove = 5, // mouse move KeyPress = 6, // key pressed KeyRelease = 7, // key released FocusIn = 8, // keyboard focus received FocusOut = 9, // keyboard focus lost Enter = 10, // mouse enters widget Leave = 11, // mouse leaves widget .................. WindowStateChange = 96, // window state has changed IconDrag = 97, // proxy icon dragged User = 1000, // first user event id MaxUser = 65535 // last user event id }; QEvent( Type type ) : t(type), posted(FALSE), spont(FALSE) {} virtual ~QEvent(); Type type() const { return t; } bool spontaneous() const { return spont; } protected: Type t; private: uint posted : 1; uint spont : 1; friend class QApplication; friend class QAccelManager; friend class QBaseApplication; friend class QETWidget; };
QEvent首先将各种消息编号,如
KeyPress,KeyRelease,FocusIn,FocusOut,Show,并用变量t标识类型,同时还有两个属性:posted用来标识QEvent是由sendEvent发出还是由postEvent发出的;spont的含义不明,从代码上看,只有通过sendSpontaneousEvent发出的QEvent的spont才是true;
2.QObject::event(QEvent *e)
QObject::event是QT的消息处理函数。下面分析其实现:
bool QObject::event( QEvent *e ) { #if defined(QT_CHECK_NULL) if ( e == 0 ) qWarning( "QObject::event: Null events are not permitted" ); #endif //这里的消息钩子和消息拦截 if ( eventFilters ) { // try filters if ( activate_filters(e) ) // stopped by a filter return TRUE; } //下面就是分发消息了 switch ( e->type() ) { case QEvent::Timer: timerEvent( (QTimerEvent*)e ); return TRUE; case QEvent::ChildInserted: case QEvent::ChildRemoved: childEvent( (QChildEvent*)e ); return TRUE; case QEvent::DeferredDelete: delete this; return TRUE; default: if ( e->type() >= QEvent::User ) { customEvent( (QCustomEvent*) e ); return TRUE; } break; } return FALSE; }
从实现上看,QObject::event函数相当于所有消息的一个分发函数,根据e->type的类型再分别调用,其相应的函数,如timerEvent,keyPressEvent等。
3.消息钩子和消息拦截
UI系统中,经常需要知道是否某一个widget收到某一类型的消息,例如没有focus的widget想接收当前keypress或keyrelease事件,这就需要在当前有foucs的widget上面安装一个钩子hook,并且在适当的时候截断这个消息,使得即使有focus的widget也不能收到事件。这就是消息钩子和消息拦截功能。在QT中,这是通过eventFilter来实现的。
首先,需要调用QObject::installEventFilter安装eventFilter,即focuswidget->installEventFilter(nonfocuswidget)。
下面,我们看看当有QEvent到来时发生了什么。根据QObject::event的实现,QObject::event会首先检查是否有eventFilter,如果有就会执行activate_filters,下面是activate_filters的实现。
bool QObject::activate_filters( QEvent *e ) { if ( !eventFilters ) // no event filter return FALSE; QObjectListIt it( *eventFilters ); register QObject *obj = it.current(); while ( obj ) { // send to all filters ++it; // until one returns TRUE if ( obj->eventFilter(this,e) ) { return TRUE; } obj = it.current(); } return FALSE; // don't do anything with it }
activate_filters会依次执行每个安装的QObject::eventFilter,这是一个虚函数。这样用户可以改eventFilter,加上自已的逻辑实现,这样nonfocuswidget就知道目前发生了一个keypress事件。
从代码中,还可以看出,如果有一个eventFilter函数返回值是TRUE,将会停止执行eventFilter函数,并返加TRUE到QObject::event,然后QObject::event也不会继续执行,这样就使实现了消息拦截功能。
4.QEvent与Win32的消息对比
Win32中,也对所有的消息进行了封装,也有消息处理函数,不过Win32的实现与QT的实现差别还是很大的:
(1)Win32提供的是C接口,所以没有把消息封装成类,这个即使是MFC也没有。Win32中,消息类型是一个UINT,消息参数固定成两个参数(WPARAM wParam, LPARAM lParam)。
(2)Win32的消息处理函数WindowProc也是一个C接口的函数,它的原型如下:
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
其中uMsg是消息类型,wParam和lParam是两个消息参数。从这点来看,Win32的实现简洁一些。
(3)Win32中的消息是围绕window定义,window是处理消息的主体。在QT中,消息处理定义到了QObject这一层,而不是在QWidget上,因此所有的 QObject都可以处理消息。QT中的消息也不仅局限于窗口消息,如ChildInserted和ChildRemoved就是处理两个QObject之间父子关系的。
(4)Win32中的消息钩子功能要比eventFilter强大,不公能拦截本进程内窗口的消息,还能拦截整个系统内所有窗口的消息。
5.event和signal/slot的对比
event和signal/slot都是QT提供的两种对象间通讯的方式,下面是一些不同点:
(1)signal/slot的需要元对象模型的支持,需要声明Q_OBJECT。event与元对象模型无关。
(2)emit signal是一种同步直接调用,对于event来说,sendEvent是同步直接调用,postEvent是异步调用。
(3)用户可以自定义signal/slot的类型,event的类型都是提前定义好的,从这一点上看,signal/slot更为灵活。
(4)signal/slot缺少消息钩子和消息拦截功能
QApplication代表着QT Embedded应用程序的运行时对象,类似于MFC的CWinApp。应用程序可以通过一个全局指针变量qApp表访问当前应用程序的QApplication。 对于QT应用来说,第一步就是要创建一个QApplication对象。 在此过程中,做了如下事情:
(1)初始化qApp
(2)对于QWS Server,创建QWSServer全局指针qwsServer
(3)创建QDisplay全局指针qt_fbdpy
(4)创建QScreen全局指针qt_screen
1.初始化qApp
2.创建QWSServer全局指针qwsServer
3.创建QDisplay全局指针qt_fbdpy
4.创建QScreen全局指针qt_screen
发表评论
-
Qt官网变更【2012】
2012-09-21 19:30 4220Qt最近被Digia完全收购,诺基亚这两年的不理不睬,没有魄力 ... -
【转】QT实现不规则窗体
2012-09-21 18:50 5007看到好文章,收藏一下: 看到网上有很多不规则窗体的实现 ... -
Qt应用程序如何使用DCMTK类库进行二次开发DICOM数据传输
2012-09-13 09:35 0参考文章: 1、Using DCMTK with ... -
【转】将QT开发的界面程序封装成DLL,在VC中成功调用
2012-09-11 10:33 21135最近手头的一个项目需要做一个QT界面,并且封装成DLL,然后 ... -
诺基亚挥别Qt,转手给Digia
2012-09-11 09:37 2867一家总部位于芬兰的IT业务供应商Digia今天宣布,已经签署了 ... -
Qt多线程间信号槽传递非QObject类型对象的参数
2012-09-07 15:29 21405一、以前就发现过这个问题: 在Qt项目中,有时候为了 ... -
QT样式表(QStyleSheet)
2012-08-17 10:37 17909QT样式表 (QStyleSheet) 作者:刘旭晖 ... -
FinalData磁盘文件恢复工具(绿色破解版)
2012-08-02 13:28 8615FinalData磁盘文件恢复工具(绿色破解版),使用起来很方 ... -
Eclipse Qt开发环境的建立【转】
2012-08-01 11:15 43981.下载Eclipse目前Eclipse+CDT已经可以 ... -
汽车辐射监测系统-Qt开发
2012-07-25 16:18 4700最近晚上抽空忙了两个月,才把一个小系统做完。虽然做的不是太完 ... -
Qt做发布版,解决声音和图片、中文字体乱码问题
2012-07-14 16:02 4875Qt做发布版,解决声音和图片、中文字体乱码问题 ... -
QTableView使用中的疑问,如何及时显示操作Model后的结果?
2012-06-01 14:52 0最终的解决方法:我正 ... -
【转】Qt QTableview使用
2012-06-01 09:49 9682QTableWidget是QT程序中常用的显示数 ... -
QTableView双击 单机事件信号
2012-06-01 09:47 23139双击QTableView的行,获取该行数据 代码 ... -
QMessageBox改变大小
2012-05-31 15:33 8463创建一个QMessageBox: QMessageBo ... -
更新QTableView中的进度条状态
2012-05-30 14:37 14885前段时间,我接触了,如何在一个QTableView中加入一个控 ... -
QThread 线程暂停 停止功能的实现
2012-05-29 11:56 12223为了实现Qt中线程的暂停运行,和停止运行的控制功能 需要在设 ... -
QT环境变量
2012-05-28 18:53 5598不知道为啥同事有台电脑,装完Qt-VS2008库,和VS Ad ... -
广告光
2012-05-24 18:33 0盈创广告联盟 http://www.yo114.cn/ ... -
Test
2012-05-24 18:22 2195Test<IMG SRC="cf08e32c2 ...
相关推荐
Qt Embedded是一个轻量级、可定制的图形用户界面框架,特别适合于嵌入式设备。本文将详细介绍如何在Qt Embedded环境中实现软键盘输入功能,以供字母、数字及各种符号的输入。 首先,我们要了解Qt中的Input Method ...
### Qt Embedded中自定义键盘驱动实现详解 #### 一、背景与目的 在Qt Embedded开发过程中,对于嵌入式设备而言,实现一个自定义的键盘驱动是非常常见的需求。特别是当设备需要特定的输入方式或者标准的键盘解决方案...
8. QT 的元对象系统可以对信号和槽使用模板,可以在多个平台的应用程序中完全应用模板。 知识点:QT 的元对象系统、模板使用、跨平台应用 9. moc 是 QT 的元对象编译器,可以产生能被任何标准 C++ 编译器访问的...
对象模型提供了诸如属性系统、事件处理、动态属性和元对象系统等功能,使得Qt在编程时具有高度的灵活性和可扩展性。 1. **信号与槽机制**:这是Qt中最独特的设计,允许对象之间进行通信而无需相互了解对方。当一个...
3. moc(Meta Object Compiler):用于处理Qt的元对象系统,支持信号与槽机制,这是Qt事件驱动编程的关键。 二、Qt对象模型 1. 信号与槽:Qt中对象间通信的方式,信号表示一个状态或事件的发生,槽是响应这些事件的...
9. **嵌入式开发**:针对Qt在嵌入式设备上的应用,如Qt for Embedded Linux和Qt Quick for Devices。 10. **Qt Quick**:讲解基于QML的快速UI开发,包括元素、动画和状态机的使用。 11. **Qt Widgets**:详细介绍...
8. **Qtopia与QtEmbedded**:这部分内容详细阐述Qtopia和QtEmbedded,这两个是专为嵌入式系统设计的Qt版本,它们的特性、配置和应用实例。 9. **设备驱动与硬件交互**:在嵌入式开发中,直接与硬件交互是常见的任务...
诺基亚曾经是 Qt 的主要维护者之一,但现在已经转交给了 The Qt Company。可以访问 Qt 官方网站下载最新版的 Qt Creator 安装包。假设下载了 `qt-sdk-win-opensource-2010.02.1.exe` 文件,在 Windows 下完成安装...
12. **QT的嵌入式开发**: QT Embedded(现在称为QT for Devices)允许在嵌入式设备上运行QT应用,如嵌入式Linux系统或物联网设备。 13. **QT Quick (QML)**: QML是一种声明式的UI设计语言,结合JavaScript,可以...
- **QObjects和继承**:Qt的基础类是QObject,它提供了信号和槽、属性系统以及事件处理等功能,大部分Qt类都继承自QObject。 2. **Qt开发环境** - **Qt Creator**:官方提供的集成开发环境(IDE),集成了编辑器...
此外,还有QObject类,它是所有Qt对象的基类,提供了属性系统和事件处理等基本功能。 Qt的图形用户界面(GUI)组件是另一个重要的部分,包括各种窗口小部件(Widgets),如按钮、文本框、菜单等。这些小部件通过...
本文将围绕"Qt.zip_QT"的主题,深入探讨Qt框架中的关键概念、核心功能和实际应用,特别关注“qtopia精讲”部分,这通常指的是早期的Qt for Embedded Linux,现在已更名为Qt for Devices。 **一、消息与槽机制** 在...
1. **Qt基础知识**:Qt 的核心概念,如信号与槽机制,这是Qt事件处理的核心,使得对象间通信变得简单高效。还有QObjects、QObject派生类以及如何创建自定义的控件。 2. **Qt界面设计**:Qt Designer 工具的使用,...
QT还拥有元对象系统,允许在运行时进行类型查询和动态属性操作,这极大地增强了代码的灵活性和可扩展性。元对象系统是基于QObject类构建的,它使得在多个平台的应用程序中可以完全应用模板。 QT的元对象编译器(moc...
Qt的核心特性之一是它的对象模型,这是通过QObject类实现的。QObject类提供了事件处理、信号与槽机制、属性系统以及类型系统,这些特性使得Qt成为一种面向对象的编程框架。信号与槽机制是Qt的独有特性,允许对象之间...
QT的元对象系统(Meta-Object System)是其独特之处,它扩展了C++,增加了运行时类型信息、动态属性以及信号和槽的动态连接能力。元对象编译器(moc,Meta-Object Compiler)是一个工具,它处理包含Q_OBJECT宏的类,...
本章介绍了Qt的对象模型,包括信号与槽机制,元对象系统以及元对象编译器(moc)的工作原理。QObject类是所有Qt对象的基类,涵盖对象树、事件处理、定时器、连接函数connect等。Qt的国际化支持使得软件能适应多种...
1. **QObject和继承体系**:Qt库基于QObject类,所有图形和非图形组件都继承自它,提供了信号和槽、属性系统等特性。 2. **信号与槽**:信号表示状态变化,槽是响应这些变化的函数,两者通过连接实现异步通信。 3. *...
- **QObject** 是所有 **Qt** 对象的基类。 - **QWidget** 类继承自 **QObject**,类似于 **MFC** 中的 **CWnd** 类,用于创建和管理窗口组件。 - 任何继承自 **QWidget** 的类都可以被用来创建可视化的窗口或...