dialog.h:

#ifndef DIALOG_H
#define DIALOG_H #include <QDialog> #include "masterthread.h"
//这里的写法有点。。为什么不直接加头文件
QT_BEGIN_NAMESPACE class QLabel;
class QLineEdit;
class QSpinBox;
class QPushButton;
class QComboBox; QT_END_NAMESPACE class Dialog : public QDialog
{
Q_OBJECT public:
explicit Dialog(QWidget *parent = nullptr); private slots:
void transaction();
void showResponse(const QString &s);
void processError(const QString &s);
void processTimeout(const QString &s); private:
void setControlsEnabled(bool enable); private:
int transactionCount;
QLabel *serialPortLabel;                  //声明了各类控件
QComboBox *serialPortComboBox;
QLabel *waitResponseLabel;
QSpinBox *waitResponseSpinBox;
QLabel *requestLabel;
QLineEdit *requestLineEdit;
QLabel *trafficLabel;
QLabel *statusLabel;
QPushButton *runButton; MasterThread thread;                    //创建了一个线程类
}; #endif // DIALOG_H

masterthread.h:

#ifndef MASTERTHREAD_H
#define MASTERTHREAD_H #include <QThread>
#include <QMutex>
#include <QWaitCondition> //! [0]
class MasterThread : public QThread
{
Q_OBJECT public:
explicit MasterThread(QObject *parent = nullptr);
~MasterThread(); void transaction(const QString &portName, int waitTimeout, const QString &request);        //用来传递GUI界面的信息函数
void run() Q_DECL_OVERRIDE;                                         //线程运行函数 signals:
void response(const QString &s);                                      //一些信号:响应、错误、时间
void error(const QString &s);
void timeout(const QString &s); private:
QString portName;                                               //需要操作记录的私有变量
QString request;
int waitTimeout;
QMutex mutex; //互斥锁,保护上面的私有变量
QWaitCondition cond; //条件变量,用来同步
bool quit;
};
//! [0] #endif // MASTERTHREAD_H

dialog.cpp:

#include "dialog.h"

#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QSpinBox>
#include <QPushButton>
#include <QGridLayout> #include <QtSerialPort/QSerialPortInfo> QT_USE_NAMESPACE Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, transactionCount()
, serialPortLabel(new QLabel(tr("Serial port:")))
, serialPortComboBox(new QComboBox())
, waitResponseLabel(new QLabel(tr("Wait response, msec:")))
, waitResponseSpinBox(new QSpinBox())
, requestLabel(new QLabel(tr("Request:")))
, requestLineEdit(new QLineEdit(tr("Who are you?")))
, trafficLabel(new QLabel(tr("No traffic.")))
, statusLabel(new QLabel(tr("Status: Not running.")))
, runButton(new QPushButton(tr("Start")))
{
const auto infos = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo &info : infos)
serialPortComboBox->addItem(info.portName()); waitResponseSpinBox->setRange(, );
waitResponseSpinBox->setValue(); auto mainLayout = new QGridLayout;
mainLayout->addWidget(serialPortLabel, , );
mainLayout->addWidget(serialPortComboBox, , );
mainLayout->addWidget(waitResponseLabel, , );
mainLayout->addWidget(waitResponseSpinBox, , );
mainLayout->addWidget(runButton, , , , );
mainLayout->addWidget(requestLabel, , );
mainLayout->addWidget(requestLineEdit, , , , );
mainLayout->addWidget(trafficLabel, , , , );
mainLayout->addWidget(statusLabel, , , , );
setLayout(mainLayout); setWindowTitle(tr("Blocking Master"));
serialPortComboBox->setFocus(); connect(runButton, &QPushButton::clicked, this, &Dialog::transaction);
connect(&thread, &MasterThread::response, this, &Dialog::showResponse);
connect(&thread, &MasterThread::error, this, &Dialog::processError);
connect(&thread, &MasterThread::timeout, this, &Dialog::processTimeout);
} void Dialog::transaction()
{
setControlsEnabled(false);
statusLabel->setText(tr("Status: Running, connected to port %1.")
.arg(serialPortComboBox->currentText()));
thread.transaction(serialPortComboBox->currentText(),
waitResponseSpinBox->value(),
requestLineEdit->text());
} void Dialog::showResponse(const QString &s)
{
setControlsEnabled(true);
trafficLabel->setText(tr("Traffic, transaction #%1:"
"\n\r-request: %2"
"\n\r-response: %3")
.arg(++transactionCount).arg(requestLineEdit->text()).arg(s));
} void Dialog::processError(const QString &s)
{
setControlsEnabled(true);
statusLabel->setText(tr("Status: Not running, %1.").arg(s));
trafficLabel->setText(tr("No traffic."));
} void Dialog::processTimeout(const QString &s)
{
setControlsEnabled(true);
statusLabel->setText(tr("Status: Running, %1.").arg(s));
trafficLabel->setText(tr("No traffic."));
} void Dialog::setControlsEnabled(bool enable)
{
runButton->setEnabled(enable);
serialPortComboBox->setEnabled(enable);
waitResponseSpinBox->setEnabled(enable);
requestLineEdit->setEnabled(enable);
}

