/*
函 数:on_Send_Bt_clicked
描 述:发送按键点击信号槽
输 入:无
输 出:无
*/
void Widget::on_Send_Bt_clicked()
{
if (isSerialOpen != false)
{
if (isSendFile)//发送文件数据
{
if (ui->Send_Bt->text() == "发送")
{
ui->Send_Bt->setText("停止");
SendFile();
}
else
{
ui->Send_Bt->setText("发送");
FileSendTimer->stop();
}
}
else//发送发送框数据
{
SerialSendData(SendTextEditBa);
}
}
else
{
QMessageBox::information(this, "提示", "串口未打开");
}
}
/*
函 数:SendData
描 述:定时器发送文件
输 入:无
输 出:无
*/
void Widget::SendFile(void)
{
/*按设置参数发送*/
FrameLen = ui->PackLen_lineEdit->text().toInt(); // 帧大小
FrameGap = ui->GapTim_lineEdit->text().toInt(); // 帧间隔
int textlen = Widget::FileText.size(); // 文件大小
if (FrameGap <= 0 || textlen <= FrameLen)
{
//时间间隔为0 或 帧大小≥文件大小 则直接一次发送
serial->write(FileText.toUtf8());
ui->Send_Bt->setText("发送");
}
else
{
//按设定时间和长度发送
FrameNumber = textlen / FrameLen; // 包数量
LastFrameLen = textlen % FrameLen; // 最后一包数据长度
//进度条步进值
if (FrameNumber >= 100)
{
ProgressBarStep = FrameNumber / 100;
}
else
{
ProgressBarStep = 100 / FrameNumber;
}
//设置定时器
FileSendTimer->start(FrameGap);
}
}
设置一个定时器,将文件按照设定的帧大小和帧间隔来发送:
/*文件帧发送定时器信号槽*/
FileSendTimer = new QTimer(this);
connect(FileSendTimer,SIGNAL(timeout()),this,SLOT(File_TimerSend()));
/*
函 数:File_TimerSend
描 述:发送文件定时器槽函数
输 入:无
输 出:无
*/
void Widget::File_TimerSend(void)
{
if (FrameCount < FrameNumber)
{
serial->write(FileText.mid(FrameCount * FrameLen, FrameLen).toUtf8());
FrameCount++;
//更新进度条
ui->progressBar->setValue(ProgressBarValue += ProgressBarStep);
}
else
{
if (LastFrameLen > 0)
{
serial->write(FileText.mid(FrameCount * FrameLen, LastFrameLen).toUtf8());
ui->progressBar->setValue(100);
}
/*发送完毕*/
FileSendTimer->stop();
FrameCount = 0;
ProgressBarValue = 0;
FrameNumber = 0;
LastFrameLen = 0;
QMessageBox::information(this, "提示", "发送完成");
ui->progressBar->setValue(0);
ui->Send_Bt->setText("发送");
}
}
QString QString::mid(int position, int n = -1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Returns a null string if the position index exceeds the length of the string. If there are less than n characters available in the string starting at the given position, or if n is -1 (default), the function returns all characters that are available from the specified position.
Example:
QString x = "Nine pineapples";
QString y = x.mid(5, 4); // y == "pine"
QString z = x.mid(5); // z == "pineapples"
2.5、数据保存
当保存数据按钮按下时,将接收框数据按文本方式进行保存:
/*
函 数:on_SaveData_Button_clicked
描 述:保存数据按钮点击槽函数
输 入:无
输 出:无
*/
void Widget::on_SaveData_Button_clicked()
{
QString data = ui->Receive_TextEdit->toPlainText();
if (data.isEmpty())
{
QMessageBox::information(this, "提示", "数据内容空");
return;
}
QString curPath = QDir::currentPath(); //获取系统当前目录
QString dlgTitle = "保存文件"; //对话框标题
QString filter = "文本文件(*.txt);;所有文件(*.*)"; //文件过滤器
QString filename = QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
if (filename.isEmpty())
{
return;
}
QFile file(filename);
if (!file.open(QIODevice::WriteOnly))
{
return;
}
/*保存文件*/
QTextStream stream(&file);
stream << data;
file.close();
}
QTextStream::QTextStream(FILE **fileHandle, QIODevice::OpenModeopenMode* = QIODevice::ReadWrite)
Constructs a QTextStream that operates on fileHandle, using openMode to define the open mode. Internally, a QFile is created to handle the FILE pointer.
This constructor is useful for working directly with the common FILE based input and output streams: stdin, stdout and stderr. Example:
QString str;
QTextStream in(stdin);
in >> str;
三、扩展
这里对接收模块的功能进行一个补充。上面说了应用程序默认编码是UTF-8,那么如果在ascii显示模式下收到的数据是GBK格式的编码就会造成显示乱码,所以需要对接收数据进行编码判断,如果是GBK编码则进行转换显示。
/*
函 数:SerialPortReadyRead_slot
描 述:readyRead()信号对应的数据接收槽函数
输 入:无
输 出:无
*/
void Widget::SerialPortReadyRead_slot()
{
/*读取串口收到的数据*/
QByteArray bytedata = serial->readAll();
//......省略
if(ui->HexDisp_checkBox->isChecked() == false) //ascii显示
{
/* 判断编码 */
QTextCodec::ConverterState state;
//调用utf8转unicode的方式转码,获取转换结果
QString asciidata = QTextCodec::codecForName("UTF-8")->toUnicode(bytedata.constData(),bytedata.size(),&state);
//存在无效字符则是GBK,转码后返回
if (state.invalidChars > 0)
{
asciidata = QTextCodec::codecForName("GBK")->toUnicode(bytedata);
}
else
{
asciidata = QString(bytedata);
}
//......省略
}
//......省略
}
四、总结
本章主要讲解对文件的操作。除了需要了解在QT中对文件类的常用操作之外,个人认为还有比较重要的两个知识点:1是文本编码的判断和转码处理,2是对于二进制文本的读取。bk