您的位置:首页 > 编程语言 > Qt开发

[置顶] 基于QT:温度串口图像显示

2016-08-18 10:07 555 查看
用Qt自己写一个上位机,将串口发过来的温度信息,显示出来,并且绘画出温度曲线

上图:



采用QT绘画曲线,首先当然是采用,qwt控件,而Qt没有自带的qwt控件,所以需要按住移植qwt控件方法具体步骤如下:

1. Download and install QT 5.0.1 (MinGw) to: “C:\Qt\Qt5.0.1”

2. Download and extract Qwt 6.1 RC3 to: “C:\qwt-6.1-rc3”

3. Add “C:\Qt\Qt5.0.1\5.0.1\mingw47_32\bin” to your systems path variable (qmake.exe is located here)

4. Add “C:\Qt\Qt5.0.1\Tools\MinGW\bin” to your systems path variable (mingw32-make.exe is located here)

5. Open a command line (cmd) and navigate to: “C:\qwt-6.1-rc3”

6. Type: “qmake” (This command won’t prompt any msg so don’t worry)

7. Type: “mingw32-make” (Compiles the whole project with examples; this will take a while so be patient)

8. Type: “mingw32-make install” (This installs qwt to the directory set in “C:\qwt-6.1-rc3\qwtconfig.pri”; the default location is “C:/Qwt-QWT_VERSION-rc3” -> “C:\Qwt-6.1.0-rc3\”)

9. Add “C:\Qwt-6.1.0-rc3\lib” to your systems path variable

10. Add a User variable named “QT_PLUGIN_PATH” with the following path “C:\Qwt-6.1.0-rc3\plugins”

11. Add a User variable named “QMAKEFEATURES” with the following path “C:\Qwt-6.1.0-rc3\features”

12. Start Qt Creator

13. Create a new project: File -> New File or Project … -> Applications -> Qt Gui Application -> Choose

14. Name it “Test”

15. Create the project in the following directory: “C:\workspace”

16. Open file “Test.pro”

17. Add “Config += qwt” at the bottom

18. Open the main.c of the project and delete all its content.

19. Paste the following in the main.c (This is the qwt example “simpleplot”):

既如下步骤,当然,中国网站上大多数都是采用直接添加一些LIB到.pro文件中去,个人感觉这种方法不是很好,所以就翻墙看了看:

1.下载并安装QT 5.0.1(MinGW的)到“C:\ Qt的\ Qt5.0.1”

2.下载并解压缩QWT 6.1 RC3到:“C:\ QWT-6.1-RC3”

3.添加“C:\ Qt的\ Qt5.0.1 \ 5.0.1 \ mingw47_32 \ BIN”到你的系统路径变量(qmake.exe就设在这里)

4.添加“C:\ Qt的\ Qt5.0.1 \ TOOLS \ MinGW的\ BIN”到你的系统路径变量(的mingw32-的make.exe就设在这里)

5.打开命令行(CMD)并导航到:“C:\ QWT-6.1-RC3”

6.键入:“qmake”(该命令将不会提示任何MSG所以不用担心)

7.键入“mingw32-make”(编译举例整个项目,这将需要一段时间,所以要耐心等待)

8.键入:“mingw32-make install”(这将安装QWT在“C:\ QWT-6.1-RC3 \ qwtconfig.pri”设置的目录;默认位置是“C:/ QWT - $$ QWT_VERSION-RC3” - >“C:\ QWT-6.1.0-RC3 \”)

9.添加“C:\ QWT-6.1.0-RC3 \ LIB”你的系统路径变量

10.添加一个名为“QT_PLUGIN_PATH”用户变量具有以下路径:“C:\Qwt-6.1.0-rc3\plugins”

11.添加一个名为“QMAKEFEATURES”用户变量具有以下路径:“C:\Qwt-6.1.0-rc3\features”

12.启动Qt Creator的

13.创建一个新的项目:文件 - >新建文件或项目… - >应用程序 - > Qt的GUI应用程序 - >选择

14.将它命名为“测试”

15.在以下目录中创建项目:“C:\workspace”

16.打开文件“Test.pro”

17.添加“CONFIG += qwt”在底部

18.打开项目的main.c中并删除其所有内容。

19.粘贴在main.c中以下(这是QWT榜样“simpleplot”):

这样就能够在ui界面编辑中找到QwtWidgets包含的控件类了。当然打开ui是要选择以QT designed 才能够找到这些控件,如下图:





接着就是设计好ui界面了,如上图所示的界面,

添加源代码:

.pro文件

QT       += core gui
CONFIG += qwt
QT       +=serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = temperature
TEMPLATE = app

SOURCES += main.cpp\
mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui


.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include <QTimer>

#include <QDebug>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

