近期在又一次学习Qt的时候,由于要涉及到子线程与主线程传递消息,所以便琢磨了一下。顺便把有用的记录下来,方便自己以后查询及各位同仁的參考!

特此声明,本篇博文主要讲述有用的,也就是直接说明怎么实现,就不打算陈述一大堆理论啦,只是,还是建议大家去查查对应的理论比較好。这样能对Qt的消息传送机制的理解更加深入。

依据网上大多数人的资料,要实现自己定义消息,须要从QEvent 派生一个自己定义的事件;事实上也能够不须要,仅仅要使用QEvent::Type自己定义一个事件即可了。

在这里,本人把两种实现方法都在这里讲述一下!

一、这里先讲述使用 QEvent::Type 定义一个自己定义事件

1、新建一个新的project “myEvent” 。在 ui 界面加入一个button,并未button加入 onclick() 响应函数。

2、在 widget.h 头文件使用 QEvent::Type 定义两个自己定义事件。

3、又一次实现 event() 虚函数

  1. bool event(QEvent* e);

4、加入 #include<QEvent>

整个头文件例如以下:

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QWidget>
  5. #include <QEvent>
  6.  
  7. namespace Ui {
  8. class Widget;
  9. }
  10.  
  11. class Widget : public QWidget
  12. {
  13. Q_OBJECT
  14.  
  15. public:
  16. explicit Widget(QWidget *parent = 0);
  17. ~Widget();
  18.  
  19. bool event(QEvent* e);
  20.  
  21. private slots:
  22. void on_pushButton_clicked();
  23.  
  24. private:
  25. Ui::Widget *ui;
  26.  
  27. QEvent::Type myEvent1;
  28. QEvent::Type myEvent2;
  29.  
  30. };
  31.  
  32. #endif // WIDGET_H

5、使用QEvent::registerEventType() 静态函数为刚才两个自己定义事件注冊值。

6、又一次实现 event()  函数 。

7、在 button响应函数里面发送时间消息。

widget.cpp 文件例如以下:

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. #include <QMessageBox>
  4. #include <QCoreApplication>
  5. #include <QDebug>
  6.  
  7. Widget::Widget(QWidget *parent) :
  8. QWidget(parent),
  9. ui(new Ui::Widget)
  10. {
  11. ui->setupUi(this);
  12.  
  13. myEvent1 = static_cast<QEvent::Type>(QEvent::registerEventType(-1));
  14. myEvent2 = static_cast<QEvent::Type>(QEvent::registerEventType(-1));
  15. }
  16.  
  17. Widget::~Widget()
  18. {
  19. delete ui;
  20. }
  21.  
  22. bool Widget::event(QEvent* e)
  23. {
  24. if(e->type() == myEvent1){
  25. QMessageBox::warning(this, tr("event"), tr("myEvent1"), QMessageBox::Yes); return true;
  26.  
  27. }else if(e->type() == myEvent2){
  28. QMessageBox::warning(this, tr("event"), tr("myEvent2"), QMessageBox::Yes); return true;
  29.  
  30. }
  31.  
  32. return QWidget::event(e);
  33. }
  34.  
  35. void Widget::on_pushButton_clicked()
  36. {
  37. QCoreApplication::sendEvent(this, &QEvent(myEvent1));
  38. QCoreApplication::sendEvent(this, &QEvent(myEvent2));
  39.  
  40. }

编译执行后界面例如以下:

二、从 QEvent 派生一个自己定义事件类,类名取为 myEvent 。

1、myevent.h 头文件例如以下。里面自己定义了三个自己定义事件,分别为
m_event1, m_event2,
m_event3:

  1. #ifndef MYEVENT_H
  2. #define MYEVENT_H
  3.  
  4. #include <QEvent>
  5.  
  6. class myEvent : public QEvent
  7. {
  8. public:
  9. myEvent(Type e);
  10.  
  11. public:
  12. static Type m_event1;
  13. static Type m_event2;
  14. static Type m_event3;
  15. };
  16.  
  17. #endif // MYEVENT_H

2 、在myevent.cpp 文件里面使用QEvent::registerEventType()
为自己定义的事件注冊。

myevent.cpp 文件例如以下:

  1. #include "myevent.h"
  2. #include <QEvent>
  3.  
  4. QEvent::Type myEvent::m_event1 = static_cast<QEvent::Type>(QEvent::registerEventType());
  5. QEvent::Type myEvent::m_event2 = static_cast<QEvent::Type>(QEvent::registerEventType());
  6. QEvent::Type myEvent::m_event3 = static_cast<QEvent::Type>(QEvent::registerEventType());
  7.  
  8. myEvent::myEvent(Type e):QEvent(e)
  9. {
  10. }