masterthread.cpp:

#include "masterthread.h"

#include <QtSerialPort/QSerialPort>

#include <QTime>

QT_USE_NAMESPACE

MasterThread::MasterThread(QObject *parent)
: QThread(parent), waitTimeout(), quit(false)
{
} //! [0]
MasterThread::~MasterThread()
{
mutex.lock();
quit = true;
cond.wakeOne();
mutex.unlock();
wait();
}
//! [0] //! [1] //! [2]
void MasterThread::transaction(const QString &portName, int waitTimeout, const QString &request)
{
//! [1]
QMutexLocker locker(&mutex);                            //用QMutexLocker锁住函数内的操作
this->portName = portName;
this->waitTimeout = waitTimeout;
this->request = request;
//! [3]
if (!isRunning())                                  //判断线程是否启动
start();
else
cond.wakeOne();                                 //已经启动则唤醒线程
}
//! [2] //! [3] //! [4]
void MasterThread::run()
{
bool currentPortNameChanged = false;          //临时变量 mutex.lock();
//! [4] //! [5]
QString currentPortName;                 //临时变量
if (currentPortName != portName) {
currentPortName = portName;
currentPortNameChanged = true;
} int currentWaitTimeout = waitTimeout;
QString currentRequest = request;
mutex.unlock();                      //到这里把私有信息传递进去了
//! [5] //! [6]
QSerialPort serial;                    //创建了一个串口类 while (!quit) {
//![6] //! [7]
if (currentPortNameChanged) {            //如果改了名字
serial.close();
serial.setPortName(currentPortName);      //重新打开 if (!serial.open(QIODevice::ReadWrite)) {        //判断是否打开成功
emit error(tr("Can't open %1, error code %2")
.arg(portName).arg(serial.error()));
return;
}
}
//! [7] //! [8]
// write request
QByteArray requestData = currentRequest.toLocal8Bit();      //请求的消息转成byte格式
serial.write(requestData);                      //发送数据
if (serial.waitForBytesWritten(waitTimeout)) {           //等待waitTimeout时间发送数据
//! [8] //! [10]
// read response
if (serial.waitForReadyRead(currentWaitTimeout)) {      //等待waitTimeout时间读取串口数据
QByteArray responseData = serial.readAll();        //将读取数据写到responseData中
while (serial.waitForReadyRead())             //再等10秒
responseData += serial.readAll();            //写进responseData中 QString response(responseData);               //这里又转成QString类型了
//! [12]
emit this->response(response);               //发送response信号
//! [10] //! [11] //! [12]
} else {
emit timeout(tr("Wait read response timeout %1")
.arg(QTime::currentTime().toString())); //发送响应延时信号
}
//! [9] //! [11]
} else {
emit timeout(tr("Wait write request timeout %1")
.arg(QTime::currentTime().toString())); //发送写延时信号
}
//! [9] //! [13]
mutex.lock();
cond.wait(&mutex);                           //这里又等待了?怎么唤醒?第二次按按钮时唤醒,这是一个循环。再次点击又运行一次
if (currentPortName != portName) {
currentPortName = portName;
currentPortNameChanged = true;
} else {
currentPortNameChanged = false;
}
currentWaitTimeout = waitTimeout;
currentRequest = request;
mutex.unlock();
}
//! [13]
}

