我们要实现的是读取大文件qtgui.index
的内容加入文本框中。
很容易想到的方法:
QFile* file = new QFile("E:\qtgui.index");
file->open(QIODevice::ReadOnly);
QTextStream *stream = new QTextStream(file);
while(!stream->atEnd())
{
QString line = stream->readLine();
ui->textEdit->append(line);
}
结果运行后发现程序失去响应。因为读取大文件要很长时间,事件循环一直等待函数返回,这样导致阻塞事件循环。结果,GUI线程所有的绘制和交互都被阻塞在事件队列中,无法执行重绘等事件,整个程序就失去响应了。
解决阻塞一般有两种方法:
手动强制事件循环
在任务中不断调用QCoreApplication::processEvents()手动强制事件循环,它会在处理完队列中所有事件后返回。但是如果两次函数调用的间隔时间不够短,用户仍能明显感觉到程序卡顿。所以在while循环最后加一行QApplication::processEvents();
即可。
多线程处理。
Qt提供了三种方式:QThread、QRunnable / QThreadPool、QtConcurrent。其中最常用的是 QThread。
对于本例,使用QThread又有三种方法:信号与槽实现线程间通信、元对象系统实现线程间通信、分离线程与任务。前两种也是跨线程调用函数的方法。
使用QThread
信号与槽实现线程间通信
这是线程间通信比较常用的方法。代码:
class ReadThread : public QThread
{
Q_OBJECT
public:
ReadThread(QObject* obj);
signals:
void toLine(QString line);
protected:
void run() Q_DECL_OVERRIDE;
private:
QFile* file;
QObject* m_obj;
};
ReadThread::ReadThread(QObject* obj):
m_obj(obj)
{
file = new QFile("E:\qtgui.index");