QT Embedded----FAQ

来源:互联网 发布:淘宝商城三雄旗舰店 编辑:程序博客网 时间:2024/06/05 17:37

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。