最近在看安晓辉老师的《Qt on android核心编程》一书,看到安老师写的一个跨线程使用信号槽的例子很好,特此分享一下,若有其他问题,请联系我删除。邮箱:lsylovecq@qq.com

直接上代码:widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QLabel>
#include <QThread>
#include <QPointer>

class SecondFirer : public QObject
{
    Q_OBJECT
public:
    SecondFirer(int seconds) : m_nSeconds(seconds){}

signals:
    void secondLeft(int sec, unsigned int id);
public slots:
    void onTimeout();
private:
    int m_nSeconds;
};

class CountThread : public QThread
{
public:
    CountThread(QWidget * receiver);
    ~CountThread();

protected:
    void run();

private:
    QPointer<QWidget> m_receiver;
};

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

public slots:
    void onSecondLeft(int sec, unsigned int id);

private:
    QLabel * m_label;
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include <QVBoxLayout>
#include <QMessageBox>
#include <QTimer>
#include <QDebug>

void SecondFirer::onTimeout()
{
    if(m_nSeconds >= 0)
    {
        unsigned int id = (unsigned int)QThread::currentThreadId();
        emit secondLeft(m_nSeconds, id);
        --m_nSeconds;
        qDebug() << "fire secondLeft signal";
    }
    else
    {
        QThread::currentThread()->exit(0);
    }
}

CountThread::CountThread(QWidget *receiver) : m_receiver(receiver)
{
}

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

void CountThread::run()
{
    qDebug() << "CountThread id - " << (unsigned int)QThread::currentThreadId();
    QTimer timer;
    SecondFirer firer(10);
    connect(&timer, SIGNAL(timeout()), &firer, SLOT(onTimeout()));
    timer.start(1000);

    if(!m_receiver.isNull())
    {
        qDebug() << "connect firer && receiver";
        connect(&firer, SIGNAL(secondLeft(int,uint)), m_receiver.data(), SLOT(onSecondLeft(int,uint)));
    }

    exec();
}


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , m_label(new QLabel)
{
    QVBoxLayout * layout = new QVBoxLayout;
    layout->addWidget(m_label);
    setLayout(layout);
    CountThread * t = new CountThread(this);
    connect(t, SIGNAL(finished()), t, SLOT(deleteLater()));
    t->start();
}

Widget::~Widget()
{
}

void Widget::onSecondLeft(int iLeft, unsigned int id)
{
    QString str = QString("remain %1, current thread id %2, fire thread id %3").arg(iLeft)
                  .arg((unsigned int)QThread::currentThreadId()).arg(id);
    m_label->setText(str);
    if(iLeft == 0)
    {
        QMessageBox::information(this, "CLAP NOW", "It\'s time to clap now!\nClap! Clap! Clap!");
    }
}

此处我就不做任何讲解了,代码的优雅之处各位看官自己慢慢体会吧。