说明:复现的代码来自《Qt C++6.0》P496-P500。在复现时完全按照代码,出现了两处报错:
(1)ui指针(2)按钮的响应函数。下面程序对以上问题进行了修改。除了图片、清空、关闭功能外,其他功能实现复现。
主线程:
.h文件
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_ThreadTest_one.h"
#include "QtClass.h"
class ThreadTest_one : public QMainWindow//主线程
{
Q_OBJECT
private:
QtClass* threadA;
protected:
void closeEvent(QCloseEvent* event);
public:
ThreadTest_one(QWidget* parent = nullptr);
~ThreadTest_one();
private:
Ui::ThreadTest_oneClass ui;
public slots:
void do_threadA_started();
void do_threadA_finished();
void do_threadA_newValue(int seq, int diceValue);
void on_actThread_Run_clicked();
void on_actDice_Run_clicked();
void on_actThread_Quit_clicked();
void on_actDict_Pause_clicked();
};
.cpp文件
#include "ThreadTest_one.h"
#include <QCloseEvent>
#include <QThread>
ThreadTest_one::ThreadTest_one(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
threadA = new QtClass(this);//创建工作线程
connect(threadA, &QtClass::started, this, &ThreadTest_one::do_threadA_started);
connect(threadA, &QtClass::finished, this, &ThreadTest_one::do_threadA_finished);
connect(threadA, &QtClass::newValue, this, &ThreadTest_one::do_threadA_newValue);
}
void ThreadTest_one::do_threadA_started() {
ui.statusBar->showMessage("Thread状态:thread start");
ui.actThread_Run->setEnabled(false);
ui.actThread_Quit->setEnabled(true);
ui.actDice_Run->setEnabled(true);
}
void ThreadTest_one::do_threadA_finished() {
ui.statusBar->showMessage("Thread状态:thread finished");
ui.actThread_Run->setEnabled(true);
ui.actThread_Quit->setEnabled(false);
ui.actDice_Run->setEnabled(false);
ui.actDict_Pause->setEnabled(false);
}
void ThreadTest_one::do_threadA_newValue(int seq, int diceValue) {//与线程的newValue()信号相关联
QString str = QString::asprintf("第%d次投骰子,点数为%d", seq, diceValue);
ui.plainTextEdit->appendPlainText(str);
}
//按键的槽函数
void ThreadTest_one::on_actThread_Run_clicked() {//要用clicked才能得到响应
threadA->start();
}
void ThreadTest_one::on_actThread_Quit_clicked() {
threadA->stopThread();
}
void ThreadTest_one::on_actDice_Run_clicked() {
threadA->diceBegin();
ui.actDice_Run->setEnabled(false);
ui.actDict_Pause->setEnabled(true);
}
void ThreadTest_one::on_actDict_Pause_clicked() {
threadA->dicePause();
ui.actThread_Run->setEnabled(true);
ui.actDict_Pause->setEnabled(false);
}
//重定义事件处理函数,确保窗口关闭时线程被停止
void ThreadTest_one::closeEvent(QCloseEvent* event) {
if (threadA->isRunning()) {
threadA->terminate();
threadA->wait();
}
event->accept();
}
ThreadTest_one::~ThreadTest_one()
{}
工作线程:
.h文件
#pragma once
#include <QThread>
class QtClass : public QThread
{
Q_OBJECT
public:
QtClass(QObject *parent);
~QtClass();
private:
int m_seq = 0; //掷骰子次数的序号
int m_diceValue;//骰子的点数
bool m_paused = true;//暂停投骰子
bool m_stop = false;//停止线程
protected:
void run();//线程的任务
public:
void diceBegin();//开始掷骰子
void dicePause();//暂停投骰子
void stopThread();//停止线程
signals:
void newValue(int seq, int diceValue);//产生新点数的信号
};
.cpp文件
#include "QtClass.h"
#include<QRandomGenerator>
#include<QThread>
QtClass::QtClass(QObject *parent)
: QThread(parent)
{}
void QtClass::diceBegin() {//开始掷骰子
m_paused = false;
}
void QtClass::dicePause() {//停止掷骰子
m_paused = true;
}
void QtClass::stopThread() {//停止线程
m_stop = true;
}
void QtClass::run() {//run函数处理事件循环
m_stop = false;
m_paused = true;
m_seq = 0;
while (!m_stop) {
if (!m_paused) {
m_diceValue = QRandomGenerator::global()->bounded(1, 7);
m_seq++;
emit newValue(m_seq, m_diceValue);
}
msleep(500);
}
quit();//退出线程
}
QtClass::~QtClass()
{}