前几天遇到一个问题:
有一个类A
class A: public QWidget
一个类B
class B: public QThread
B在A中生成一个实例b
A中有一个按钮,点击后启动b,b要操作A中的lcdNumber实时显示一个数
问题来了,b的run()函数是如何声明的?
void B::run()
{
……
}
像这样吗?
void B::run()
{
A::ui->lcdNumber->display(k);
}
编译不过去的。
因为GUI线程中的事件循环并没有做线程同步,如果直接利用非GUI线程操作界面的控件,会触发新的事件,因此可能会破坏GUI线程的事件循环
对于这种情况,需要采用信号、槽机制
我的例子如下:
头文件:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QThread>
#include "ui_widget.h"
namespace Ui {
class Widget;
}
class MyThread : public QThread
{
Q_OBJECT
signals:
void signalOut(); //这里我定义了一个信号
protected:
void run();
};
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
MyThread mythread;
protected:
void changeEvent(QEvent *e);
private:
Ui::Widget *ui;
private slots:
void on_pushButton_clicked();
void myshow(); //这里我定义了一个槽
};
#endif // WIDGET_H
CPP文件:
#include "widget.h"
#include "ui_widget.h"
int k=0;
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
connect(&mythread, SIGNAL(signalOut()), this, SLOT(myshow()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
void Widget::on_pushButton_clicked()
{
mythread.start();
}
void MyThread::run()
{
while(1)
{
k++;
if(k>99999)
k=0;
emit signalOut();
}
}
void Widget::myshow()
{
ui->lcdNumber->display(k);
}
大家可以试一试,你会发现功能实现了,但有死掉的趋势。界面好像响应不过来了。程序好像也是动一下停半天,数字变化不连续。
我们再加上一条语句
void MyThread::run()
{
while(1)
{
k++;
if(k>99999)
k=0;
emit signalOut();
msleep(1); //延时1毫秒
}
}
一切都活了。
为什么会这样,看起来好像QT的开发小组为我们证明了“欲速则不达”。但显然这个线程在被系统拆分成时间片时发生了堵塞。
所以,在处理数据时,给你的程序一点喘息的时间,鞭打快牛是会被牛反踢一脚的。