3、在 widget.cpp 文件 加入   myevent.h 头文件 。

4、改动 widget.cpp 文件中面的button响应函数例如以下:

  1. void Widget::on_pushButton_clicked()
  2. {
  3. myEvent e(myEvent::m_event1);
  4. QCoreApplication::sendEvent(this, &e);
  5. }

5、改动 widget.cpp 文件中面的 event() 函数例如以下:

  1. bool Widget::event(QEvent* e)
  2. {
  3. if(e->type() == myEvent1){
  4. QMessageBox::warning(this, tr("event"), tr("myEvent1"), QMessageBox::Yes); <pre name="code" class="cpp"> return true;
  5.  
  6. }else if(e->type() == myEvent2){
  7. QMessageBox::warning(this, tr("event"), tr("myEvent2"), QMessageBox::Yes);
  8. <pre name="code" class="cpp"><pre name="code" class="cpp"> return true;
  1.  

}else if(e->type() == myEvent::m_event1){ QMessageBox::warning(this, tr("myEvent"), tr("m_event1"), QMessageBox::Yes); return true; } else if(e->type() == myEvent::m_event2){ QMessageBox::warning(this, tr("myEvent"), tr("m_event2"), QMessageBox::Yes); return
true; } return QWidget::event(e);}

  1.  
  1.  

然后又一次编译执行,效果例如以下:

三 、 前面讲的都是在主线程里面传递事件消息,接下来讲述怎样 在子线程里面 往主线程 传递事件消息。

1、从 QThread 派生一个自己定义事件类,类名取为 myThread , 并又一次实现 run() 虚函数。mythread.h 头文件例如以下:

  1. #ifndef MYTHREAD_H
  2. #define MYTHREAD_H
  3.  
  4. #include <QThread>
  5.  
  6. class myThread : public QThread
  7. {
  8. Q_OBJECT
  9. public:
  10. explicit myThread(QObject *parent = 0);
  11.  
  12. signals:
  13.  
  14. public slots:
  15.  
  16. protected:
  17. void run();
  18. };
  19.  
  20. #endif // MYTHREAD_H
  21.  

2、在mythread.cpp 里面又一次实现 run() 函数。在里面实现向主线程发送事件消息,mythread.cpp 文件例如以下:

  1. #include "mythread.h"
  2. #include "myevent.h"
  3. #include <QCoreApplication>
  4.  
  5. myThread::myThread(QObject *parent) :
  6. QThread(parent)
  7. {
  8. }
  9.  
  10. void myThread::run()
  11. {
  12. myEvent e(myEvent::m_event2);
  13. QCoreApplication::postEvent(this->parent(), new myEvent(myEvent::m_event2));
  14.  
  15. //this->exec();
  16. }

3、在 widget.h        里面加入 mythread.h 头文件, 然后定义一个子线程对象, 例如以下:

#include"mythread.h"

myThread*m_pThread;

4、在堆内存里面为m_pThread开辟一个内存空间,例如以下:

  1. <span style="color:#000000;">Widget::Widget(QWidget *parent) :
  2. QWidget(parent),
  3. ui(new Ui::Widget)
  4. {
  5. ui->setupUi(this);
  6.  
  7. m_pThread = new myThread(this);
  8.  
  9. 。。
  10.  
  11. 。。。。
  12. }</span>

5、在 ui  界面 加入还有一个button。并为它加入 onclick() 事件响应。然后在里面执行子线程,例如以下:

  1. void Widget::on_pushButton_2_clicked()
  2. {
  3. m_pThread->start();
  4. }

编译执行程序,效果例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGJtb3hpYQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

四、QCoreApplication::postEvent(); 和
QCoreApplication::sendEvent();     的差别。

在前面的程序中发送 事件消息 的时候用到了
QCoreApplication::postEvent(); 和
QCoreApplication::sendEvent(); 两个函数,这里可不是随便使用的,这两个函数时又差别的!

1、QCoreApplication::sendEvent();   依据Qt Asistant 里面的讲述。这个函数直接将事件消息直接发送给接受者进行处理,等到事件处理完成后才返回;而且使用它所传递的消息事件是在
栈(stack) 上创建的,也就是说它的内存空间是有编译器来自己主动管理的。

2、QCoreApplication::postEvent();    依据Qt
Asistant 里面的讲述,使用这个函数来传递时间消息时。它将事件消息发送到接受者的的消息队列里面,然后马上返回。不须要等到事件处理完成才返回;而且使用它所传递的消息事件是在 堆(heep) 上创建的。也就是说它的内存空间是又程序猿自己管理的,如用 new 创建的变量。

这两个函数对事件的处理方式就像使用 repaint()  和 paint() 这两个函数对界面进行重画一样。前者直接对界面进行重画操作;后者先将重画事件放到消息队列里面,等到适当的时候在对界面进行重画操作。