#include <qwt_plot_curve.h>
#include <qwt_legend.h>
#include <qwt_plot_item.h>
#include <qwt_legend_data.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_picker.h>
#include <qwt_plot_magnifier.h>
#include <qwt_picker_machine.h>
#include <qwt_plot_zoomer.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
//    void timerEvent(QTimerEvent *);
~MainWindow();
private slots:
void legendChecked(const QVariant &itemInfo,bool on);
void OpenButtonClicked();
void closeButtonClicked();
void Read_Data();
void clearButtonClicked();
void timeoutslot();
private:
Ui::MainWindow *ui;
QSerialPort *serial;
//    QVector<double> xs;
//    QVector<double> ys;
};

#endif // MAINWINDOW_H


.cpp文件

#include "mainwindow.h"
#include "ui_mainwindow.h"

QwtPlotCurve *curve = new QwtPlotCurve("temperature");
//定义一个QWtPlotCurve类的对象,curve  用来绘画曲线
//右边图例初始化,名字为“temperature”

//X轴
double time[20] = {};
//Y轴
double val[20] ={};
int time_count;

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//    ui->temperplot->resize(640,400);
setWindowFlags(Qt::WindowCloseButtonHint);//只显示一个关闭按钮
//固定界面大小不可改变
setMaximumSize(this->width(),this->height());
setMinimumSize(this->width(),this->height());
//设置图像显示标题
ui->temperplot->setTitle("温度实时波形");
//设置坐标轴名称
ui->temperplot->setAxisTitle(QwtPlot::xBottom,"time   s");
ui->temperplot->setAxisTitle(QwtPlot::yLeft,"temperature  ℃");

//    //设置坐标轴的范围
//    ui->temperplot->setAxisScale(QwtPlot::yLeft,0,50);
//    ui->temperplot->setAxisScale(QwtPlot::xBottom,0,5);
//改变绘图区域的背景,canvas 表示画布
ui->temperplot->canvas()->setPalette(QPalette(QColor(Qt::white)));
//    //使用滚轮放大缩小
//    (void) new QwtPlotMagnifier(ui->temperplot->canvas());
//    (void) new QwtPlotPanner(ui->temperplot->canvas());

(new QwtPlotPanner(ui->temperplot->canvas()))->setMouseButton(Qt::RightButton);
(new QwtPlotMagnifier(ui->temperplot->canvas()))->setAxisEnabled(QwtPlot::yLeft,false);
//y轴在放大的时候,坐标不变化

QwtPlotZoomer* zoomer = new QwtPlotZoomer(ui->temperplot->canvas());
zoomer->setRubberBandPen(QColor(Qt::black));
zoomer->setTrackerPen(QColor(Qt::black));
zoomer->setMousePattern(QwtEventPattern::MouseSelect2,Qt::RightButton,Qt::ControlModifier);
zoomer->setMousePattern(QwtEventPattern::MouseSelect3,Qt::RightButton);
//实现鼠标左键选择区域放大:(右键还原)功能。

//定义一个选择器,(十字架),以xBottom 和yLeft为坐标显示
QwtPlotPicker *picker;
picker = new QwtPlotPicker(QwtPlot::xBottom,QwtPlot::yLeft,QwtPlotPicker::CrossRubberBand,QwtPicker::AlwaysOn,ui->temperplot->canvas());
picker->setStateMachine(new QwtPickerDragPointMachine());//拖拽点起作用
picker->setRubberBandPen(QPen(QColor(Qt::white)));//拖拽点颜色
picker->setTrackerPen(QColor(Qt::blue));//跟踪器 显示对应坐标的颜色

QwtLegend *legend = new QwtLegend;//legend(图例)
legend->setDefaultItemMode(QwtLegendData::Checkable);//图例可选择
ui->temperplot->insertLegend(legend,QwtPlot::RightLegend);//图例插入到plot绘画中。

QwtPlotGrid *grid = new QwtPlotGrid;//grid 格子,网格
grid->enableXMin(true);
grid->setMajorPen(QPen(Qt::red, 0, Qt::DotLine));//大格子
grid->setMinorPen(QPen(Qt::red, 0 , Qt::DotLine));//大格子里的小格子
grid->attach(ui->temperplot);//加载到plot中

setAutoFillBackground(true);//自动填充背景颜色
curve->setPen(QPen(Qt::red));
curve->setSamples(time,val,20);//加载数据,也可以使用setData
//    curve->setSamples(xs,ys);
curve->setCurveAttribute(QwtPlotCurve::Fitted,true);//是曲线更圆滑
curve->attach(ui->temperplot);//加载到plot绘画上

//连接槽,处理对应事件
connect(legend,SIGNAL(checked(const QVariant &,bool,int)),this,SLOT(legendChecked(const QVariant &,bool)));

/*串口部分*/
/*查找可用串口,调用foreach 串口信息保存在info 中*/
foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
qDebug() <<"Name   :" <<info.portName();
qDebug() <<"Description" <<info.description();
qDebug() <<"Manufacturer"<<info.manufacturer();

