1.如何管理从堆中new出的QObject对象?如何安全delete才能避免内存泄露?
这个问题看起来很愚蠢,new出QObject,不用时delete了,不就行了,怎么会有这种问题呢? 问题就在于"不用时"难以确定.
QT是一个图形平台系统,有些时候,对象之间的逻辑关系比较复杂,用户可能找不到合适的时机delete或者需要写额外的代码来delete。为此,QT提供了一些机制,来帮助你管理对象的生命周期,在合适的时候帮助你delete。
(1)利用对象树object_trees管理对象
先看一下,QObject的构造函数
QObject的类构造函数的第一个参数也是一个QObject.如下:
QObject( QObject *parent=0, const char *name=0 );
第一个参数实际上为QObject指定个父对象。QT中所有parent=0的对象形成一个双向链表object_trees,每个parent=0的对象及其所有子对象也形成一棵树,parent=0的对象是树根,其它子对象/孙子对象挂在这个树上. 当父对象删除时,QT会遍历其子对象并删除. 所以最好为每个子对象指定一个父对象,这样只要记得删除这个父对象就可以了。当然对于没有父对象的QT对象,就需要手工写代码删除。
这个方法适用于所有QObject对象及其子类对象。
(2)利用WDestructiveClose属性
先看一下,QWidget的构造函数
QWidget( QWidget* parent=0, const char* name=0, WFlags f=0 );
利用最后一个参数WFlags f可以指定WDestructiveClose属性,当调用QWidget::close关闭时,QWidget::close里会检查是否有WDestructiveClose属性,如果有就是主动delete这个对象。
这个方法仅适用于QWidget对象及其子对象
2.widget和window之间有什么区别?
在QT/E的代码会出现window这个名词,window一般是指topLevelWidget。
3.什么是topLevelWidget?
答案很简单,就是具有WType_TopLevel属性的widget。对于这个属性用户也可以直接用QWidget::setWFlags()来设置,但是除非用户明白想做什么,否则不要做。因为QWidget::setWFlags只是改了一下值,并没有做其它调整。
有些的widget会有WType_TopLevel:
(1)在构造函数中指定WType_TopLevel WType_Dialog WType_Popup WType_Desktop
(2)在构造函数中指定parentWidget=0
4.topLevelWidget和普通的widget有什么区别?
(1)topLevelWidget->parenWidget()=0
(2)topLevelWidget->winId()>0
topLevelWidget在调用show后,QWS server会记录这个widget,并分配一个大于0的winId.对于普通的widget, QWS Server是不管理的,也不知道其存在,其winId是负值。
(3)topLevelWidget在调用show后,QWS Server会分配屏幕区域给topLevelWidget。普通的widget的有parentWidget,是从其parenWidget分配屏幕区域,因此在QT Embedded中,普通的widget是由其parentWidget管理的。
(4)对应于Win32/MFC中的概念,topLevelWidget就是具有WS_OVERLAPPEDWINDOW或WS_POPUPWINDOW属性的window(有title,border),普通的widget就是control或child window。
5.什么是activewindow?
QWS Server会记录所有的topLevelWidget,在这些topLevelWidget中,在一个时刻只有一个是activeWindow,QWS Client收到QWS Server发来的key event后,会把key event再发给activewindow->focusWidget()。
6.this->focusWidget(),this->topLevelWidget()->focusWidget(),qapp->focusWidget() ?
this->focusWidget==this->topLevelWidget()->focusWidget()
qapp->focusWidget() == qapp->activeWindow()-->focusWidget()
7.什么是QWS Client和QWS Server?
QT Embedded也是一种C/S结构,需要有一个QT application做QWS Server,程序启动时带有-qws参数的就是QWS Server,不带这个参数就是QWS Client。因此任何一个基于QT的application都可以做QWS Server。当然QWS Server一定先于QWS Client启动,否则QWS Client将启动失败。在实际应用中,会指定某个特殊的application做QWS Server,这个application一般还会管理一些其它的系统资源。
8.QWS Server是如何管理QWS Client的?
QWS Server是一个server socket,QWS Client是一个client socket。QWS Client启动时会主动向QWS Server的server socket建立连接。而后就QWS Server通过这个socket传递QWSCommand和QWSEvent来管理QWS Client。
9.QT/E application是否有类似Win32/MFC的消息队列?
有,从代码上看应该有四个,优先级从高到低如下:
(1)QWSEvent事件队列
(2)posted QEvent事件队列
(3)socket事件队列
(4)timer事件队列
10.sendEvent和postEvent的区别?
sendEvent是直接同步调用
postEvent是间接异步调用,先把事件放到posted QEvent事件队列中,对于发往同一个widget的同一种事件会做合并,在事件循环中再处理。
11.QWidget::repaint和QWidget::update的区别?
这个类似于sendEvent和postEvent.QWidget::repaint会导致QWidget立即重画,QWidget::update只是产生一个QPaint事件并调用postEvent将其放入posted event队列,等待消息循环检查到有事件后再执行。因此要尽量使用QWidget::update,绘图操作是比较消息耗CPU时间。
12.能给其它进程的QWidget发消息?
不能,QT Embeded是一个简单的图形系统,不能像Win32/MFC那样通过EnumWindows/FindWindow查找整个系统的window,不能通过sendMessaget给其它进程的window发消息。虽然topLevelWidget->winId()也是唯一的,但是不同进程的widget是互相不知道的。在QT Embeded上没有类似spy++的工具。
13.QT Embeded是否支持多进程多线程?
支持多进程,编译时由QT_NO_QWS_MULTIPROCESS来控制。有些嵌入式环境下没必要支持多进程,可以只有一个QT进程,即做QWS Server,又做QWS Client。这样编译出来的共享库会小一些,程序执行起来也快。
支持多线程,编译时由QT_THREAD_SUPPORT来控制,QT Embeded还定义了QMutex、QSemaphore、QThread等类支持多线程,实现线程之间的通讯。QThread本身是pthread库的一个封库。
14.QT Embeded是否线程安全?
C++的类库一般都不是线程安全的,QT Embeded也不例外,其的绝大多数函数和类都不是线程安全,线程安全需要用户自已保证。QApplication提供一个锁,用户可以qapp->lock()/unlock()来保护代码或自已定义QMutex。
15.既然QT Embeded线程不安全,线程如何给widget发消息?
可以通过QThread::postEvent给widget发消息,QThread::postEvent实际调用QApplication::postEvent来实现的,QApplication::postEvent是线程安全,它通过postevent_mutex来保护posted event队列。将消息加入到posted event队列后,会唤醒主线程执行消息循环,从而保证新加入的消息有机会被执行。
16.QT Embedded的线程能创建并使用widget?
QT Embedded的线程应该都看做是work thread,尽量只做与UI无关的事情,不要直接操作widget,给widget发消息调用QThread::postEvent。QT Embedded中的widget和消息队列没有线程属性的,都是属于整个进程的。因此最好只在主进程中操作widget。
17.QApplication::exec能嵌套使用吗?
直觉上是可以的,但是从代码上看是不行的,QApplication::exec只能调用一次。
18.QThread中可以有消息循环吗?可以调用QApplication::exec吗?
QThread中不能调用QApplication::exec,不要有消息循环,尽量只做与UI无关的事情。
19.如何阻塞住当前事件的执行,但又不阻塞住整个消息循环?
这就是模态对话框的功能,QApplication::exec不能嵌套使用,但是消息循环可以嵌套,这个需要自已实现。QDialog::exec就是直接调用QApplication::enter_loop来嵌套一个新的消息循环,阻塞当前事件的执行,通过调用QApplication::exit_loop来退出当前的消息循环并继续执行原事件。
20.调用QApplication::enter_loop时注意什么?
调用QApplication::enter_loop时会嵌套一个新的消息循环,具体实现可以考QDialog::exec的实现。但是QDialog的实现是有问题的,没有判断当前的loopLevel。
21.如何改变qvfb桌面的默认颜色(绿色)?
qte 2.x里提供的API:
QWSServer::setDesktopBackground(const QColor&);
QWSServer::setDesktopBackground(const QImage&);
qtopia core 4里提供的API:
QWSServer::setBackground(const QBrush&);
默认的颜色在源码的qwindowsystem_qws.cpp文件, QWSServer的构造函数里赋值,也可以直接去修改源码。