在上面的子线程给主线程传递消息的时候使用的就是QCoreApplication::postEvent();  函数。由于这里必须保证在子线程退出之前,若子线程所传递的事件消息还未被主线程处理的话,子线程所传递的消息仍然是可用的。

好了。主线程内事件的传递与子线程向主线程传递事件消息的方法就介绍到这里了。至于Qt 的事件传送机制。这里就没有怎么讲了。只是还是建议读者好好去了解一下的好。

Qt自己定义事件实现及子线程向主线程传送事件消息的更多相关文章

  1. c# 子线程与主线程通信二

    之前写过使用线程上下文实现线程同步,今天利用子线程向主线程发送事件,实现子线程与主线程的同步 基本步骤 1.定义类 using System; using System.Collections.Gen ...

  2. [转]QT子线程与主线程的信号槽通信-亲测可用!

    近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI.所以,网络通信端采用新开线程的方式.在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦.网上提供了很多同一线程不同类间采用信号槽 ...

  3. WinForm 中使用 Action 子线程对主线程 控制进行访问

    /// <summary> /// 开启新线程执行 /// </summary> /// <param name="sender"></p ...

  4. Unity3d 创建线程 子线程与主线程通信

    创建子线程 一,不带参数 Thread   resourcesLoadThread=new Thread (this.resourceLoadTxt); resourcesLoadThread.Sta ...

  5. C# 子线程与主线程通讯方法一

    最近在项目中要用到子线程运行结束向主线程通知的需求,利用线程上下文来实现线程之间的同步. 子线程结束后调用同步函数,向主线程发送时间字符串,改变主窗体的label标签 label标签改变事件触发处理函 ...

  6. Android笔记(三十一)Android中线程之间的通信(三)子线程给主线程发送消息

    先看简单示例:点击按钮,2s之后,TextView改变内容. package cn.lixyz.handlertest; import android.app.Activity; import and ...

  7. 19 Handler 子线程向主线程发送信息

    案例一 Message创建三种方法: package com.example.day19_handler_demo1; import android.os.Bundle; import android ...

  8. C# 子线程调用主线程窗体的解决方法

    摘自其他人博客,自己试过确实解决问题.(如在自己定义的线程里面给textbox赋值) 由于Windows窗体控件本质上不是线程安全的.因此如果有两个或多个线程适度操作某一控件的状态(set value ...

  9. Android中,子线程使用主线程中的组件出现问题的解决方法

    Android中,主线程中的组件,不能被子线程调用,否则就会出现异常. 这里所使用的方法就是利用Handler类中的Callback(),接受线程中的Message类发来的消息,然后把所要在线程中执行 ...

随机推荐

  1. Codeforces Round #324 (Div. 2) D

    D. Dima and Lisa time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  2. IEjs 调试、火狐 js 调试

    http://www.jb51.net/article/26707.htm IE下调试代码, 在代码中写 debugger; 然后IE启用调试, 会执行到debugger 断点出, 双击变量 右键 添 ...

  3. Android JSON

    转自:http://www.open-open.com/lib/view/open1326376799874.html JSON的定义: 一 种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性 ...

  4. [LeetCode]Word Search 回溯

    Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...

  5. iOS crash 崩溃问题的追踪方法

    http://www.cnblogs.com/easonoutlook/archive/2012/12/27/2835884.html iOS crash 崩溃问题的追踪方法 在调试程序的时候,总是碰 ...

  6. 【原创】Linux环境下的图形系统和AMD R600显卡编程(9)——R600显卡的3D引擎和图形流水线

    1. R600 3D引擎 R600核心是AMD一款非常重要的GPU核心,这个核心引入了统一处理器架构,其寄存器和指令集同以前的GPU 都完全不同,对其编程也有比较大的区别. 图1显示了R600 GPU ...

  7. java实现MQ消息收发两种方式

    定义: 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们.简单理解:蓝牙配对 jar包依赖: <!-- ...

  8. CppCMS1.0.3 Build by VS2012

    1.CppCMS简介 CppCMS是一个C++的Web开发框架(不是一个CMS).它不同于大多数其他Web开发框架,如巨蟒Django , Java的Servlets ,或C++ Wt因为它在设计和调 ...

  9. C 实现删除非空文件夹

    /* 文件名:   rd.c ---------------------------------------------------- c中提供的对文件夹操作的函数,只能对空文件夹进行 删除,这使很多 ...

  10. zabbix 批量添加聚合图形

    环境为centos 脚本要在centos zabbix服务器上运行,zabbix server上运行 1.先把脚本部署到zabbix客户端,把脚本保存为nic.sh 存放路径确保zabbix可以访问 ...