QSerialPort serial;
serial.setPort(info);//设置串口端口
if(serial.open(QIODevice::ReadWrite))//可读可写方式打开串口
{
ui->portBox->addItem(serial.portName());//将检测到的串口信息放到Box中显示
serial.close();
}
}
ui->closeButton->setEnabled(false);//关闭按钮不可用
ui->clearButtom->setEnabled(false);//清空数据按钮不可以
qDebug() <<tr("界面设定成功");
connect(ui->openButton,SIGNAL(clicked()),this,SLOT(OpenButtonClicked()));
connect(ui->closeButton,SIGNAL(clicked()),this,SLOT(closeButtonClicked()));
connect(ui->clearButtom,SIGNAL(clicked()),this,SLOT(clearButtonClicked()));
}

MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::legendChecked(const QVariant &itemInfo,bool on)
{
//获得曲线
QwtPlotItem *plotItem = ui->temperplot->infoToItem(itemInfo);
if(plotItem)
{
plotItem->setVisible(on);
}
ui->temperplot->replot();//重新加载曲线
}

//打开串口槽函数
void MainWindow::OpenButtonClicked()
{

if(ui->portBox->currentText() == NULL)
{
QMessageBox::information(this,"Error Message","Open port Error");
}
else
{
ui->openButton->setEnabled(false);
ui->clearButtom->setEnabled(true);
ui->closeButton->setEnabled(true);//使能关闭串口
//设置各个组合框不可用
ui->portBox->setEnabled(false);
ui->dataBox->setEnabled(false);
ui->checkBox->setEnabled(false);
ui->stopBox->setEnabled(false);
ui->baudrateBox->setEnabled(false);

serial = new QSerialPort;

//设置端口名com x; 这两句的顺序不能够变,否则会出错。
serial->setPortName(ui->portBox->currentText());
//打开串口
serial->open(QIODevice::ReadWrite);
//设置波特率
//       serial->setBaudRate(ui->baudrateBox->currentText().toInt());
if(ui->baudrateBox->currentText()==tr("9600")) //根据组合框内容对串口进行设置
serial->setBaudRate(QSerialPort::Baud9600);
else if(ui->baudrateBox->currentText()==tr("115200"))
serial->setBaudRate(QSerialPort::Baud115200);
//设置数据位
switch(ui->dataBox->currentIndex())
{
case 8:serial->setDataBits(QSerialPort::Data8);
break;
case 7:serial->setDataBits(QSerialPort::Data7);
break;
default :
break;
}
//设置校验位
switch (ui->checkBox->currentIndex())
{
case 0:serial->setParity(QSerialPort::NoParity);
break;
default:
break;
}
//设置停止位
switch (ui->stopBox->currentIndex())
{
case 1:serial->setStopBits(QSerialPort::OneStop);
break;
default:
break;
}
//设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);
//连接槽函数,当串口有数据到来时,回调函数。
connect(serial,SIGNAL(readyRead()),this,SLOT(Read_Data()));

QTimer *timer_clock = new QTimer(this);
connect(timer_clock,SIGNAL(timeout()),this,SLOT(timeoutslot()));
timer_clock->start(100);//200ms

}
}

void MainWindow::closeButtonClicked()
{
ui->openButton->setEnabled(true);
ui->closeButton->setEnabled(false);
ui->clearButtom->setEnabled(false);

//设置各个组合框可以
ui->portBox->setEnabled(true);
ui->dataBox->setEnabled(true);
ui->checkBox->setEnabled(true);
ui->stopBox->setEnabled(true);
ui->baudrateBox->setEnabled(true);

serial->clear();
serial->close();
serial->deleteLater();

}

void MainWindow::Read_Data()//进去这个函数是,只要串口中有数据,就会进入这个函数。
{
QByteArray buf;//QByteArray 类是定义一个字节数组(char *),
buf = serial->readAll();//读取串口所有的数据给变量buf
if(buf != NULL)
{
QString str = ui->receiveEdit->toPlainText();//获取TextEdit的内容

for (int i = 0; i < 19; i++)
{
val[i] = val[i+1];
}
//最后一位为新数据
val[19] =buf.toDouble();
curve->setSamples(time,  val, 20);//重新加载数据
//        ys.append(buf.toDouble());
//        curve->setSamples(xs,ys);
ui->temperplot->replot(); //QwtPlot重绘,重要,没有这句不起作用

str = tr(buf);//将接收区之前的数据+串口缓冲区的数据
QString str1,str2;
str1 = str+tr("℃ ");
str2 = QString::number(time_count*100);//int --> Qstring
str1 += str2+tr("ms");
//   ui->receiveEdit->clear();
ui->receiveEdit->append(str1);//把文本str添加到文本编辑的结尾
}
buf.clear();
}

void MainWindow::clearButtonClicked()
{
ui->receiveEdit->clear();
memset(time,0,20);
memset(val,0,20);
time_count = 0;
}

//定时100ms一到,回调这个函数
void MainWindow::timeoutslot()
{
time_count++;
for(int i = 0;i < 19;i++)
{
time[i]=time[i+1];
}
time[19] = time_count;
}


版权所有,转发请注明出处:

http://blog.csdn.net/qq_33559992/article/details/52238116
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: