首页 > 编程语言 > 详细

第85课 多线程与界面组件的通信(下)

时间:2017-03-03 23:51:21      阅读:325      评论:0      收藏:0      [点我收藏+]

1. 信号槽机制与界面更新

技术分享 

(1)子线程发射信号通知主线程进行界面更新

(2)主线程根据具体信号以及信号参数对界面组件进行修改

2. 事件机制与界面更新——解决方案:发送自定义事件

(1)自定义事件类用于描述界面更新细节

(2)在主窗口类中重写事件处理函数event

(3)使用postEvent函数(异步方式)发送自定义事件类对象

  ①子线程指定接受消息的对象为主窗口对象

  ②在event事件处理函数更新界面状态

技术分享 

【编程实验】子线程中更新界面组件

//StringEvent.h

#ifndef STRINGEVENT_H
#define STRINGEVENT_H

#include <QEvent>
#include <QString>
//自定义事件对象
class StringEvent : public QEvent
{
    QString m_data;
public:
    //提供全局唯一的Type值
    static const QEvent::Type TYPE = static_cast<QEvent::Type>(QEvent::User + 0xFF);
    explicit StringEvent(QString data = "");

    QString data();

    //用于测试采用postEvent发送事件对象,被接收后会自动释放!
    ~StringEvent();
};

#endif // STRINGEVENT_H

//StringEvent.cpp

#include "StringEvent.h"
#include <QDebug>

StringEvent::StringEvent(QString data) : QEvent(TYPE)
{
    m_data = data;
    qDebug() << "StringEvent::StringEvent(QString data)";
}

QString StringEvent::data()
{
    return m_data;
}

StringEvent::~StringEvent()
{
    qDebug() << "StringEvent::~StringEvent()";
}

//UpdateThread.h

#ifndef UPDATETHREAD_H
#define UPDATETHREAD_H

#include <QThread>

class UpdateThread : public QThread
{
    Q_OBJECT
protected:
    void run();
public:
    explicit UpdateThread(QObject* parent = 0);

signals:
    void updateUI(QString text);
};

#endif // UPDATETHREAD_H

//UpdateThread.cpp

#include "UpdateThread.h"
#include <QApplication>
#include "StringEvent.h"

UpdateThread::UpdateThread(QObject *parent) : QThread(parent)
{
}

void UpdateThread::run()
{
    //发送事件对象
    QApplication::postEvent(parent(), new StringEvent("Begin"));  //parent为目标widget

    for(int i=0; i<10; i++){
        QApplication::postEvent(parent(), new StringEvent(QString::number(i)));

        sleep(1);
    }

    QApplication::postEvent(parent(), new StringEvent("End"));
}

//Widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QPlainTextEdit>
#include <QWidget>
#include "UpdateThread.h"

class Widget : public QWidget
{
    Q_OBJECT
    UpdateThread m_thread;
    QPlainTextEdit textEdit;

public:
    Widget(QWidget *parent = 0);
    bool event(QEvent* evt);
    ~Widget();
};

#endif // WIDGET_H

//Widget.cpp

#include "Widget.h"
#include "StringEvent.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    textEdit.setParent(this);
    textEdit.move(20, 20);
    textEdit.resize(200, 150);
    textEdit.setReadOnly(true);

    connect(&m_thread, SIGNAL(updateUI(QString)), this, SLOT(appendText(QString)));

    //这里使用了一个技巧,将Widget这个组件传入线程中所供子线程访问。
    m_thread.setParent(this);//传这个目标Widget组件给子线程

    m_thread.start();
}

bool Widget::event(QEvent *evt)
{
    bool ret = true;

    if(evt ->type() ==StringEvent::TYPE ){
        StringEvent* se = dynamic_cast<StringEvent*>(evt);

        if(se != NULL){
            textEdit.appendPlainText(se->data());
        }
    }else{
        ret = QWidget::event(evt);
    }

    return ret;
}

Widget::~Widget()
{

}

//main.cpp

#include "Widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

3. 小结

(1)Qt中可以发送自定义事件在子线程中间接操作界面组件

(2)必须使用postEvent函数进行事件发送(异步方式

(3)发送的事件对象必须在堆上创建

(4)子线程创建时必须附带目标对象的地址信息

第85课 多线程与界面组件的通信(下)

原文:http://www.cnblogs.com/5iedu/p/6498723.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!