本文记录自己在使用Qt过程中遇到的坑,有些是自己疏忽或认识不足导致的问题,有些是Qt自身的bug或陷阱。本文旨在总结自己遇到的问题和解决方法。
-----------------------------------------------本文将持续更新,如有帮助请收藏-------------------------------------------
1.关于Qt SerialPort
由于公司性质,做过几个上位机软件,主要通信接口就是串口、蓝牙和网口了。Qt4时代相信大家都是用的第三方QextSerialPort类,但是自Qt5开始Qt SerialPort已作为单独模块加入到Qt库中,可以,这很强势,既然有了官方库我们何必去到处找轮子,于是。。。
(1)Qt串口的信号槽
相信所有的教程介绍Qt串口都是这样开始的:
ui->textEdit_recvSerial->append(QString("检测到端口列表:"));
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if (serial.open(QIODevice::ReadWrite))
{
ui->comboBox_serialport->addItem(info.portName());
ui->textEdit_recvSerial->append(info.portName());
ui->textEdit_recvSerial->append(info.description());
ui->textEdit_recvSerial->append(info.manufacturer());
serial.close();
}
}
if(ui->comboBox_serialport->count()==0)ui->textEdit_recvSerial->append(QString("未检测到串口设备!"));
mSerialport= new QSerialPort();
//接收串口数据并显示
connect(mSerialport,SIGNAL(readyRead()),this,SLOT(readUart()));
//处理串口错误(中途断开连接等错误)
connect(mSerialport, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
this, &BeaconControlCenter::handleSerialError);
可以,我们通过readyRead()信号触发readUart()处理接收到的数据,槽函数里一般比较简单,诸如:
mSerialData=mSerialport->readAll();
或者:
while (!mSerialPort.atEnd()) {
QByteArray data = mSerialPort.read(100);
....
}
//串口接收
void BeaconControlCenter::readUart()
{
serialTimer->start(100);
mSerialRecvData.append(mSerialport->readAll());
}
//超时处理
void BeaconControlCenter::serialTimerUpdate() { serialTimer->stop(); mSerialRecvNum += mSerialRecvData.count(); if(ui->radioButton_recvHex->isChecked()) { ui->textEdit_recvSerial->append(QString(mSerialRecvData.toHex()));//十六进制显示 } else { ui->textEdit_recvSerial->append(QString(mSerialRecvData.data()));//字符模式显示 } ui->label_serialRecvNum->setText(QString::number(mSerialRecvNum)); //存储到BLE数据包缓存队列,每个BLE package为一个QString
//此次换成你所需要的处理,比如我这里根据包长提取每个数据包加入到我的队列 qDebug()<<mSerialRecvData; for(int i=0;i<mSerialRecvData.count();i+=PACK_Length) { QString tempStr=mSerialRecvData.mid(i,i+PACK_Length-1); mSerialBLEpackageQueue->enqueue(tempStr); qDebug()<<mSerialBLEpackageQueue-> back(); } mSerialRecvData.clear(); }
其实接收超时机制在modbus里已有运用,我们使用某种传输协议的时候已经帮我们做好了这些工作,否则我们就要自行处理这些问题。经过处理后,终于可以拆分数据包显示了:
数据包也能正常解析了:
在.pro中加入:QT+=multimedia 头文件中包含QMediaPlayer等类库,就可以开始写一个简单的音视频播放器了。核心代码如下:
playlist = new QMediaPlaylist;
playlist->addMedia(QUrl("http://example.com/movie1.mp4"));
playlist->addMedia(QUrl("http://example.com/movie2.mp4"));
playlist->addMedia(QUrl("http://example.com/movie3.mp4"));
playlist->setCurrentIndex(1);
player = new QMediaPlayer;
player->setPlaylist(playlist);
videoWidget = new QVideoWidget;
player->setVideoOutput(videoWidget);
videoWidget->show();
player->play();
然后当你跃跃一试准备运行的时候发现不能播放视频,原因是QMediaPlayer解码音视频文件底层依赖解码库,在Linux下需要安装gstreamer-ffmpeg;在Windows下需要安装LAV filters。因为 QMediaPlayer依赖于DirectShow服务,所以需要在不同平台下安装对应的底层库。
问题来了:我们发布的程序怎么保证所运行的平台上安装了这些库??
这个真的就是Qt的坑了,不是我们的错。所以在Qt里不会有人直接使用Qt Multimedia,哪怕是个简单的音视频播放,最好采用第三方框架,比如:ffmpeg、VLC、mplayer等。
如果你实在想用,只能在打包发布时将对应平台的依赖库一起打包进去。
-----------------------------------------------------------持续更新中---------------------------------------------------------------