Qt自己定义事件实现及子线程向主线程传送事件消息
近期在又一次学习Qt的时候,由于要涉及到子线程与主线程传递消息,所以便琢磨了一下。顺便把有用的记录下来,方便自己以后查询及各位同仁的參考!
特此声明,本篇博文主要讲述有用的,也就是直接说明怎么实现,就不打算陈述一大堆理论啦,只是,还是建议大家去查查对应的理论比較好。这样能对Qt的消息传送机制的理解更加深入。
依据网上大多数人的资料,要实现自己定义消息,须要从QEvent 派生一个自己定义的事件;事实上也能够不须要,仅仅要使用QEvent::Type自己定义一个事件即可了。
在这里,本人把两种实现方法都在这里讲述一下!
一、这里先讲述使用 QEvent::Type 定义一个自己定义事件
1、新建一个新的project “myEvent” 。在 ui 界面加入一个button,并未button加入 onclick() 响应函数。
2、在 widget.h 头文件使用 QEvent::Type 定义两个自己定义事件。
3、又一次实现 event() 虚函数
bool event(QEvent* e);
4、加入 #include<QEvent>
整个头文件例如以下:
#ifndef WIDGET_H
#define WIDGET_H #include <QWidget>
#include <QEvent> namespace Ui {
class Widget;
} class Widget : public QWidget
{
Q_OBJECT public:
explicit Widget(QWidget *parent = 0);
~Widget(); bool event(QEvent* e); private slots:
void on_pushButton_clicked(); private:
Ui::Widget *ui; QEvent::Type myEvent1;
QEvent::Type myEvent2; }; #endif // WIDGET_H
5、使用QEvent::registerEventType() 静态函数为刚才两个自己定义事件注冊值。
6、又一次实现 event() 函数 。
7、在 button响应函数里面发送时间消息。
widget.cpp 文件例如以下:
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QCoreApplication>
#include <QDebug> Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this); myEvent1 = static_cast<QEvent::Type>(QEvent::registerEventType(-1));
myEvent2 = static_cast<QEvent::Type>(QEvent::registerEventType(-1));
} Widget::~Widget()
{
delete ui;
} bool Widget::event(QEvent* e)
{
if(e->type() == myEvent1){
QMessageBox::warning(this, tr("event"), tr("myEvent1"), QMessageBox::Yes); return true; }else if(e->type() == myEvent2){
QMessageBox::warning(this, tr("event"), tr("myEvent2"), QMessageBox::Yes); return true; } return QWidget::event(e);
} void Widget::on_pushButton_clicked()
{
QCoreApplication::sendEvent(this, &QEvent(myEvent1));
QCoreApplication::sendEvent(this, &QEvent(myEvent2)); }
编译执行后界面例如以下:
二、从 QEvent 派生一个自己定义事件类,类名取为 myEvent 。
1、myevent.h 头文件例如以下。里面自己定义了三个自己定义事件,分别为
m_event1, m_event2,
m_event3:
#ifndef MYEVENT_H
#define MYEVENT_H #include <QEvent> class myEvent : public QEvent
{
public:
myEvent(Type e); public:
static Type m_event1;
static Type m_event2;
static Type m_event3;
}; #endif // MYEVENT_H
2 、在myevent.cpp 文件里面使用QEvent::registerEventType()
为自己定义的事件注冊。
myevent.cpp 文件例如以下:
#include "myevent.h"
#include <QEvent> QEvent::Type myEvent::m_event1 = static_cast<QEvent::Type>(QEvent::registerEventType());
QEvent::Type myEvent::m_event2 = static_cast<QEvent::Type>(QEvent::registerEventType());
QEvent::Type myEvent::m_event3 = static_cast<QEvent::Type>(QEvent::registerEventType()); myEvent::myEvent(Type e):QEvent(e)
{
}
3、在 widget.cpp 文件 加入 myevent.h 头文件 。
4、改动 widget.cpp 文件中面的button响应函数例如以下:
void Widget::on_pushButton_clicked()
{
myEvent e(myEvent::m_event1);
QCoreApplication::sendEvent(this, &e);
}
5、改动 widget.cpp 文件中面的 event() 函数例如以下:
bool Widget::event(QEvent* e)
{
if(e->type() == myEvent1){
QMessageBox::warning(this, tr("event"), tr("myEvent1"), QMessageBox::Yes); <pre name="code" class="cpp"> return true; }else if(e->type() == myEvent2){
QMessageBox::warning(this, tr("event"), tr("myEvent2"), QMessageBox::Yes);
<pre name="code" class="cpp"><pre name="code" class="cpp"> return true;
}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、从 QThread 派生一个自己定义事件类,类名取为 myThread , 并又一次实现 run() 虚函数。mythread.h 头文件例如以下:
#ifndef MYTHREAD_H
#define MYTHREAD_H #include <QThread> class myThread : public QThread
{
Q_OBJECT
public:
explicit myThread(QObject *parent = 0); signals: public slots: protected:
void run();
}; #endif // MYTHREAD_H
2、在mythread.cpp 里面又一次实现 run() 函数。在里面实现向主线程发送事件消息,mythread.cpp 文件例如以下:
#include "mythread.h"
#include "myevent.h"
#include <QCoreApplication> myThread::myThread(QObject *parent) :
QThread(parent)
{
} void myThread::run()
{
myEvent e(myEvent::m_event2);
QCoreApplication::postEvent(this->parent(), new myEvent(myEvent::m_event2)); //this->exec();
}
3、在 widget.h 里面加入 mythread.h 头文件, 然后定义一个子线程对象, 例如以下:
#include"mythread.h"
myThread*m_pThread;
4、在堆内存里面为m_pThread开辟一个内存空间,例如以下:
<span style="color:#000000;">Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this); m_pThread = new myThread(this); 。。 。。。。
}</span>
5、在 ui 界面 加入还有一个button。并为它加入 onclick() 事件响应。然后在里面执行子线程,例如以下:
void Widget::on_pushButton_2_clicked()
{
m_pThread->start();
}
编译执行程序,效果例如以下:
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自己定义事件实现及子线程向主线程传送事件消息的更多相关文章
- c# 子线程与主线程通信二
之前写过使用线程上下文实现线程同步,今天利用子线程向主线程发送事件,实现子线程与主线程的同步 基本步骤 1.定义类 using System; using System.Collections.Gen ...
- [转]QT子线程与主线程的信号槽通信-亲测可用!
近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI.所以,网络通信端采用新开线程的方式.在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦.网上提供了很多同一线程不同类间采用信号槽 ...
- WinForm 中使用 Action 子线程对主线程 控制进行访问
/// <summary> /// 开启新线程执行 /// </summary> /// <param name="sender"></p ...
- Unity3d 创建线程 子线程与主线程通信
创建子线程 一,不带参数 Thread resourcesLoadThread=new Thread (this.resourceLoadTxt); resourcesLoadThread.Sta ...
- C# 子线程与主线程通讯方法一
最近在项目中要用到子线程运行结束向主线程通知的需求,利用线程上下文来实现线程之间的同步. 子线程结束后调用同步函数,向主线程发送时间字符串,改变主窗体的label标签 label标签改变事件触发处理函 ...
- Android笔记(三十一)Android中线程之间的通信(三)子线程给主线程发送消息
先看简单示例:点击按钮,2s之后,TextView改变内容. package cn.lixyz.handlertest; import android.app.Activity; import and ...
- 19 Handler 子线程向主线程发送信息
案例一 Message创建三种方法: package com.example.day19_handler_demo1; import android.os.Bundle; import android ...
- C# 子线程调用主线程窗体的解决方法
摘自其他人博客,自己试过确实解决问题.(如在自己定义的线程里面给textbox赋值) 由于Windows窗体控件本质上不是线程安全的.因此如果有两个或多个线程适度操作某一控件的状态(set value ...
- Android中,子线程使用主线程中的组件出现问题的解决方法
Android中,主线程中的组件,不能被子线程调用,否则就会出现异常. 这里所使用的方法就是利用Handler类中的Callback(),接受线程中的Message类发来的消息,然后把所要在线程中执行 ...
随机推荐
- jQuery静态分页功能
分页功能在做项目的过程中是常常用到的,下面是我常用的一款分页效果: 1.分页的CSS样式(page.css) #setpage { margin: 15px auto; text-align: cen ...
- 新浪微博 page应用 自适应高度设定 终于找到解决方法
我做的是PAGE应用,无法自适应高度.找了好久解决方法. 用js 设置父窗口 iframe 也不好用,有的浏览器不兼容. 官方上说发是这样的: 应用动态高度自适应 Iframe高度:开发者可以使Ifr ...
- [中山市选2011][bzoj2440] 完全平方数 [二分+莫比乌斯容斥]
题面 传送门 思路 新姿势get 莫比乌斯容斥 $\sum_{i=1}{n}\mu(i)f(i)$ 这个东西可以把所有没有平方质因子的东西表示出来,还能容斥掉重复的项 证明是根据莫比乌斯函数的定义,显 ...
- Delivering Goods UVALive - 7986(最短路+最小路径覆盖)
Delivering Goods UVALive - 7986(最短路+最小路径覆盖) 题意: 给一张n个点m条边的有向带权图,给出C个关键点,问沿着最短路径走,从0最少需要出发多少次才能能覆盖这些关 ...
- 怎么查看linux系统是32位还是64位
1.#uname -a如果有x86_64就是64位的,没有就是32位的 这是64位的 # uname -a Linux desktop 2.6.35-23-generic #20-Ubuntu SMP ...
- [ CodeVS冲杯之路 ] P3115
不充钱,你怎么AC? 题目:http://codevs.cn/problem/3115/ 基础的高精度减法,先判断一下被减数是否小于减数,若是则交换位置,打上 “-” 负号 当然也可以用压位做 #in ...
- sklearn的常用函数以及参数
sklearn可实现的函数或者功能可分为如下几个方面 1.分类算法2.回归算法3.聚类算法4.降维算法5.模型优化6.文本预处理 其中分类算法和回归算法又叫监督学习,聚类算法和降维算法又叫非监督学习 ...
- 使用 JavaScript 将网站后台的数据变化实时更新到前端-【知乎总结】
问: 难道只能设置定时器每隔一秒通过 Ajax 向后台请求数据来实现吗? 答: 1. nodejs的 http://socket.io 支持上述 李宏训 所说的三种方式,另外还支持 Flash Soc ...
- Selenium2+python自动化2-pip降级selenium3.0【转载】
selenium版本安装后启动Firefox出现异常:'geckodriver' executable needs to be in PATH selenium默默的升级到了3.0,然而网上的教程都是 ...
- poj 3348(凸包面积)
Cows Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8063 Accepted: 3651 Description ...