QT blockingmaster例子学习的更多相关文章

  1. qt下面例子学习(部分功能)

    from aa import Ui_Formfrom PyQt4.Qt import *from PyQt4.QtCore import *from PyQt4.QtGui import *from ...

  2. (转)Qt Model/View 学习笔记 (七)——Delegate类

    Qt Model/View 学习笔记 (七) Delegate  类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...

  3. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  4. Qt 智能指针学习(7种指针)

    Qt 智能指针学习 转载自:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ ...

  5. 数百个 HTML5 例子学习 HT 图形组件 – 3D建模篇

    http://www.hightopo.com/demo/pipeline/index.html <数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇>里提到 HT 很 ...

  6. 数百个 HTML5 例子学习 HT 图形组件 – 3D 建模篇

    http://www.hightopo.com/demo/pipeline/index.html <数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇>里提到 HT 很 ...

  7. 数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇

    <数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇>一文让读者了解了 HT的 2D 拓扑图组件使用,本文将对 HT 的 3D 功能做个综合性的介绍,以便初学者可快速上手使用 HT ...

  8. 数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇

    HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心目中的产品方向,接着就朝这个方向慢慢打 ...

  9. HTML5 例子学习 HT 图形组件

    HTML5 例子学习 HT 图形组件 HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心 ...

随机推荐

  1. 4412 GPIO读 和 ioremap控制GPIO寄存器

    一.配置GPIO读 在视频14的基础上做 1.利用拨码开关来实现GPIO输入 所以AP_SLEEP对应GPC0_3,然后在drivers/gpio/gpio-exynos4.c中对应EXYNOS4_G ...

  2. mongodbdriver 的C# 驱动findasync变成列表的方法

    IAsyncCursorExtensions.ToList(返回的Task<IAsyncCursor<T>>实例). 也有他的异步版本.可以参见 https://mongodb ...

  3. Shiro那些事儿(一): Shiro初探

    引言 权限,可以简单的理解成你能干什么,不能干什么.在管理系统中,对权限的设计可以很简单,也可以很复杂.简单点的,基本都是基于角色扮演的方式,比如系统管理员角色可以操作哪些菜单,普通用户角色可以操作哪 ...

  4. Zlib not installed

    若提示:zlib not installed   wget http://zlib.net/zlib-1.2.8.tar.gz   tar zxf zlib-1.2.8.tar.gz cd zlib- ...

  5. (转)关于SimpleDateFormat安全的时间格式化线程安全问题

    想必大家对SimpleDateFormat并不陌生.SimpleDateFormat 是 Java 中一个非常常用的类,该类用来对日期字符串进行解析和格式化输出,但如果使用不小心会导致非常微妙和难以调 ...

  6. C# 获取微信小程序access_token

    /// <summary> /// 获取access_token /// </summary> /// <returns></returns> publ ...

  7. FileInputStream_FileOutputStream

    Writer的基本方法 //向输出流中写入一个字符数据,该字节数据为参数b的低16位 void write(int c) throws IOException //将一个字符类型的数组中的数据写入输出 ...

  8. Springboot02-配置文件

    配置文件读取 springboot中的配置文件都放在application.properties中,其中而k-v属性可以通过@Value("${属性名}")直接获取 @Compon ...

  9. mybatis小技巧

    本节主要讲解mybatis如下五个方面的内容: foreach 批量插入 模糊查询like的写法 #{}和${}的区别 解决实体类中的属性名和表中的字段名不一致问题 由于每次建立工程比较复杂,可以参考 ...

  10. golang的数据类型之布尔类型

    1)布尔类型也叫 bool类型,bool类型数据只允许取值true或false2)bool类型占1个字节.3)bool类型适于逻辑运算,一般用于程序流程控制4)不可以0或非0的整数替代false和tr ...