Qt5编写的一个推力传感器静态性能计算程序
程序员文章站
2022-05-28 11:35:49
...
最近一门课设做推力传感器设计和标定,要用到一个辅助程序,所以就用Qt5写了一个界面的计算程序,也分享上来供大家参考一下思路。
小程序:
数据处理方法在这里:链接:http://pan.baidu.com/s/1jIagziu 密码:9ya5
exe程序在这里:链接:http://pan.baidu.com/s/1c1YqNrq 密码:09gy
使用时,先输入校准点个数K和校准循环次数R,从表格(QTableWidget)输入原始数据,程序计算出一系列统计参数并从输出框输出,在下方绘制校准曲线。
在QPixmap绘图,之后用QLabel加载,也不需要动态更新,没有用paintevent (有没有大神,这样做有问题吗?)
为了方便输出,用了一个二维数组vector<qstringlist>保存计算结果,编写过程可能有些繁琐
头文件:
mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QtWidgets/QWidget>
#include "ui_mainwidget.h"
class mainWidget : public QWidget
{
Q_OBJECT
public:
mainWidget(QWidget *parent = 0);
~mainWidget();
private:
Ui::mainWidgetClass ui;
//私有变量
int K = 0, R = 0;//校准点个数,校准循环次数
//QPixmap pixmap;
//函数
void mainWidget::setHeaders();//设置表头
void mainWidget::print(const std::vector<std::vector<double>>& outputData);
void mainWidget::paintCurve(const std::vector<std::vector<double>>& tableData, const std::vector<std::vector<double>>& outputData);
//槽函数
void mainWidget::on_spinBoxK_valueChanged();
void mainWidget::on_spinBoxR_valueChanged();
void mainWidget::on_buttonClearTable_clicked();
void mainWidget::on_buttonClearTexeEdit_clicked();
void mainWidget::on_buttonCompute_clicked();
};
#endif // MAINWIDGET_H
#ifndef COMPUTE_H
#define COMPUTE_H
#include <vector>
void compute(const std::vector<std::vector<double>>& tableData, std::vector<std::vector<double>>& outputData);
#endif // COMPUTE_H
源文件:
main.cpp
#include "mainwidget.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
mainWidget w;
w.show();
return a.exec();
}
mainwidget.cpp
#include "mainwidget.h"
#include "compute.h"
#include <QPainter>
mainWidget::mainWidget(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
//隔行改变背景色
ui.tableWidget->setAlternatingRowColors(true);
//ui.labelCurve->setScaledContents(true);
//ui.labelCurve->setStyleSheet("QLabel{background:rgb(0,0,0);color:white;}");
//初始化spinbox
K = ui.tableWidget->rowCount();
R = (ui.tableWidget->columnCount() - 1)/ 2;
ui.spinBoxNumK->setValue(K);
ui.spinBoxNumR->setValue(R);
//设置表头
setHeaders();
connect(ui.spinBoxNumK, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &mainWidget::on_spinBoxK_valueChanged);
connect(ui.spinBoxNumR, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &mainWidget::on_spinBoxR_valueChanged);
connect(ui.buttonClearTable, &QPushButton::clicked, this, &mainWidget::on_buttonClearTable_clicked);
connect(ui.buttonClearTextEdit, &QPushButton::clicked, this, &mainWidget::on_buttonClearTexeEdit_clicked);
connect(ui.buttonCompute, &QPushButton::clicked, this, &mainWidget::on_buttonCompute_clicked);
}
mainWidget::~mainWidget()
{
}
void mainWidget::setHeaders()
{
//设置表头
QStringList headers;
headers.append(QString("Xi/kN"));
for (int i = 1; i <= R; i++)
{
headers.append(QString("Yci") + QString("%1/mV").arg(i));
headers.append(QString("Yfi") + QString("%1/mV").arg(i));
}
ui.tableWidget->setHorizontalHeaderLabels(headers);
}
void mainWidget::print(const std::vector<std::vector<double>>& outputData)//输出
{
for (int i = 0; i < K; i++)
{
ui.textEdit->append(QString(QString::fromLocal8Bit("-----------------------")));
ui.textEdit->append(QString(QString::fromLocal8Bit("第%1个校准点:")).arg(i + 1));
ui.textEdit->append(QString(QString::fromLocal8Bit("正行程平均值:%1")).arg(outputData.at(0).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("反行程平均值:%1")).arg(outputData.at(1).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("正、反行程总平均值:%1")).arg(outputData.at(2).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("最小二乘值:%1")).arg(outputData.at(4).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("线性差值ΔL:%1")).arg(outputData.at(5).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("迟滞性ΔH:%1")).arg(outputData.at(6).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("正行程标准差Sc:%1")).arg(outputData.at(7).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("反行程标准差Sf:%1")).arg(outputData.at(8).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("正行程系统偏差Bc:%1")).arg(outputData.at(9).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("反行程系统偏差Bf:%1")).arg(outputData.at(10).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("不确定度Bc+tSc:%1")).arg(outputData.at(11).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("不确定度Bf+tSf:%1")).arg(outputData.at(12).at(i)));
ui.textEdit->append(QString(QString::fromLocal8Bit("-----------------------")));
}
ui.textEdit->append(QString(QString::fromLocal8Bit("最终结果:")));
ui.textEdit->append(QString(QString::fromLocal8Bit("y = bx + a,其中:")));
ui.textEdit->append(QString(QString::fromLocal8Bit("b = %1")).arg(outputData.at(3).at(0)));
ui.textEdit->append(QString(QString::fromLocal8Bit("a = %1")).arg(outputData.at(3).at(1)));
//ui.textEdit->append(QString(QString::fromLocal8Bit("YF:%1")).arg(outputData.at(13).at(0)));
//ui.textEdit->append(QString(QString::fromLocal8Bit("t_alpha:%1")).arg(outputData.at(13).at(1)));
ui.textEdit->append(QString(QString::fromLocal8Bit("重复性:%1")).arg(outputData.at(13).at(2)));
ui.textEdit->append(QString(QString::fromLocal8Bit("相对不确定度:%1")).arg(outputData.at(13).at(3)));
ui.textEdit->append(QString(QString::fromLocal8Bit("非线性:%1")).arg(outputData.at(13).at(4)));
ui.textEdit->append(QString(QString::fromLocal8Bit("迟滞性:%1")).arg(outputData.at(13).at(5)));
}
void mainWidget::paintCurve(const std::vector<std::vector<double>>& tableData, const std::vector<std::vector<double>>& outputData)//绘制曲线
{
QPixmap pixmap(ui.labelCurve->width(), ui.labelCurve->height());
pixmap.fill(Qt::black);//黑色背景
QPainter p(&pixmap);//开始绘图----------------------------------------------------------
//定义边距及图像大小
int left = 35;
int up = 10;
int right = 15;
int down = 20;
int imgWidth = ui.labelCurve->width() - left - right;
int imgHeight = ui.labelCurve->height() - up - down;
//白色边框
p.setPen(Qt::white);
p.drawRect(left, up, imgWidth, imgHeight);
//绿色网格线
p.setPen(QPen(Qt::green, 1, Qt::DotLine));
for (int i = left + imgWidth / 10; i <= left + imgWidth * 9 / 10; i += imgWidth / 10)
{
p.drawLine(i, up, i, up + imgHeight);
}
for (int j = up + imgHeight / 10; j <= up + imgHeight * 9 / 10; j += imgHeight / 10)
{
p.drawLine(left, j, left + imgWidth, j);
}
//坐标值
p.setPen(QPen(Qt::white));
p.drawText(left - 3, up + imgHeight + 15, QString("0"));
p.drawText(left - 34, up + imgHeight + 5, QString("0.000"));
double maxX = tableData.at(K - 1).at(0);//X坐标最大值
for (int i = 1; i <= 10; i++)
{
p.drawText(left - 15 + i * imgWidth / 10, up + imgHeight + 15, QString::number(i * maxX / 10,'f',2));
}
double maxY = tableData.at(K - 1).at(1) * 1.1;//Y坐标最大值
for (int j = 1; j <= 10; j++)
{
p.drawText(left - 34, up + imgHeight + 5 - j * imgHeight / 10, QString::number(j * maxY / 10, 'f', 3));
}
//工作曲线
int numA = 0;//左截距 像素坐标值
int numB = 0;//右截距 像素坐标值
numA = outputData.at(3).at(1) / maxY * imgHeight;
numB = (outputData.at(3).at(0) * tableData.at(K - 1).at(0) + outputData.at(3).at(1)) / maxY * imgHeight;
p.setPen(QPen(Qt::yellow, 2));
p.drawLine(left, up + imgHeight - numA, left + imgWidth, up + imgHeight - numB);
//数据点
p.setPen(QPen(Qt::red, 2));
for (int i = 0; i < K; i++)
{
for (int j = 1; j <= 2 * R; j++)//j从1到R
{
int X;
int Y;
X = tableData.at(i).at(0) / tableData.at(K - 1).at(0) * imgWidth + left;
Y = up + imgHeight - tableData.at(i).at(j) / maxY * imgHeight;
p.drawPoint(X,Y);
}
}
p.end();//结束绘图-------------------------------------------------------------------
ui.labelCurve->setPixmap(pixmap);//显示
}
void mainWidget::on_spinBoxK_valueChanged()
{
K = ui.spinBoxNumK->value();
ui.tableWidget->setRowCount(K);
}
void mainWidget::on_spinBoxR_valueChanged()
{
R = ui.spinBoxNumR->value();
ui.tableWidget->setColumnCount(2 * R + 1);
setHeaders();
}
void mainWidget::on_buttonClearTable_clicked()
{
ui.tableWidget->clearContents();
}
void mainWidget::on_buttonClearTexeEdit_clicked()
{
ui.textEdit->clear();
}
void mainWidget::on_buttonCompute_clicked()
{
if (K == 0 || R == 0) return;
else//若列表不为空
{
std::vector<std::vector<double>> tableData(K, std::vector<double>(2 * R + 1));//表格原始输入数据
//按列遍历读取并检查数据
for (int i = 0; i < K; i++)
{
for (int j = 0; j < 2 * R + 1; j++)
{
if (ui.tableWidget->item(i, j) == NULL) return;//若表格有填写空缺,退出函数
else//单元格非空,读取数据
{
bool ok = true;
tableData.at(i).at(j) = ui.tableWidget->item(i, j)->text().toDouble(&ok);
//ui.textEdit->append(QString("%1").arg(tableData.at(i).at(j)));
if (ok == false) return;//若表格输入非double类型,退出函数
}
}
}
//计算并输出
std::vector<std::vector<double>> outputData(17);//用二维数组保存计算结果,见compute.cpp
compute(tableData, outputData);//计算
print(outputData);//输出
paintCurve(tableData, outputData);//绘图并显示
//ui.labelCurve->setPixmap(pixmap);//显示
}
}
#include "compute.h"
#include <cmath>
void compute(const std::vector<std::vector<double>>& tableData, std::vector<std::vector<double>>& outputData)
{
const int K = tableData.size();
const int R = (tableData.at(0).size() - 1) / 2;
double temp1 = 0;//中间临时变量
double temp2 = 0;
//0正行程平均值
//1反行程平均值
//2总平均值
for (int i = 0; i < K; i++)
{
for (int j = 1; j <= R; j++)//j从1到R
{
temp1 += tableData.at(i).at(2 * j - 1);//temp1、temp2表示正反行程Y的和
temp2 += tableData.at(i).at(2 * j);
}
outputData.at(0).push_back(temp1 / R);//正行程平均值,一共push_back了K次
outputData.at(1).push_back(temp2 / R);//反行程平均值
outputData.at(2).push_back((temp1 + temp2) / R / 2);//总平均值
temp1 = 0;//置零
temp2 = 0;
}
//3求a 求b
double sum_x = 0;
double sum_x2 = 0;
double sum_y = 0;
double sum_xy = 0;
double a = 0, b = 0;
for (int i = 0; i < K; i++)
{
sum_x += tableData.at(i).at(0);
sum_x2 += tableData.at(i).at(0) * tableData.at(i).at(0);
sum_y += outputData.at(2).at(i);
sum_xy += tableData.at(i).at(0) * outputData.at(2).at(i);
}
b = (K * sum_xy - sum_x * sum_y) / (K * sum_x2 - sum_x * sum_x);
a = sum_y / K - b * sum_x / K;
outputData.at(3).push_back(b);
outputData.at(3).push_back(a);
//4最小二乘值bx+a
//5线性差值
//6迟滞性
//9正行程系统偏差Bc
//10反行程系统偏差Bf
for (int i = 0; i < K; i++)
{
outputData.at(4).push_back(b * tableData.at(i).at(0) + a);
outputData.at(5).push_back(std::abs(outputData.at(2).at(i) - outputData.at(4).at(i)));
outputData.at(6).push_back(std::abs(outputData.at(0).at(i) - outputData.at(1).at(i)));
outputData.at(9).push_back(std::abs(outputData.at(0).at(i) - outputData.at(4).at(i)));
outputData.at(10).push_back(std::abs(outputData.at(1).at(i) - outputData.at(4).at(i)));
}
//7正行程标准差Sc
//8反行程标准差Sf
temp1 = 0;//temp1、temp2表示正反行程(Yi-Y_average)^2的和
temp2 = 0;//置零
for (int i = 0; i < K; i++)//第i个校准点
{
for (int j = 1; j <= R; j++)//j从1到R
{
temp1 += (tableData.at(i).at(2 * j - 1) - outputData.at(0).at(i))
* (tableData.at(i).at(2 * j - 1) - outputData.at(0).at(i));
temp2 += (tableData.at(i).at(2 * j) - outputData.at(1).at(i))
* (tableData.at(i).at(2 * j) - outputData.at(1).at(i));
}
outputData.at(7).push_back(std::sqrt(temp1 / (R - 1)));//正行程标准差
outputData.at(8).push_back(std::sqrt(temp2 / (R - 1)));//反行程标准差
}
//11 Bc+t0.95Sc
//12 Bf+t0.95Sf
double t_alpha = 0;//t_0.95
switch (R)
{
case 2:
{
t_alpha = 12.706;
break;
}
case 3:
{
t_alpha = 4.303;
break;
}
case 4:
{
t_alpha = 3.182;
break;
}
case 5:
{
t_alpha = 2.776;
break;
}
case 6:
{
t_alpha = 2.571;
break;
}
case 7:
{
t_alpha = 2.447;
break;
}
case 8:
{
t_alpha = 2.365;
break;
}
}
for (int i = 0; i < K; i++)
{
outputData.at(11).push_back(outputData.at(9).at(i) + t_alpha * outputData.at(7).at(i));//11 Bc+t0.95Sc
outputData.at(12).push_back(outputData.at(10).at(i) + t_alpha * outputData.at(8).at(i));//12 Bf+t0.95Sf
}
//13 0:Yfc = b * (Xk - X1)、1:t_alpha、2:重复性、3:不确定度、4:非线性、5:迟滞
outputData.at(13).push_back(b * (tableData.at(K - 1).at(0) - tableData.at(0).at(0)));
outputData.at(13).push_back(t_alpha);
double maxS = outputData.at(7).at(0);//最大标准差
double maxU = outputData.at(11).at(0);//不确定度
double maxL = outputData.at(5).at(0);//最大线性差值
double maxH = outputData.at(6).at(0);//最大迟滞性
for (int i = 0; i < K; i++)
{
if (outputData.at(7).at(i) > maxS) maxS = outputData.at(7).at(i);
if (outputData.at(8).at(i) > maxS) maxS = outputData.at(8).at(i);
if (outputData.at(11).at(i) > maxU) maxU = outputData.at(11).at(i);
if (outputData.at(12).at(i) > maxU) maxU = outputData.at(12).at(i);
if (outputData.at(5).at(i) > maxL) maxL = outputData.at(5).at(i);
if (outputData.at(6).at(i) > maxH) maxH = outputData.at(6).at(i);
}
outputData.at(13).push_back(t_alpha * maxS / outputData.at(13).at(0));//重复性2
outputData.at(13).push_back(maxU / outputData.at(13).at(0));//相对不确定度3
outputData.at(13).push_back(maxL / outputData.at(13).at(0));//非线性4
outputData.at(13).push_back(maxH / outputData.at(13).at(0));//迟滞5
}
mainwidget.ui:
控件布局:
最终效果(虚构的数据):
就这些,除 了计算各种统计量有些繁琐以外,没有什么难的地方。以上可供Qt初学者参考,我也只是个菜鸟,可能有很多地方写得不好,欢迎批评指正
上一篇: javaGUI基础(一)
下一篇: 3