1 Star 0 Fork 122

alen_wp/QtSerialPortPlotter

forked from 觉皇/QtSerialPortPlotter 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
mainwindow.cpp 29.85 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
/***************************************************************************
** This file is part of Serial Port Plotter **
** **
** **
** Serial Port Plotter is a program for plotting integer data from **
** serial port using Qt and QCustomPlot **
** **
** This program is free software: you can redistribute it and/or modify **
** it under the terms of the GNU General Public License as published by **
** the Free Software Foundation, either version 3 of the License, or **
** (at your option) any later version. **
** **
** This program is distributed in the hope that it will be useful, **
** but WITHOUT ANY WARRANTY; without even the implied warranty of **
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
** GNU General Public License for more details. **
** **
** You should have received a copy of the GNU General Public License **
** along with this program. If not, see http://www.gnu.org/licenses/. **
** **
****************************************************************************
** Author: Borislav **
** Contact: [email protected] **
** Date: 29.12.14 **
****************************************************************************/
#include "mainwindow.hpp"
#include "ui_mainwindow.h"
#include <x86intrin.h>
MainWindow::MainWindow (QWidget *parent) :
QMainWindow (parent),
ui (new Ui::MainWindow)
{
ui->setupUi (this);
createUI();
setupPlot();
serialPort = new QSerialPort(this);
connect (serialPort, SIGNAL(readyRead()), this, SLOT(readData()));
connect (this, SIGNAL(newData(QStringList)), this, SLOT(onNewDataArrived(QStringList)));
connect (this, SIGNAL(newData(QStringList)), this, SLOT(saveStream(QStringList)));
connect(ui->textBrowser, &QTextEdit::textChanged, this, [=](){
ui->textBrowser->moveCursor(QTextCursor::End);
});
connect(ui->hideRecvAreaCheckBox, &QCheckBox::stateChanged, this, [=](int state){
if(state == Qt::Checked)
{
ui->textBrowser->setVisible(false);
}else
{
ui->textBrowser->setVisible(true);
}
});
// connect(ui->hideRecvDataCheckBox, &QCheckBox::stateChanged, this, [=](int state){
// if(state == Qt::Checked)
// {
// ui->hideRecvAreaCheckBox->setChecked(true);
// ui->hideRecvAreaCheckBox->setVisible(false);
// ui->dataFormatCheckBox->setVisible(false);
// }else
// {
// ui->hideRecvAreaCheckBox->setChecked(false);
// ui->hideRecvAreaCheckBox->setVisible(true);
// ui->dataFormatCheckBox->setVisible(true);
// }
// });
}
MainWindow::~MainWindow()
{
on_actionDisconnect_triggered();
delete ui;
}
void MainWindow::closeEvent(QCloseEvent* e)
{
Settings::setPortName(ui->comboPort->currentText());
Settings::setBaudrate(ui->comboBaud->currentText().toInt());
Settings::setDatabits(ui->comboData->currentIndex());
Settings::setStopbits(ui->comboStop->currentIndex());
Settings::setParity(ui->comboParity->currentIndex());
Settings::setTheme(Settings::getTheme());
Settings::setLineColors(Settings::getLineColors());
Settings::setHideRecvArea(ui->hideRecvAreaCheckBox->isChecked());
Settings::setHideRecvData(ui->hideRecvDataCheckBox->isChecked());
Settings::setDisplayRawData(ui->dataFormatCheckBox->isChecked());
Settings::setWindowPos(pos());
Settings::setWindowSize(size());
QList<int> l;
l.append(ui->spinPoints->value());
l.append(ui->spinYStep->value());
l.append(ui->spinAxesMin->value());
l.append(ui->spinAxesMax->value());
Settings::setPlotArgs(l);
QWidget::closeEvent(e);
}
void MainWindow::createUI()
{
for (QSerialPortInfo port : QSerialPortInfo::availablePorts())
{
ui->comboPort->addItem (port.portName());
}
/* Populate baud rate combo box with standard rates */
ui->comboBaud->addItem ("1200");
ui->comboBaud->addItem ("2400");
ui->comboBaud->addItem ("4800");
ui->comboBaud->addItem ("9600");
ui->comboBaud->addItem ("19200");
ui->comboBaud->addItem ("38400");
ui->comboBaud->addItem ("57600");
ui->comboBaud->addItem ("115200");
/* And some not-so-standard */
ui->comboBaud->addItem ("128000");
ui->comboBaud->addItem ("153600");
ui->comboBaud->addItem ("230400");
ui->comboBaud->addItem ("256000");
ui->comboBaud->addItem ("460800");
ui->comboBaud->addItem ("921600");
/* Populate data bits combo box */
ui->comboData->addItem (tr("8位"));
ui->comboData->addItem (tr("7位"));
/* Populate parity combo box */
ui->comboParity->addItem (tr("无校验"));
ui->comboParity->addItem (tr("奇校验"));
ui->comboParity->addItem (tr("偶校验"));
/* Populate stop bits combo box */
ui->comboStop->addItem (tr("1位"));
ui->comboStop->addItem (tr("2位"));
/* Initialize the listwidget */
ui->listWidget_Channels->clear();
ui->comboPort->installEventFilter(this);
ui->textBrowser->document()->setMaximumBlockCount(1000); /* 设置最大显示1000行 */
ui->comboPort->setCurrentIndex(ui->comboPort->findText(Settings::getPortName()));
ui->comboBaud->setCurrentText(QString("%1").arg(Settings::getBaudrate()));
ui->comboData->setCurrentIndex(Settings::getDatabits());
ui->comboStop->setCurrentIndex(Settings::getStopbits());
ui->comboParity->setCurrentIndex(Settings::getParity());
ui->hideRecvAreaCheckBox->setChecked(Settings::hideRecvArea());
ui->hideRecvDataCheckBox->setChecked(Settings::hideRecvData());
ui->dataFormatCheckBox->setChecked(Settings::displayRawData());
lineColorNamesStrList = Settings::getLineNames();
if(ui->hideRecvAreaCheckBox->isChecked())
{
ui->textBrowser->setVisible(false);
}
QList<int> l = Settings::plotArgs();
ui->spinPoints->setValue(l[0]);
ui->spinYStep->setValue(l[1]);
ui->spinAxesMin->setValue(l[2]);
ui->spinAxesMax->setValue(l[3]);
enable_com_controls(true);
resize(Settings::windowSize());
move(Settings::windowPos());
}
void MainWindow::setupPlot()
{
foreach(QString color, Settings::getLineColors())
{
lineColorsList.append(QColor(color));
}
if(Settings::getTheme() == 0)
{
gui_colors[0] = QColor (255, 255, 255, 255); /**< 0: qdark ui dark/background color */
gui_colors[1] = QColor (175, 175, 175, 255); /**< 0: qdark ui dark/background color */
gui_colors[2] = QColor (85, 85, 85, 255); /**< 0: qdark ui dark/background color */
gui_colors[3] = QColor (207, 208, 208, 200); /**< 0: qdark ui dark/background color */
}else
{
gui_colors[0] = QColor (48, 47, 47, 255); /**< 0: qdark ui dark/background color */
gui_colors[1] = QColor (80, 80, 80, 255); /**< 1: qdark ui medium/grid color */
gui_colors[2] = QColor (170, 170, 170, 255); /**< 2: qdark ui light/text color */
gui_colors[3] = QColor (48, 47, 47, 200); /**< 3: qdark ui dark/background color w/transparency */
}
/* Background for the plot area */
ui->plot->setBackground (gui_colors[0]);
/* Used for higher performance (see QCustomPlot real time example) */
ui->plot->setNotAntialiasedElements (QCP::aeAll);
QFont font;
font.setStyleStrategy (QFont::NoAntialias);
ui->plot->legend->setFont (font);
/** See QCustomPlot examples / styled demo **/
/* X Axis: Style */
ui->plot->xAxis->grid()->setPen (QPen(gui_colors[2], 1, Qt::DotLine));
ui->plot->xAxis->grid()->setSubGridPen (QPen(gui_colors[1], 1, Qt::DotLine));
ui->plot->xAxis->grid()->setSubGridVisible (true);
ui->plot->xAxis->setBasePen (QPen (gui_colors[2]));
ui->plot->xAxis->setTickPen (QPen (gui_colors[2]));
ui->plot->xAxis->setSubTickPen (QPen (gui_colors[2]));
ui->plot->xAxis->setUpperEnding (QCPLineEnding::esSpikeArrow);
ui->plot->xAxis->setTickLabelColor (gui_colors[2]);
ui->plot->xAxis->setTickLabelFont (font);
/* Range */
ui->plot->xAxis->setRange (dataPointNumber - ui->spinPoints->value(), dataPointNumber);
/* Y Axis */
ui->plot->yAxis->grid()->setPen (QPen(gui_colors[2], 1, Qt::DotLine));
ui->plot->yAxis->grid()->setSubGridPen (QPen(gui_colors[1], 1, Qt::DotLine));
ui->plot->yAxis->grid()->setSubGridVisible (true);
ui->plot->yAxis->setBasePen (QPen (gui_colors[2]));
ui->plot->yAxis->setTickPen (QPen (gui_colors[2]));
ui->plot->yAxis->setSubTickPen (QPen (gui_colors[2]));
ui->plot->yAxis->setUpperEnding (QCPLineEnding::esSpikeArrow);
ui->plot->yAxis->setTickLabelColor (gui_colors[2]);
ui->plot->yAxis->setTickLabelFont (font);
/* Range */
ui->plot->yAxis->setRange (ui->spinAxesMin->value(), ui->spinAxesMax->value());
/* User can change Y axis tick step with a spin box */
//ui->plot->yAxis->setAutoTickStep (false);
ui->plot->yAxis->ticker()->setTickCount(ui->spinYStep->value());
/* User interactions Drag and Zoom are allowed only on X axis, Y is fixed manually by UI control */
ui->plot->setInteraction (QCP::iRangeDrag, true);
//ui->plot->setInteraction (QCP::iRangeZoom, true);
ui->plot->setInteraction (QCP::iSelectPlottables, true);
ui->plot->setInteraction (QCP::iSelectLegend, true);
ui->plot->axisRect()->setRangeDrag (Qt::Horizontal);
ui->plot->axisRect()->setRangeZoom (Qt::Horizontal);
/* Legend */
QFont legendFont;
legendFont.setPointSize(9);
ui->plot->legend->setVisible (true);
ui->plot->legend->setFont (legendFont);
ui->plot->legend->setBrush (gui_colors[3]);
ui->plot->legend->setBorderPen (gui_colors[2]);
/* By default, the legend is in the inset layout of the main axis rect. So this is how we access it to change legend placement */
ui->plot->axisRect()->insetLayout()->setInsetAlignment (0, Qt::AlignTop|Qt::AlignRight);
ui->plot->replot();
connect (ui->plot, SIGNAL(mouseWheel (QWheelEvent*)), this, SLOT (onMouseWheelInPlot(QWheelEvent*)));
connect (ui->plot, SIGNAL(mouseMove (QMouseEvent*)), this, SLOT (onMouseMoveInPlot (QMouseEvent*)));
connect (ui->plot, SIGNAL(selectionChangedByUser()), this, SLOT(channel_selection()));
//connect (ui->plot, SIGNAL(legendDoubleClick (QCPLegend*, QCPAbstractLegendItem*, QMouseEvent*)), this, SLOT(legend_double_click (QCPLegend*, QCPAbstractLegendItem*, QMouseEvent*)));
connect (&updateTimer, SIGNAL (timeout()), this, SLOT (replot()));
}
void MainWindow::enable_com_controls (bool enable)
{
ui->comboBaud->setEnabled (enable);
ui->comboData->setEnabled (enable);
ui->comboParity->setEnabled (enable);
ui->comboPort->setEnabled (enable);
ui->comboStop->setEnabled (enable);
ui->actionConnect->setEnabled (enable);
ui->actionPause_Plot->setEnabled (!enable);
ui->actionDisconnect->setEnabled (!enable);
// ui->actionRecord_stream->setEnabled(enable);
ui->actionHow_to_use->setEnabled(enable);
ui->actionSettings->setEnabled(enable);
}
void MainWindow::on_comboPort_currentIndexChanged (const QString &arg1)
{
QSerialPortInfo selectedPort (arg1); // Dislplay info for selected port
ui->statusBar->showMessage (selectedPort.description());
}
void MainWindow::replot()
{
ui->plot->xAxis->setRange (dataPointNumber - ui->spinPoints->value(), dataPointNumber);
ui->plot->replot();
}
void MainWindow::onNewDataArrived(QStringList newData)
{
static int data_members = 0;
static int channel = 0;
static int i = 0;
volatile bool you_shall_NOT_PASS = false;
/* When a fast baud rate is set (921kbps was the first to starts to bug),
this method is called multiple times (2x in the 921k tests), so a flag
is used to throttle
TO-DO: Separate processes, buffer data (1) and process data (2) */
while (you_shall_NOT_PASS) {}
you_shall_NOT_PASS = true;
if (plotting)
{
/* Get size of received list */
data_members = newData.size();
/* Parse data */
for (i = 0; i < data_members; i++)
{
/* Update number of axes if needed */
while (ui->plot->plottableCount() <= channel)
{
/* Add new channel data */
ui->plot->addGraph();
ui->plot->graph()->setPen (lineColorsList[channels % lineColorsList.size()]);
ui->plot->graph()->setName (lineColorNamesStrList[channels % lineColorNamesStrList.size()]);
if(ui->plot->legend->item(channels))
{
ui->plot->legend->item (channels)->setTextColor (lineColorsList[channels % lineColorsList.size()]);
}
ui->listWidget_Channels->addItem(ui->plot->graph()->name());
ui->listWidget_Channels->item(channel)->setForeground(QBrush(lineColorsList[channels % lineColorsList.size()]));
channels++;
}
/* [TODO] Method selection and plotting */
/* X-Y */
if (0)
{
}
/* Rolling (v1.0.0 compatible) */
else
{
/* Add data to Graph 0 */
ui->plot->graph(channel)->addData (dataPointNumber, newData[channel].toDouble());
/* Increment data number and channel */
channel++;
}
}
/* Post-parsing */
/* X-Y */
if (0)
{
}
/* Rolling (v1.0.0 compatible) */
else
{
dataPointNumber++;
channel = 0;
}
}
you_shall_NOT_PASS = false;
}
void MainWindow::on_spinPoints_valueChanged (int arg1)
{
Q_UNUSED(arg1)
int step = (float)abs(ui->spinPoints->value()) * 0.025f;
if(step == 0)
{
step = 1;
}
ui->spinPoints->setSingleStep(step);
ui->plot->xAxis->setRange (dataPointNumber - ui->spinPoints->value(), dataPointNumber);
ui->plot->replot();
}
void MainWindow::on_spinAxesMin_valueChanged(int arg1)
{
int step = (float)abs(ui->spinAxesMin->value()) * 0.025f;
if(step == 0)
{
step = 1;
}
ui->spinAxesMin->setSingleStep(step);
ui->plot->yAxis->setRangeLower (arg1);
ui->plot->replot();
}
void MainWindow::on_spinAxesMax_valueChanged(int arg1)
{
int step = (float)abs(ui->spinAxesMax->value()) * 0.025f;
if(step == 0)
{
step = 1;
}
ui->spinAxesMax->setSingleStep(step);
ui->plot->yAxis->setRangeUpper (arg1);
ui->plot->replot();
}
void MainWindow::readData()
{
if(serialPort->bytesAvailable()) { // If any bytes are available
QByteArray data = serialPort->readAll(); // Read all data in QByteArray
if(!data.isEmpty()) { // If the byte array is not empty
char *temp = data.data(); // Get a '\0'-terminated char* to the data
if(!ui->hideRecvDataCheckBox->isChecked() && ui->dataFormatCheckBox->isChecked())
{
ui->textBrowser->insertPlainText(QString(data));
}
for(int i = 0; i != data.size(); i++) { // Iterate over the char*
switch(STATE) { // Switch the current state of the message
case WAIT_START: // If waiting for start [$], examine each char
if(temp[i] == START_MSG) { // If the char is $, change STATE to IN_MESSAGE
STATE = IN_MESSAGE;
receivedData.clear(); // Clear temporary QString that holds the message
break; // Break out of the switch
}
break;
case IN_MESSAGE: // If state is IN_MESSAGE
if(temp[i] == END_MSG) { // If char examined is ;, switch state to END_MSG
STATE = WAIT_START;
QStringList incomingData = receivedData.split(' '); // Split string received from port and put it into list
if(!ui->hideRecvDataCheckBox->isChecked() && !ui->dataFormatCheckBox->isChecked())
{
ui->textBrowser->append(receivedData);
}
emit newData(incomingData); // Emit signal for data received with the list
receivedData.clear();
break;
}
else if (isdigit (temp[i]) || isspace (temp[i]) || temp[i] =='-' || temp[i] =='.')
{
/* If examined char is a digit, and not '$' or ';', append it to temporary string */
receivedData.append(temp[i]);
}
break;
default: break;
}
}
}
}
}
void MainWindow::on_spinYStep_valueChanged(int arg1)
{
ui->plot->yAxis->ticker()->setTickCount(arg1);
ui->plot->replot();
ui->spinYStep->setValue(ui->plot->yAxis->ticker()->tickCount());
}
void MainWindow::on_savePNGButton_clicked()
{
ui->plot->savePng(QDateTime::currentDateTime().toString("yyyy-MM-d-HH-mm-ss-") + QString("snapshot.png"), 1920, 1080, 2, 50);
}
void MainWindow::onMouseMoveInPlot(QMouseEvent *event)
{
int xx = int(ui->plot->xAxis->pixelToCoord(event->x()));
int yy = int(ui->plot->yAxis->pixelToCoord(event->y()));
QString coordinates("X: %1 Y: %2");
coordinates = coordinates.arg(xx).arg(yy);
ui->statusBar->showMessage(coordinates);
}
void MainWindow::onMouseWheelInPlot(QWheelEvent *event)
{
QWheelEvent inverted_event = QWheelEvent(event->posF(), event->globalPosF(),
-event->pixelDelta(), -event->angleDelta(),
0, Qt::Vertical, event->buttons(), event->modifiers());
QApplication::sendEvent (ui->spinPoints, &inverted_event);
}
void MainWindow::channel_selection (void)
{
/* synchronize selection of graphs with selection of corresponding legend items */
for (int i = 0; i < ui->plot->graphCount(); i++)
{
QCPGraph *graph = ui->plot->graph(i);
QCPPlottableLegendItem *item = ui->plot->legend->itemWithPlottable (graph);
if (item->selected())
{
item->setSelected (true);
// graph->set (true);
}
else
{
item->setSelected (false);
// graph->setSelected (false);
}
}
}
void MainWindow::legend_double_click(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event)
{
Q_UNUSED (legend)
Q_UNUSED(event)
/* Only react if item was clicked (user could have clicked on border padding of legend where there is no item, then item is 0) */
if (item)
{
QCPPlottableLegendItem *plItem = qobject_cast<QCPPlottableLegendItem*>(item);
bool ok;
QString newName = QInputDialog::getText (this, tr("设置通道名称"), tr("名称:"), QLineEdit::Normal, plItem->plottable()->name(), &ok, Qt::FramelessWindowHint);
if (ok)
{
plItem->plottable()->setName(newName);
for(int i=0; i<ui->plot->graphCount(); i++)
{
ui->listWidget_Channels->item(i)->setText(ui->plot->graph(i)->name());
}
ui->plot->replot();
}
}
}
void MainWindow::on_actionHow_to_use_triggered()
{
HelpWindow *helpWindow = new HelpWindow (nullptr);
helpWindow->setAttribute(Qt::WA_DeleteOnClose);
helpWindow->setModal(true);
helpWindow->show();
}
void MainWindow::on_actionConnect_triggered()
{
if (connected)
{
/* Is connected, restart if paused */
if (!plotting)
{
plotting = true;
updateTimer.start(10);
ui->actionConnect->setEnabled (false);
ui->actionPause_Plot->setEnabled (true);
ui->statusBar->showMessage (tr("开始绘制!"));
}
}
else
{
/* If application is not connected, connect */
/* Get parameters from controls first */
QSerialPortInfo portInfo (ui->comboPort->currentText()); // Temporary object, needed to create QSerialPort
int baudRate = ui->comboBaud->currentText().toInt(); // Get baud rate from combo box
int dataBitsIndex = ui->comboData->currentIndex(); // Get index of data bits combo box
int parityIndex = ui->comboParity->currentIndex(); // Get index of parity combo box
int stopBitsIndex = ui->comboStop->currentIndex(); // Get index of stop bits combo box
QSerialPort::DataBits dataBits;
QSerialPort::Parity parity;
QSerialPort::StopBits stopBits;
/* Set data bits according to the selected index */
switch (dataBitsIndex)
{
case 0:
dataBits = QSerialPort::Data8;
break;
default:
dataBits = QSerialPort::Data7;
}
/* Set parity according to the selected index */
switch (parityIndex)
{
case 0:
parity = QSerialPort::NoParity;
break;
case 1:
parity = QSerialPort::OddParity;
break;
default:
parity = QSerialPort::EvenParity;
}
/* Set stop bits according to the selected index */
switch (stopBitsIndex)
{
case 0:
stopBits = QSerialPort::OneStop;
break;
default:
stopBits = QSerialPort::TwoStop;
}
serialPort->close();
serialPort->setPort(portInfo);
serialPort->setBaudRate (baudRate);
serialPort->setParity (parity);
serialPort->setDataBits (dataBits);
serialPort->setStopBits (stopBits);
if (serialPort->open(QIODevice::ReadWrite))
{
serialPort->clear();
serialPort->clearError();
enable_com_controls (false); // Disable controls if port is open
updateTimer.start(10); // Slot is refreshed 20 times per second
connected = true; // Set flags
plotting = true;
ui->statusBar->showMessage (tr("端口打开成功!"));
}
else
{
ui->statusBar->showMessage (tr("打开失败,请检查该端口是否存在或被占用!"));
}
}
}
void MainWindow::on_actionPause_Plot_triggered()
{
if (plotting)
{
updateTimer.stop(); // Stop updating plot timer
plotting = false;
ui->actionConnect->setEnabled (true);
ui->actionPause_Plot->setEnabled (false);
ui->statusBar->showMessage (tr("暂停绘制,新数据将被忽略!"));
}
}
void MainWindow::on_actionRecord_stream_triggered()
{
if(ui->actionRecord_stream->isChecked())
{
openCsvFile();
}else
{
closeCsvFile();
}
}
void MainWindow::on_actionDisconnect_triggered()
{
if (connected)
{
serialPort->close(); // Close serial port
updateTimer.stop();
receivedData.clear(); // Clear received string
connected = false;
plotting = false;
enable_com_controls (true);
ui->statusBar->showMessage (tr("关闭端口!"));
}
}
void MainWindow::on_actionClear_triggered()
{
if(serialPort->isOpen())
{
serialPort->clear();
}
receivedData.clear();
ui->textBrowser->clear();
ui->listWidget_Channels->clear();
channels = 0;
dataPointNumber = 0;
ui->plot->clearPlottables();
ui->plot->replot();
}
void MainWindow::openCsvFile(void)
{
QString path = Settings::lastSavePath();
QString filename = QFileDialog::getSaveFileName(this, QApplication::applicationName(), path, tr("xlsx (*.xlsx)"));
if(filename.isEmpty())
{
ui->actionRecord_stream->setChecked(false);
return;
}
QDir dir;
if(dir.exists(filename))
dir.remove(filename);
QFileInfo finfo = QFileInfo(filename);
xlsxDevice = new QXlsx::Document(filename);
if(!xlsxDevice)
{
ui->actionRecord_stream->setChecked(false);
QMessageBox::critical(this, QApplication::applicationName(), tr("错误:创建%1.%2失败,请重试!").arg(finfo.baseName()).arg(finfo.completeSuffix()), QMessageBox::Close);
return;
}
xlsxRow = 1;
xlsxDevice->write(xlsxRow, 1, tr("时间"));
QStringList titles = Settings::getLineNames();
for(int i = 0; i < titles.size(); i++)
{
xlsxDevice->write(xlsxRow, i + 2, titles[i]);
}
xlsxRow++;
xlsxDevice->save();
Settings::setLastSavePath(finfo.absolutePath());
ui->statusBar->showMessage (tr("保存数据到文件!"));
}
void MainWindow::closeCsvFile(void)
{
if(xlsxDevice)
{
xlsxRow = 1;
xlsxDevice->save();
delete xlsxDevice;
xlsxDevice = nullptr;
ui->statusBar->showMessage (tr("取消保存数据到文件!"));
}
}
void MainWindow::saveStream(QStringList newData)
{
if(xlsxDevice && ui->actionRecord_stream->isChecked())
{
xlsxDevice->write(xlsxRow, 1, QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
for(int i = 0; i < newData.size(); i++)
{
xlsxDevice->write(xlsxRow, i + 2, newData[i]);
}
xlsxRow++;
xlsxDevice->save();
}
}
void MainWindow::on_pushButton_AutoScale_clicked()
{
ui->plot->yAxis->rescale(true);
ui->spinAxesMax->setValue(int(ui->plot->yAxis->range().upper) + int(ui->plot->yAxis->range().upper*0.1));
ui->spinAxesMin->setValue(int(ui->plot->yAxis->range().lower) + int(ui->plot->yAxis->range().lower*0.1));
}
void MainWindow::on_pushButton_ResetVisible_clicked()
{
for(int i=0; i<ui->plot->graphCount(); i++)
{
ui->plot->graph(i)->setVisible(true);
ui->listWidget_Channels->item(i)->setBackground(Qt::NoBrush);
}
}
void MainWindow::on_listWidget_Channels_itemDoubleClicked(QListWidgetItem *item)
{
int graphIdx = ui->listWidget_Channels->currentRow();
if(ui->plot->graph(graphIdx)->visible())
{
ui->plot->graph(graphIdx)->setVisible(false);
QBrush brush = item->background();
if(brush.style() == Qt::NoBrush)
{
brush = ui->listWidget_Channels->palette().window();
}
QColor c = brush.color();
QColor cset = QColor(255 - c.red(), 255 - c.green(), 255 - c.blue(), c.alpha());
item->setBackground(QBrush(cset));
}
else
{
ui->plot->graph(graphIdx)->setVisible(true);
item->setBackground(Qt::NoBrush);
}
ui->plot->replot();
}
void MainWindow::on_pushButton_ClearRecv_clicked()
{
ui->textBrowser->clear();
}
void MainWindow::on_actionSettings_triggered()
{
SettingsDialog* d = new SettingsDialog(nullptr);
// 退出设置自动重启软件
connect(d, &QDialog::accepted, this, [=](){
qApp->closeAllWindows(); //或qApp->quit(),但使用quit不会调用closeEvent
QProcess::startDetached(qApp->applicationFilePath(), QStringList());
});
d->setWindowTitle(tr("设置"));
d->setAttribute(Qt::WA_DeleteOnClose);
d->setModal(true); // 阻塞父窗口
d->show();
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress)
{
if(watched == ui->comboPort)
{
QComboBox* comboBox = qobject_cast<QComboBox *>(watched);
comboBox->clear();
foreach (QSerialPortInfo info, QSerialPortInfo::availablePorts())
{
comboBox->addItem(info.portName());
}
}
}
return QMainWindow::eventFilter(watched, event);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/aarch64/QtSerialPortPlotter.git
[email protected]:aarch64/QtSerialPortPlotter.git
aarch64
QtSerialPortPlotter
QtSerialPortPlotter
main

搜索帮助