尝试用多线程处理数据时,串口数据传输出现问题
之前在主界面处理串口传输的数据发生界面卡死状态,经过大神指点,可以使用多线程解决问题,最近两天学习了多线程,并尝试编写,但效果不佳。编译倒是没有问题,但运行时出现QIODevice::read (QSerialPort): device not open的情况,添加了OPEN也不行。程序太多,放在附件上了。希望大佬们不吝赐教QAQ既然开辟线程就想多次执行,有可能线程执行一次就退出了,可以添加QEventLoop loop; loop.exec(); 防止线程退出 #ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>
class MyThread : public QObject
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
void read(QByteArray temp);
signals:
void update(QByteArray temp);
};
#endif // MYTHREAD_H
#include "mymainwindow.h"
#include "ui_mymainwindow.h"
MyMainWindow::MyMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MyMainWindow)
{
ui->setupUi(this);
//查找可用的串口
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
ui->PortBox->addItem(serial.portName());
serial.close();
}
}
//设置波特率下拉菜单默认显示第0项
ui->BaudBox->setCurrentIndex(0);
//关闭发送按钮的使能
ui->sendButton->setEnabled(false);
qDebug() << tr("界面设定成功!");
thread = new QThread(this);
myThread = new MyThread;
myThread->moveToThread(thread);
thread->start();
connect(ui->pushButton, &QPushButton::pressed, myThread, &MyThread::drawImage);
connect(this, &MyMainWindow::update, thread, &MyThread::read);
connect(this, &MyMainWindow::destroyed, this, &MyMainWindow::dealClose);
}
void MyMainWindow::Read_Data()
{
QByteArray buf;
buf = serial->readAll();
QDataStream out(&buf,QIODevice::ReadWrite); //将字节数组读入
while(!out.atEnd())
{
qint8 outChar = 0;
out>>outChar; //每字节填充一次,直到结束
QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0'));//十六进制的转换
ui->textEdit->insertPlainText(str.toUpper());//大写
ui->textEdit->insertPlainText(" ");//每发送两个字符后添加一个空格
ui->textEdit->moveCursor(QTextCursor::End);
}
emit update(buf);
}
void MyMainWindow::on_openButton_clicked()
{
if(ui->openButton->text()==tr("打开串口"))
{
serial = new QSerialPort;
//设置串口名
serial->setPortName(ui->PortBox->currentText());
//打开串口
serial->open(QIODevice::ReadWrite);
//设置波特率
serial->setBaudRate(ui->BaudBox->currentText().toInt());
//设置数据位数
switch(ui->BitNumBox->currentIndex())
{
case 8: serial->setDataBits(QSerialPort::Data8); break;
default: break;
}
//设置奇偶校验
switch(ui->ParityBox->currentIndex())
{
case 0: serial->setParity(QSerialPort::NoParity); break;
default: break;
}
//设置停止位
switch(ui->StopBox->currentIndex())
{
case 1: serial->setStopBits(QSerialPort::OneStop); break;
case 2: serial->setStopBits(QSerialPort::TwoStop); break;
default: break;
}
//设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);
//关闭设置菜单使能
ui->PortBox->setEnabled(false);
ui->BaudBox->setEnabled(false);
ui->BitNumBox->setEnabled(false);
ui->ParityBox->setEnabled(false);
ui->StopBox->setEnabled(false);
ui->openButton->setText(tr("关闭串口"));
ui->sendButton->setEnabled(true);
//连接信号槽
QObject::connect(serial, &QSerialPort::readyRead, this, &MyMainWindow::Read_Data);
}
else
{
//关闭串口
serial->clear();
serial->close();
serial->deleteLater();
//恢复设置使能
ui->PortBox->setEnabled(true);
ui->BaudBox->setEnabled(true);
ui->BitNumBox->setEnabled(true);
ui->ParityBox->setEnabled(true);
ui->StopBox->setEnabled(true);
ui->openButton->setText(tr("打开串口"));
ui->sendButton->setEnabled(false);
}
}
void MyMainWindow::dealClose()
{
//退出子线程
thread->quit();
//当子线程结束后,完成相关的资源回收工作
thread->wait();
//因为(作为子线程加载)的类没有指定父对象, 所以在这里手动回收
delete myThread;
}
#include "mythread.h"
#include <QElapsedTimer>
MyThread::MyThread(QObject *parent) : QObject(parent)
{
}
void MyThread::read()
{
QByteArray buf=temp;
QByteArray kjs;
QPalette pal(ui->widget_1->palette());
QPalette pal2(ui->widget_2->palette());
QPalette pal3(ui->widget_3->palette());
QElapsedTimer t;
int i=0;
while(buf.contains("\001"))
{
for(i=0;i<buf.length()/4;i++)
{
//kjs = buf.left(buf.indexOf('#')-1);*/
kjs = buf.left(4);
if(kjs.at(0)==0)//0X00表示停机
{
pal.setColor(QPalette::Background, Qt::yellow); //设置背景黄色
ui->widget_1->setAutoFillBackground(true);
ui->widget_1->setPalette(pal);
ui->widget_1->show();
t.start();
while(t.elapsed()<10000);//停机30秒
{
if(kjs.at(0)==0)
{
pal.setColor(QPalette::Background, Qt::red); //设置背景红色
ui->widget_1->setAutoFillBackground(true);
ui->widget_1->setPalette(pal);
ui->widget_1->show();
}
}
}
else if(kjs.at(0)==1)
{
pal.setColor(QPalette::Background, Qt::green); //设置背景绿色
ui->widget_1->setAutoFillBackground(true);
ui->widget_1->setPalette(pal);
ui->widget_1->show();
}
else
{
pal.setColor(QPalette::Background, Qt::gray); //设置背景灰色
ui->widget_1->setAutoFillBackground(true);
ui->widget_1->setPalette(pal);
ui->widget_1->show();
}
if(kjs.at(1)==0)//0X00表示停机
{
pal2.setColor(QPalette::Background, Qt::yellow); //设置背景黄色
ui->widget_2->setAutoFillBackground(true);
ui->widget_2->setPalette(pal2);
ui->widget_2->show();
t.start();
while(t.elapsed()<10000);//停机30秒
{
if(kjs.at(1)==0)
{
pal2.setColor(QPalette::Background, Qt::red); //设置背景红色
ui->widget_2->setAutoFillBackground(true);
ui->widget_2->setPalette(pal2);
ui->widget_2->show();
}
}
}
else if(kjs.at(1)==1)
{
pal2.setColor(QPalette::Background, Qt::green); //设置背景绿色
ui->widget_2->setAutoFillBackground(true);
ui->widget_2->setPalette(pal2);
ui->widget_2->show();
}
else
{
pal2.setColor(QPalette::Background, Qt::gray); //设置背景灰色
ui->widget_2->setAutoFillBackground(true);
ui->widget_2->setPalette(pal2);
ui->widget_2->show();
}
if(kjs.at(2)==0)//0X00表示停机
{
pal3.setColor(QPalette::Background, Qt::yellow); //设置背景黄色
ui->widget_3->setAutoFillBackground(true);
ui->widget_3->setPalette(pal3);
ui->widget_3->show();
t.start();
while(t.elapsed()<10000);//停机30秒
{
if(kjs.at(2)==0)
{
pal3.setColor(QPalette::Background, Qt::red); //设置背景红色
ui->widget_3->setAutoFillBackground(true);
ui->widget_3->setPalette(pal);
ui->widget_3->show();
}
}
}
else if(kjs.at(2)==1)
{
qDebug() << tr("界面颜色设定成功!");
pal3.setColor(QPalette::Background, Qt::green); //设置背景绿色
ui->widget_3->setAutoFillBackground(true);
ui->widget_3->setPalette(pal3);
ui->widget_3->show();
}
else
{
pal3.setColor(QPalette::Background, Qt::gray); //设置背景灰色
ui->widget_3->setAutoFillBackground(true);
ui->widget_3->setPalette(pal3);
ui->widget_3->show();
}
buf=buf.right(buf.size()-4*i);
}
}
buf.clear();
}
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
#include <QMainWindow>
#include <QThread>
#include <QDebug>
#include <mythread.h>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
namespace Ui {
class MyMainWindow;
}
class MyMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MyMainWindow(QWidget *parent = 0);
~MyMainWindow();
private slots:
void on_clearButton_clicked();
void on_sendButton_clicked();
void on_openButton_clicked();
void Read_Data();
void dealClose();
void on_checkBox_toggled(bool checked);
private:
Ui::MyMainWindow *ui;
QSerialPort *serial;
MyThread *myThread;
QThread *thread;
QByteArray temp;
};
#endif // MYMAINWINDOW_H
以上的程序是我的新改动,把图形界面刷新放在了次线程里,IO数据没出错,但是显示这个错误 error: 'class Ui::MyMainWindow' has no member named 'pushButton'
connect(ui->pushButton, &QPushButton::pressed, myThread, &MyThread::drawImage);
^ 非白不是黑 发表于 2018-11-19 16:13
void MyMainWindow::Read_Data()
{
QByteArray buf;
connect(ui->pushButton, &QPushButton::pressed, myThread, &MyThread::drawImage);这个是我复制错了没有这个~ 思路有点乱,我再去学习一下线程,打扰各位了,不好意思QAQ QT是不能在子线程里面更新界面的,也就是子线程不可以操作UI界面,我记得是这样的 楼主解决了吗?我这两天也在做这个,对线程有点懵:L 没有回答了吗,这个一收一发多线程了解一下 楼主解决了吗?我这两天也在做这个,对线程有点懵
页:
[1]