完成更新数据到Panel
|
@ -10,18 +10,19 @@ CONFIG += c++17
|
|||
|
||||
SOURCES += \
|
||||
appinit.cpp \
|
||||
customwidget.cpp \
|
||||
customdisplaypanel.cpp \
|
||||
formserialportsettingdialog.cpp \
|
||||
libmodbus/modbus-data.c \
|
||||
libmodbus/modbus-rtu.c \
|
||||
libmodbus/modbus-tcp.c \
|
||||
libmodbus/modbus.c \
|
||||
main.cpp \
|
||||
mainwindow.cpp
|
||||
mainwindow.cpp \
|
||||
openjson.cpp
|
||||
|
||||
HEADERS += \
|
||||
appinit.h \
|
||||
customwidget.h \
|
||||
customdisplaypanel.h \
|
||||
formserialportsettingdialog.h \
|
||||
libmodbus/config.h \
|
||||
libmodbus/modbus-private.h \
|
||||
|
@ -32,6 +33,7 @@ HEADERS += \
|
|||
libmodbus/modbus-version.h \
|
||||
libmodbus/modbus.h \
|
||||
mainwindow.h \
|
||||
openjson.h \
|
||||
slave_define.h
|
||||
|
||||
FORMS += \
|
||||
|
|
|
@ -0,0 +1,417 @@
|
|||
#include "customdisplaypanel.h"
|
||||
#include <QLabel>
|
||||
#include <QTableWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QFontDatabase>
|
||||
|
||||
CustomDisplayPanel::CustomDisplayPanel(QWidget *parent)
|
||||
: QWidget{parent}
|
||||
,m_label_count{5},m_table_rows_count{10},m_table_rols_count{2},m_imagePath{":/icons/home.png"},m_pTableWidget(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void CustomDisplayPanel::Build()
|
||||
{
|
||||
// **让 CustomWidget 背景透明,避免遮挡阴影**
|
||||
this->setAttribute(Qt::WA_TranslucentBackground);
|
||||
this->setStyleSheet("background: transparent;");
|
||||
|
||||
// **创建一个子容器 `containerWidget`,所有内容都放在这里**
|
||||
QWidget *containerWidget = new QWidget(this);
|
||||
containerWidget->setStyleSheet("background-color: white; border-radius: 10px;");
|
||||
|
||||
// **为 `containerWidget` 添加阴影**
|
||||
QGraphicsDropShadowEffect *shadowMain = new QGraphicsDropShadowEffect(this);
|
||||
shadowMain->setBlurRadius(10);
|
||||
shadowMain->setOffset(5, 5);
|
||||
shadowMain->setColor(QColor(0, 0, 0, 120)); // 半透明黑色
|
||||
containerWidget->setGraphicsEffect(shadowMain);
|
||||
|
||||
// **主垂直布局**
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->addWidget(containerWidget);
|
||||
mainLayout->setContentsMargins(10, 10, 10, 10); // 预留空间显示阴影
|
||||
this->setLayout(mainLayout);
|
||||
|
||||
// **容器内的布局**
|
||||
QVBoxLayout *containerLayout = new QVBoxLayout(containerWidget);
|
||||
|
||||
// **上半部分(固定高度 200)**
|
||||
QWidget *topWidget = new QWidget(containerWidget);
|
||||
topWidget->setFixedHeight(200);
|
||||
topWidget->setStyleSheet("background-color: white; border-radius: 10px;");
|
||||
|
||||
// **应用阴影效果**
|
||||
QGraphicsDropShadowEffect *shadowTop = new QGraphicsDropShadowEffect(this);
|
||||
shadowTop->setBlurRadius(10);
|
||||
shadowTop->setOffset(5, 5);
|
||||
shadowTop->setColor(QColor(0, 0, 0, 100)); // 半透明黑色
|
||||
topWidget->setGraphicsEffect(shadowTop);
|
||||
|
||||
QHBoxLayout *topLayout = new QHBoxLayout(topWidget);
|
||||
|
||||
// **左侧布局(上下排列:64x64 图片 + QLabel)**
|
||||
QVBoxLayout *leftLayout = new QVBoxLayout();
|
||||
QLabel *imageLabel = new QLabel(topWidget);
|
||||
QPixmap pixmap(m_imagePath); // 替换为实际图片路径
|
||||
imageLabel->setPixmap(pixmap.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
int width = 120;
|
||||
imageLabel->setFixedSize(width, 64);
|
||||
imageLabel->setAlignment(Qt::AlignCenter);
|
||||
|
||||
QLabel *textLabel = new QLabel(m_mainLabel, topWidget);
|
||||
textLabel->setAlignment(Qt::AlignCenter);
|
||||
textLabel->setStyleSheet(
|
||||
"QLabel {"
|
||||
//" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
|
||||
" font-family: 'Arial';"
|
||||
" font-size: 20px;"
|
||||
" color: #13396E;"
|
||||
" font-weight: bold;"
|
||||
" font-style: black;"
|
||||
"}"
|
||||
);
|
||||
textLabel->setFixedSize(width, 40);
|
||||
|
||||
leftLayout->addWidget(imageLabel);
|
||||
leftLayout->addWidget(textLabel);
|
||||
leftLayout->setAlignment(Qt::AlignCenter);
|
||||
|
||||
// **右侧布局:包含 5 个 QLabel**
|
||||
// 加载字体
|
||||
int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf");
|
||||
if (fontId == -1)
|
||||
{
|
||||
qDebug() << "字体加载失败";
|
||||
}
|
||||
|
||||
QVBoxLayout *rightLayout = new QVBoxLayout();
|
||||
for (int i = 0; i < m_label_count; ++i)
|
||||
{
|
||||
QLabel *label = new QLabel(m_lables[i], topWidget);
|
||||
label->setStyleSheet(
|
||||
"QLabel {"
|
||||
//" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
|
||||
" font-family: 'Arial';"
|
||||
" font-size: 20px;"
|
||||
" color: #2E86C1;"
|
||||
" font-weight: bold;"
|
||||
"}"
|
||||
);
|
||||
label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
rightLayout->addWidget(label);
|
||||
m_txtLabels.push_back(label);
|
||||
}
|
||||
|
||||
// **组装上半部分布局**
|
||||
QWidget *leftWidget = new QWidget(topWidget);
|
||||
leftWidget->setLayout(leftLayout);
|
||||
|
||||
QWidget *rightWidget = new QWidget(topWidget);
|
||||
rightWidget->setLayout(rightLayout);
|
||||
|
||||
topLayout->addWidget(leftWidget, 1); // 1/3 宽度
|
||||
topLayout->addWidget(rightWidget, 4); // 2/3 宽度
|
||||
containerLayout->addWidget(topWidget,1);
|
||||
|
||||
// **下半部分:2 列 5 行表格**
|
||||
QTableWidget *tableWidget = new QTableWidget(m_table_rows_count, m_table_rols_count, containerWidget);
|
||||
m_pTableWidget = tableWidget;
|
||||
|
||||
// tableWidget->setHorizontalHeaderLabels({"Signal", "Value"});
|
||||
|
||||
// 设置列宽策略
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||
tableWidget->setColumnWidth(0, 150);
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
//tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
//tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
// 隐藏所有表头
|
||||
tableWidget->horizontalHeader()->setVisible(false); // 隐藏水平表头[1](@ref)
|
||||
tableWidget->verticalHeader()->setVisible(false); // 隐藏垂直表头[1](@ref)
|
||||
|
||||
// 禁止表格编辑
|
||||
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
|
||||
// 设置网格线样式
|
||||
tableWidget->setShowGrid(true); // 默认显示网格线[3](@ref)
|
||||
tableWidget->setStyleSheet("QTableWidget { gridline-color: #e0e0e0; background-color: white; border-radius: 10px;}");
|
||||
|
||||
// **应用阴影效果**
|
||||
QGraphicsDropShadowEffect *shadowTable = new QGraphicsDropShadowEffect(this);
|
||||
shadowTable->setBlurRadius(10);
|
||||
shadowTable->setOffset(5, 5);
|
||||
shadowTable->setColor(QColor(0, 0, 0, 100));
|
||||
tableWidget->setGraphicsEffect(shadowTable);
|
||||
|
||||
containerLayout->addWidget(tableWidget,1);
|
||||
m_pTableWidget->setRowCount(0);
|
||||
}
|
||||
|
||||
|
||||
void CustomDisplayPanel::UpdateData(OpenJson& json)
|
||||
{
|
||||
int panel_type = json["panel_type"].i32();
|
||||
qDebug() << panel_type;
|
||||
|
||||
if (panel_type == CustomDisplayPanel::PANEL_TEMPERATURE)
|
||||
{
|
||||
UpdateTemperature(json);
|
||||
}
|
||||
else if (panel_type == CustomDisplayPanel::PANEL_ALARM)
|
||||
{
|
||||
UpdateAlarm(json);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomDisplayPanel::UpdateTemperature(OpenJson &json)
|
||||
{
|
||||
auto& nodeLabel = json["text_panel"];
|
||||
qDebug() << nodeLabel.size();
|
||||
for(size_t i=0; i<nodeLabel.size(); i++)
|
||||
{
|
||||
auto& node = nodeLabel[i];
|
||||
std::string title = node["title"].s();
|
||||
std::string value = node["value"].s();
|
||||
qDebug() << QString::fromStdString(title) << ":"<< QString::fromStdString(value);
|
||||
QString disp;
|
||||
if (i == 0)
|
||||
{
|
||||
if (value == "1")
|
||||
disp = QString("Online");
|
||||
else
|
||||
disp = QString("Offline");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
disp = QString("%1: %2").arg(QString::fromStdString(title)).arg(QString::fromStdString(value));
|
||||
}
|
||||
m_txtLabels[i]->setText(disp);
|
||||
}
|
||||
|
||||
auto& nodeTable = json["table"];
|
||||
qDebug() << nodeTable.size();
|
||||
|
||||
m_pTableWidget->clear();
|
||||
m_pTableWidget->setRowCount(nodeTable.size());
|
||||
|
||||
// 加载字体
|
||||
int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf");
|
||||
if (fontId == -1)
|
||||
{
|
||||
qDebug() << "字体加载失败";
|
||||
}
|
||||
|
||||
for(size_t i=0; i<nodeTable.size(); i++)
|
||||
{
|
||||
auto& node = nodeTable[i];
|
||||
std::string title = node["signal"].s();
|
||||
std::string value = node["value"].s();
|
||||
|
||||
int col = 0;
|
||||
|
||||
// **填充表格数据**
|
||||
QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(title));
|
||||
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); // 右对齐+垂直居中
|
||||
// 仅第一列设置特殊字体
|
||||
|
||||
QFont font;
|
||||
//font.setFamily("Alimama DongFangDaKai");
|
||||
font.setFamily("Arial");
|
||||
font.setPixelSize(20);
|
||||
font.setBold(true);
|
||||
item->setFont(font);
|
||||
//item->setForeground(QBrush(QColor("#2E86C1")));
|
||||
item->setForeground(QColor(Qt::red));
|
||||
|
||||
m_pTableWidget->setItem(i, col++, item);
|
||||
|
||||
// **填充表格数据**
|
||||
QTableWidgetItem *item2 = new QTableWidgetItem(QString::fromStdString(value));
|
||||
item2->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); // 右对齐+垂直居中
|
||||
|
||||
QFont font2;
|
||||
font2.setFamily("Arial");
|
||||
font2.setPixelSize(20);
|
||||
//font2.setBold(true);
|
||||
item2->setFont(font2);
|
||||
//item2->setForeground(QBrush(QColor("#2E86C1")));
|
||||
item2->setForeground(QColor(Qt::red));
|
||||
|
||||
m_pTableWidget->setItem(i, col, item2);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomDisplayPanel::UpdateAlarm(OpenJson &json)
|
||||
{
|
||||
qDebug() << "更新告警信息";
|
||||
QFont font;
|
||||
font.setFamily("Arial");
|
||||
font.setPixelSize(16);
|
||||
font.setBold(false);
|
||||
|
||||
auto& nodeTable = json["alarm"];
|
||||
qDebug() << nodeTable.size();
|
||||
for(size_t i=0; i<nodeTable.size(); i++)
|
||||
{
|
||||
m_pTableWidget->insertRow(0);
|
||||
auto& node = nodeTable[i];
|
||||
std::string s = node["time"].s();
|
||||
std::string title = node["signal"].s();
|
||||
std::string value = node["value"].s();
|
||||
|
||||
int col = 0;
|
||||
QTableWidgetItem *item0 = new QTableWidgetItem(QString::fromStdString(s));
|
||||
item0->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); // 右对齐+垂直居中
|
||||
QTableWidgetItem *item1 = new QTableWidgetItem(QString::fromStdString(title));
|
||||
QTableWidgetItem *item2 = new QTableWidgetItem(QString::fromStdString(value));
|
||||
|
||||
item0->setFont(font);
|
||||
item1->setFont(font);
|
||||
item2->setFont(font);
|
||||
item0->setForeground(QBrush(QColor("#2E86C1")));
|
||||
item1->setForeground(QBrush(QColor("#2E86C1")));
|
||||
item2->setForeground(QBrush(QColor("#2E86C1")));
|
||||
|
||||
m_pTableWidget->setItem(0, 0, item0);
|
||||
m_pTableWidget->setItem(0, 1, item1);
|
||||
m_pTableWidget->setItem(0, 2, item2);
|
||||
}
|
||||
}
|
||||
|
||||
////////
|
||||
/// \brief CustomWarningPanel::CustomWarningPanel
|
||||
///
|
||||
///
|
||||
CustomWarningPanel::CustomWarningPanel(QWidget *parent)
|
||||
: CustomDisplayPanel{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CustomWarningPanel::Build()
|
||||
{
|
||||
// **让 CustomWidget 背景透明,避免遮挡阴影**
|
||||
this->setAttribute(Qt::WA_TranslucentBackground);
|
||||
this->setStyleSheet("background: transparent;");
|
||||
|
||||
// **创建一个子容器 `containerWidget`,所有内容都放在这里**
|
||||
QWidget *containerWidget = new QWidget(this);
|
||||
containerWidget->setStyleSheet("background-color: white; border-radius: 10px;");
|
||||
|
||||
// **为 `containerWidget` 添加阴影**
|
||||
QGraphicsDropShadowEffect *shadowMain = new QGraphicsDropShadowEffect(this);
|
||||
shadowMain->setBlurRadius(10);
|
||||
shadowMain->setOffset(5, 5);
|
||||
shadowMain->setColor(QColor(0, 0, 0, 120)); // 半透明黑色
|
||||
containerWidget->setGraphicsEffect(shadowMain);
|
||||
|
||||
// **主垂直布局**
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->addWidget(containerWidget);
|
||||
mainLayout->setContentsMargins(10, 10, 10, 10); // 预留空间显示阴影
|
||||
this->setLayout(mainLayout);
|
||||
|
||||
// **容器内的布局**
|
||||
QVBoxLayout *containerLayout = new QVBoxLayout(containerWidget);
|
||||
|
||||
// **上半部分(固定高度 200)**
|
||||
QWidget *topWidget = new QWidget(containerWidget);
|
||||
topWidget->setFixedHeight(100);
|
||||
topWidget->setStyleSheet("background-color: white; border-radius: 10px;");
|
||||
|
||||
// **应用阴影效果**
|
||||
QGraphicsDropShadowEffect *shadowTop = new QGraphicsDropShadowEffect(this);
|
||||
shadowTop->setBlurRadius(10);
|
||||
shadowTop->setOffset(5, 5);
|
||||
shadowTop->setColor(QColor(0, 0, 0, 100)); // 半透明黑色
|
||||
topWidget->setGraphicsEffect(shadowTop);
|
||||
|
||||
QHBoxLayout *topLayout = new QHBoxLayout(topWidget);
|
||||
|
||||
// **左侧布局(上下排列:64x64 图片 + QLabel)**
|
||||
QVBoxLayout *leftLayout = new QVBoxLayout();
|
||||
QLabel *imageLabel = new QLabel(topWidget);
|
||||
QPixmap pixmap(m_imagePath); // 替换为实际图片路径
|
||||
imageLabel->setPixmap(pixmap.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
int width = 80;
|
||||
imageLabel->setFixedSize(width, 80);
|
||||
imageLabel->setAlignment(Qt::AlignCenter);
|
||||
|
||||
leftLayout->addWidget(imageLabel);
|
||||
leftLayout->setAlignment(Qt::AlignCenter);
|
||||
|
||||
// **右侧布局:包含 5 个 QLabel**
|
||||
// 加载字体
|
||||
int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf");
|
||||
if (fontId == -1)
|
||||
{
|
||||
qDebug() << "字体加载失败";
|
||||
}
|
||||
|
||||
QVBoxLayout *rightLayout = new QVBoxLayout();
|
||||
for (int i = 0; i < m_label_count; ++i)
|
||||
{
|
||||
QLabel *label = new QLabel(m_lables[i], topWidget);
|
||||
label->setStyleSheet(
|
||||
"QLabel {"
|
||||
//" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
|
||||
" font-family: 'Arial';"
|
||||
" font-size: 20px;"
|
||||
" color: #2E86C1;"
|
||||
" font-weight: bold;"
|
||||
"}"
|
||||
);
|
||||
label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
rightLayout->addWidget(label);
|
||||
m_txtLabels.push_back(label);
|
||||
}
|
||||
|
||||
// **组装上半部分布局**
|
||||
QWidget *leftWidget = new QWidget(topWidget);
|
||||
leftWidget->setLayout(leftLayout);
|
||||
|
||||
QWidget *rightWidget = new QWidget(topWidget);
|
||||
rightWidget->setLayout(rightLayout);
|
||||
|
||||
topLayout->addWidget(leftWidget, 1); // 1/3 宽度
|
||||
topLayout->addWidget(rightWidget, 4); // 2/3 宽度
|
||||
containerLayout->addWidget(topWidget,1);
|
||||
|
||||
// **下半部分:2 列 5 行表格**
|
||||
QTableWidget *tableWidget = new QTableWidget(m_table_rows_count, m_table_rols_count, containerWidget);
|
||||
m_pTableWidget = tableWidget;
|
||||
|
||||
// tableWidget->setHorizontalHeaderLabels({"Signal", "Value"});
|
||||
|
||||
// 设置列宽策略
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||
tableWidget->setColumnWidth(0, 150);
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
//tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
//tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
// 隐藏所有表头
|
||||
tableWidget->horizontalHeader()->setVisible(false); // 隐藏水平表头[1](@ref)
|
||||
tableWidget->verticalHeader()->setVisible(false); // 隐藏垂直表头[1](@ref)
|
||||
|
||||
// 禁止表格编辑
|
||||
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
|
||||
// 设置网格线样式
|
||||
tableWidget->setShowGrid(true); // 默认显示网格线[3](@ref)
|
||||
tableWidget->setStyleSheet("QTableWidget { gridline-color: #e0e0e0; background-color: white; border-radius: 10px;}");
|
||||
|
||||
// **应用阴影效果**
|
||||
QGraphicsDropShadowEffect *shadowTable = new QGraphicsDropShadowEffect(this);
|
||||
shadowTable->setBlurRadius(10);
|
||||
shadowTable->setOffset(5, 5);
|
||||
shadowTable->setColor(QColor(0, 0, 0, 100));
|
||||
tableWidget->setGraphicsEffect(shadowTable);
|
||||
|
||||
containerLayout->addWidget(tableWidget,1);
|
||||
m_pTableWidget->setRowCount(0);
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
#ifndef CUSTOMDISPLAYPANEL_H
|
||||
#define CUSTOMDISPLAYPANEL_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QHBoxLayout>
|
||||
#include <QStringList>
|
||||
#include <QLabel>
|
||||
#include <QVector>
|
||||
#include <QTableWidget>
|
||||
|
||||
#include "openjson.h"
|
||||
|
||||
/**
|
||||
* 创建一个自定义的显示面板
|
||||
* 上半部分的左边为图示,右边为显示的主要KPI指标标签
|
||||
* 下半部为表格,显示主要的参数
|
||||
*/
|
||||
|
||||
class CustomDisplayPanel : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CustomDisplayPanel(QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
int m_label_count;
|
||||
int m_table_rows_count;
|
||||
int m_table_rols_count;
|
||||
QStringList m_lables;
|
||||
QStringList m_rowItems;
|
||||
QString m_imagePath;
|
||||
QString m_mainLabel;
|
||||
|
||||
QVector<QLabel*> m_txtLabels;
|
||||
QTableWidget* m_pTableWidget;
|
||||
|
||||
public:
|
||||
typedef enum _tagPanelType: int
|
||||
{
|
||||
PANEL_TEMPERATURE = 1,
|
||||
PANEL_BATTERY,
|
||||
PANEL_POWER,
|
||||
PANEL_AC,
|
||||
PANEL_PV,
|
||||
PANEL_ALARM,
|
||||
PANEL_INVERTER,
|
||||
PANEL_HOME,
|
||||
} PanelType;
|
||||
|
||||
public:
|
||||
void setImage(const QString& img)
|
||||
{
|
||||
m_imagePath = img;
|
||||
}
|
||||
|
||||
//设置显示指标和表格数据,其中显示的标签数量需要跟QStringlist的数量一致
|
||||
void setLableCount(int number = 5)
|
||||
{
|
||||
m_label_count = number;
|
||||
};
|
||||
void setTableRolCount(int number = 2)
|
||||
{
|
||||
m_table_rols_count = number;
|
||||
}
|
||||
void setTableRowsCount(int number = 10)
|
||||
{
|
||||
m_table_rows_count = number;
|
||||
};
|
||||
|
||||
void setLables(const QStringList& sl)
|
||||
{
|
||||
m_lables = sl;
|
||||
}
|
||||
void setRowItems(const QStringList& sl)
|
||||
{
|
||||
m_rowItems = sl;
|
||||
}
|
||||
//设置Panel的标题
|
||||
void setMainLabel(QString label)
|
||||
{
|
||||
m_mainLabel = label;
|
||||
}
|
||||
|
||||
virtual void Build();
|
||||
|
||||
public:
|
||||
//更新数据
|
||||
void UpdateData(OpenJson& json);
|
||||
|
||||
void UpdateTemperature(OpenJson& json);
|
||||
void UpdateAlarm(OpenJson& json);
|
||||
public:
|
||||
|
||||
|
||||
signals:
|
||||
};
|
||||
|
||||
class CustomWarningPanel : public CustomDisplayPanel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CustomWarningPanel(QWidget *parent = nullptr);
|
||||
virtual void Build();
|
||||
};
|
||||
|
||||
#endif // CUSTOMDISPLAYPANEL_H
|
|
@ -1,100 +0,0 @@
|
|||
#include "customwidget.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QTableWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
|
||||
CustomWidget::CustomWidget(QWidget *parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
QWidget *centralWidget = new QWidget();
|
||||
QGridLayout *mainLayout = new QGridLayout(this);
|
||||
mainLayout->addWidget(centralWidget);
|
||||
|
||||
//实例阴影shadow
|
||||
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
|
||||
//设置阴影距离
|
||||
shadow->setOffset(0, 0);
|
||||
//设置阴影颜色
|
||||
shadow->setColor(QColor(44,44,44));
|
||||
//设置阴影圆角
|
||||
shadow->setBlurRadius(16);
|
||||
//给嵌套QDialog设置阴影
|
||||
centralWidget->setGraphicsEffect(shadow);
|
||||
|
||||
QVBoxLayout *mainLayout1 = new QVBoxLayout(centralWidget);
|
||||
mainLayout1->setSpacing(5); // 控件间间隔
|
||||
|
||||
// 上1/3:QLabel
|
||||
QWidget *topWidget = new QWidget();
|
||||
mainLayout1->addWidget(topWidget, 1); // 拉伸因子为1
|
||||
setupTopSection(topWidget);
|
||||
|
||||
// 中1/3:两个垂直排列的QTextEdit
|
||||
QWidget *midWidget = new QWidget();
|
||||
mainLayout1->addWidget(midWidget, 1);
|
||||
setupMidSection(midWidget);
|
||||
|
||||
// 下1/3:表格
|
||||
QWidget *bottomWidget = new QWidget();
|
||||
mainLayout1->addWidget(bottomWidget, 1);
|
||||
setupBottomSection(bottomWidget);
|
||||
}
|
||||
|
||||
void CustomWidget::setupTopSection(QWidget *parent)
|
||||
{
|
||||
//实例阴影shadow
|
||||
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
|
||||
//设置阴影距离
|
||||
shadow->setOffset(0, 0);
|
||||
//设置阴影颜色
|
||||
shadow->setColor(QColor(244,44,44));
|
||||
//设置阴影圆角
|
||||
shadow->setBlurRadius(16);
|
||||
|
||||
QLabel *label = new QLabel("顶部标签", parent);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
label->setGraphicsEffect(shadow);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(parent);
|
||||
layout->addWidget(label);
|
||||
}
|
||||
|
||||
void CustomWidget::setupMidSection(QWidget *parent)
|
||||
{
|
||||
//实例阴影shadow
|
||||
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
|
||||
//设置阴影距离
|
||||
shadow->setOffset(0, 0);
|
||||
//设置阴影颜色
|
||||
shadow->setColor(QColor(244,44,44));
|
||||
//设置阴影圆角
|
||||
shadow->setBlurRadius(16);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(parent);
|
||||
QTextEdit *textEdit1 = new QTextEdit();
|
||||
QTextEdit *textEdit2 = new QTextEdit();
|
||||
layout->addWidget(textEdit1, 1); // 各占中间区域的一半高度
|
||||
layout->addWidget(textEdit2, 1);
|
||||
}
|
||||
|
||||
void CustomWidget::setupBottomSection(QWidget *parent)
|
||||
{
|
||||
//实例阴影shadow
|
||||
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
|
||||
//设置阴影距离
|
||||
shadow->setOffset(0, 0);
|
||||
//设置阴影颜色
|
||||
shadow->setColor(QColor(244,44,44));
|
||||
//设置阴影圆角
|
||||
shadow->setBlurRadius(16);
|
||||
|
||||
QTableWidget *table = new QTableWidget(5, 2, parent); // 5行2列
|
||||
table->setHorizontalHeaderLabels({"列1", "列2"});
|
||||
table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 列宽自适应
|
||||
table->setGraphicsEffect(shadow);
|
||||
QVBoxLayout *layout = new QVBoxLayout(parent);
|
||||
layout->addWidget(table);
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef CUSTOMWIDGET_H
|
||||
#define CUSTOMWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
class CustomWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CustomWidget(QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
void setupTopSection(QWidget *parent);
|
||||
void setupMidSection(QWidget *parent);
|
||||
void setupBottomSection(QWidget *parent);
|
||||
|
||||
signals:
|
||||
};
|
||||
|
||||
#endif // CUSTOMWIDGET_H
|
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 900 B |
After Width: | Height: | Size: 848 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.3 KiB |
|
@ -12,10 +12,11 @@
|
|||
#include <QMessageBox>
|
||||
#include <QSizePolicy>
|
||||
#include <QFontDatabase>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "libmodbus/modbus.h"
|
||||
|
||||
#include "customwidget.h"
|
||||
#include "customdisplaypanel.h"
|
||||
|
||||
#include "formserialportsettingdialog.h"
|
||||
|
||||
|
@ -91,7 +92,10 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
: QMainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
,m_pModbus(nullptr)
|
||||
,m_pTimer(nullptr)
|
||||
,m_pSettings(nullptr)
|
||||
,m_bInitializeModbus(false)
|
||||
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -203,9 +207,11 @@ void MainWindow::getConfiguration(QString iniFilePath)
|
|||
bool MainWindow::InitializeUI()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
this->showMaximized();
|
||||
//this->showMaximized();
|
||||
#endif
|
||||
|
||||
ui->statusbar->showMessage(tr("Ready"), 0);
|
||||
|
||||
//初始化窗口边框
|
||||
QWidget *centralWidget = this->centralWidget(); // new QWidget(this);
|
||||
QGridLayout *mainLayout = new QGridLayout(centralWidget);
|
||||
|
@ -231,27 +237,102 @@ bool MainWindow::InitializeUI()
|
|||
//给垂直布局器设置边距(此步很重要, 设置宽度为阴影的宽度)
|
||||
//->setMargin(12);
|
||||
|
||||
// 创建2行4列布局(共8个控件示例)
|
||||
for(int row=0; row<2; ++row)
|
||||
{
|
||||
for(int col=0; col<4; ++col)
|
||||
{
|
||||
#if 0
|
||||
QLabel *label = new QLabel(QString("Cell %1-%2").arg(row).arg(col),this);
|
||||
label->setStyleSheet("background-color: rgb(192,192,192);"
|
||||
"color: #333333;"
|
||||
"border-radius: 8px;"
|
||||
"font: bold 14px;");
|
||||
label->setAutoFillBackground(true);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
mainLayout->addWidget(label, row, col);
|
||||
m_panel_labels.push_back(label);
|
||||
#endif
|
||||
CustomWidget* pWidget = new CustomWidget(this);
|
||||
mainLayout->addWidget(pWidget, row, col);
|
||||
}
|
||||
}
|
||||
//温度
|
||||
m_pTemperaturePanel = new CustomDisplayPanel(this);
|
||||
m_pTemperaturePanel->setImage(":/icons/main_temp.png");
|
||||
QStringList l1{tr("Online"),tr("Temperature"),tr("Humidity")};
|
||||
m_pTemperaturePanel->setLableCount(l1.count());
|
||||
m_pTemperaturePanel->setTableRowsCount(10);
|
||||
m_pTemperaturePanel->setLables(l1);
|
||||
m_pTemperaturePanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
|
||||
m_pTemperaturePanel->setMainLabel(tr("Temp&RH"));
|
||||
m_pTemperaturePanel->Build();
|
||||
mainLayout->addWidget(m_pTemperaturePanel, 0, 0);
|
||||
|
||||
//电源
|
||||
m_pPowerPanel = new CustomDisplayPanel(this);
|
||||
m_pPowerPanel->setImage(":/icons/main_power.png");
|
||||
QStringList l2{QStringList{tr("Online"),tr("Input Voltage"),tr("Output Voltage"),tr("Output Current"),tr("Module Temp.")}};
|
||||
m_pPowerPanel->setLableCount(l2.count());
|
||||
m_pPowerPanel->setTableRowsCount(10);
|
||||
m_pPowerPanel->setLables(l2);
|
||||
m_pPowerPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
|
||||
m_pPowerPanel->setMainLabel(tr("Power"));
|
||||
m_pPowerPanel->Build();
|
||||
mainLayout->addWidget(m_pPowerPanel, 0, 1);
|
||||
|
||||
//电池
|
||||
m_pBatteryPanel = new CustomDisplayPanel(this);
|
||||
m_pBatteryPanel->setImage(":/icons/main_battery.png");
|
||||
QStringList l3{QStringList{tr("Online"),tr("SOC"),tr("SOH"),tr("Group Voltage"),tr("Cell V.Avg"),tr("Cell V.Max"),tr("Cell V.Min")}};
|
||||
m_pBatteryPanel->setLableCount(l3.count());
|
||||
m_pBatteryPanel->setTableRowsCount(10);
|
||||
m_pBatteryPanel->setLables(l3);
|
||||
m_pBatteryPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
|
||||
m_pBatteryPanel->setMainLabel(tr("Battery Pack"));
|
||||
m_pBatteryPanel->Build();
|
||||
mainLayout->addWidget(m_pBatteryPanel, 0, 2);
|
||||
|
||||
//空调
|
||||
m_pACPanel = new CustomDisplayPanel(this);
|
||||
m_pACPanel->setImage(":/icons/main_ac.png");
|
||||
QStringList l4{QStringList{tr("Online"),tr("Machine"),tr("IFM"),tr("Compressor"),tr("OFM"),tr("Discharge Temp."),tr("Room Temp.")}};
|
||||
m_pACPanel->setLableCount(l4.count());
|
||||
m_pACPanel->setTableRowsCount(10);
|
||||
m_pACPanel->setLables(l4);
|
||||
m_pACPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
|
||||
m_pACPanel->setMainLabel(tr("HVACR"));
|
||||
m_pACPanel->Build();
|
||||
mainLayout->addWidget(m_pACPanel, 0, 3);
|
||||
|
||||
//交流配电
|
||||
m_pInverterPanel = new CustomDisplayPanel(this);
|
||||
m_pInverterPanel->setImage(":/icons/main_invertor.png");
|
||||
QStringList l5{QStringList{tr("Online"),tr("Input Voltage"),tr("Input Current"),tr("Module Temp.")}};
|
||||
m_pInverterPanel->setLableCount(l5.count());
|
||||
m_pInverterPanel->setTableRowsCount(10);
|
||||
m_pInverterPanel->setLables(l5);
|
||||
m_pInverterPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
|
||||
m_pInverterPanel->setMainLabel(tr("AC Power"));
|
||||
m_pInverterPanel->Build();
|
||||
mainLayout->addWidget(m_pInverterPanel, 1, 0);
|
||||
|
||||
//PV太阳能
|
||||
m_pPVPanel = new CustomDisplayPanel(this);
|
||||
m_pPVPanel->setImage(":/icons/main_pv.png");
|
||||
QStringList l6{QStringList{tr("Online"),tr("Output Voltage"),tr("Output Current"),tr("Module Temp.")}};
|
||||
m_pPVPanel->setLableCount(l6.count());
|
||||
m_pPVPanel->setTableRowsCount(10);
|
||||
m_pPVPanel->setLables(l6);
|
||||
m_pPVPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
|
||||
m_pPVPanel->setMainLabel(tr("PV Module"));
|
||||
m_pPVPanel->Build();
|
||||
mainLayout->addWidget(m_pPVPanel, 1, 1);
|
||||
|
||||
//门禁
|
||||
m_pHomePanel = new CustomDisplayPanel(this);
|
||||
m_pHomePanel->setImage(":/icons/main_cab.png");
|
||||
QStringList l7{QStringList{tr("Online"),tr("Output Voltage"),tr("Output Current"),tr("Module Temp.")}};
|
||||
m_pHomePanel->setLableCount(l7.count());
|
||||
m_pHomePanel->setTableRowsCount(10);
|
||||
m_pHomePanel->setLables(l7);
|
||||
m_pHomePanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
|
||||
m_pHomePanel->setMainLabel(tr("Sensors"));
|
||||
m_pHomePanel->Build();
|
||||
mainLayout->addWidget(m_pHomePanel, 1, 2);
|
||||
|
||||
//告警
|
||||
m_pAlarmPanel = new CustomWarningPanel(this);
|
||||
m_pAlarmPanel->setImage(":/icons/main_alarm.png");
|
||||
QStringList l8{QStringList{tr("Warning Board")}};
|
||||
m_pAlarmPanel->setLableCount(l8.count());
|
||||
m_pAlarmPanel->setTableRowsCount(10);
|
||||
m_pAlarmPanel->setTableRolCount(3);
|
||||
m_pAlarmPanel->setLables(l8);
|
||||
m_pAlarmPanel->setRowItems(QStringList{tr("")});
|
||||
m_pAlarmPanel->setMainLabel(tr("Warning"));
|
||||
m_pAlarmPanel->Build();
|
||||
mainLayout->addWidget(m_pAlarmPanel, 1, 3);
|
||||
|
||||
// 设置布局的间距和边距
|
||||
mainLayout->setSpacing(5);
|
||||
|
@ -278,6 +359,13 @@ bool MainWindow::InitializeUI()
|
|||
QAction *actionClose = new QAction(QIcon(":/icons/close.png"), tr("Close"), this);
|
||||
actionClose->setToolTip(tr("Close Application"));
|
||||
|
||||
//添加logo
|
||||
QLabel *logoLabel = new QLabel(this);
|
||||
QPixmap pixmap(":/icons/logo-en.png"); // 替换为实际图片路径
|
||||
logoLabel->setPixmap(pixmap.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
toolBar->addWidget(logoLabel);
|
||||
toolBar->addSeparator();
|
||||
|
||||
//添加按钮
|
||||
toolBar->addAction(actionRead);
|
||||
toolBar->addSeparator();
|
||||
|
@ -288,25 +376,26 @@ bool MainWindow::InitializeUI()
|
|||
toolBar->addWidget(spacer);
|
||||
|
||||
// 添加中央标签
|
||||
QLabel *label = new QLabel(tr("综合电源柜监测"), this);
|
||||
QLabel *label = new QLabel(tr("Integrated Power Cabinet Monitoring"), this);
|
||||
|
||||
// 加载字体
|
||||
int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf");
|
||||
if (fontId == -1)
|
||||
{
|
||||
qDebug() << "字体加载失败";
|
||||
return -1;
|
||||
}
|
||||
// // 加载字体
|
||||
// int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf");
|
||||
// if (fontId == -1)
|
||||
// {
|
||||
// ui->statusbar->showMessage(tr("Failed to load font"));
|
||||
// }
|
||||
//QFont customFont("Alimama DongFangDaKai", 48);
|
||||
//customFont.setBold(true);
|
||||
//label->setFont(customFont);
|
||||
//label->setStyleSheet("color: #2E86C1;");
|
||||
label->setStyleSheet(
|
||||
"QLabel {"
|
||||
" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
|
||||
//" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
|
||||
" font-family: 'Arial';" // 需确保字体已加载
|
||||
" font-size: 52px;"
|
||||
" color: #2E86C1;"
|
||||
//" font-weight: bold;"
|
||||
" font-weight: bold;"
|
||||
" font-style: black;"
|
||||
"}"
|
||||
);
|
||||
toolBar->addWidget(label);
|
||||
|
@ -327,17 +416,20 @@ bool MainWindow::InitializeUI()
|
|||
connect(actionSetting, &QAction::triggered, this, &MainWindow::SettingSerialPort);
|
||||
connect(actionRead, &QAction::triggered, this, &MainWindow::ReadSerialPortData);
|
||||
|
||||
ui->statusbar->showMessage(tr("Ready"), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::InitializeModbus()
|
||||
{
|
||||
if (m_bInitializeModbus)
|
||||
return true;
|
||||
|
||||
QString appDir = QCoreApplication::applicationDirPath();
|
||||
QString iniFilePath = appDir + QString::fromStdString("/emsshower.ini");
|
||||
|
||||
getConfiguration(iniFilePath);
|
||||
|
||||
m_bInitializeModbus = true;
|
||||
switch (m_modbus_type)
|
||||
{
|
||||
case 0:
|
||||
|
@ -413,7 +505,11 @@ bool MainWindow::InitializeTcp()
|
|||
|
||||
bool MainWindow::readRegister(int addr,int nb,uint16_t* dest)
|
||||
{
|
||||
InitializeModbus();
|
||||
if(!InitializeModbus()) //这里有问题,如果是虚拟串口,连接的通常会返回成功
|
||||
{
|
||||
ui->statusbar->showMessage(tr("Failed to open Modbus device,Check modbus connection please!")); //打开MODBUS设备失败,请检查设备连接情况!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto it = m_SlaveData.begin(); it != m_SlaveData.end(); ++it)
|
||||
{
|
||||
|
@ -443,16 +539,17 @@ bool MainWindow::readRegister(int addr,int nb,uint16_t* dest)
|
|||
{
|
||||
TemperatureData* pData = (TemperatureData*)pDevice;
|
||||
assert(pData);
|
||||
QString value;
|
||||
if (pData->bDecodeTemp)
|
||||
OpenJson json;
|
||||
if(CreateJson(pData,json))
|
||||
{
|
||||
//ui->txt_content_1->append(QString(tr("温度:%1\n湿度: %2\n露点: %3\n")).arg(pData->TempValue).arg(pData->HumidityValue).arg(pData->DewPointValue));
|
||||
//m_panel_labels[0]->setText(QString(tr("温度: %1\n湿度: %2\n露点: %3\n")).arg(pData->TempValue).arg(pData->HumidityValue).arg(pData->DewPointValue));
|
||||
if(pData->bDecodeTemp)
|
||||
m_pTemperaturePanel->UpdateData(json);
|
||||
if(pData->bDecodeAlarm)
|
||||
m_pAlarmPanel->UpdateAlarm(json);
|
||||
}
|
||||
if (pData->bDecodeAlarm)
|
||||
else
|
||||
{
|
||||
//ui->txt_content_1->append(QString(tr("高温告警: %1\n低温告警: %2\n湿度告警: %3\n")).arg(pData->TempHighAlarm).arg(pData->TempLowAlarm).arg(pData->HumidityHighAlarm));
|
||||
//m_panel_labels[0]->setText(QString(tr("高温告警: %1\n低温告警: %2\n湿度告警: %3\n")).arg(pData->TempHighAlarm).arg(pData->TempLowAlarm).arg(pData->HumidityHighAlarm));
|
||||
ui->statusbar->showMessage(tr("Failed to decode temperaure data")); //解析温度数据失败!"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,6 +597,26 @@ void MainWindow::startAsyncProcess(const QVector<uint16_t>& array,int slave_id,i
|
|||
|
||||
|
||||
void MainWindow::ReadSerialPortData()
|
||||
{
|
||||
if (!m_pTimer)
|
||||
m_pTimer = new QTimer(this);
|
||||
|
||||
if (m_pTimer->isActive())
|
||||
{
|
||||
m_pTimer->stop();
|
||||
ui->statusbar->showMessage(tr("Stop Reading"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTimer->setInterval(10000); // 10秒
|
||||
connect(m_pTimer, &QTimer::timeout, this, &MainWindow::onTimeout);
|
||||
ui->statusbar->showMessage(tr("Begin Readding"));
|
||||
m_pTimer->start();
|
||||
onTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onTimeout()
|
||||
{
|
||||
readRegister(0,0,0);
|
||||
}
|
||||
|
@ -508,11 +625,98 @@ void MainWindow::SettingSerialPort()
|
|||
{
|
||||
FormSerialPortSettingDialog* dlg = new FormSerialPortSettingDialog(this);
|
||||
dlg->setWindowFlags(dlg->windowFlags()&~(Qt::WindowMinMaxButtonsHint|Qt::WindowContextHelpButtonHint));
|
||||
//dlg.setModal(true);
|
||||
//dlg->show();
|
||||
if(dlg->exec() == QDialog::Accepted)
|
||||
QMessageBox::information(this, "OK Clicked", "Button 1 was clicked!");
|
||||
else
|
||||
QMessageBox::information(this, "Cancel Clicked", "Cancel was clicked!");
|
||||
dlg->exec();
|
||||
|
||||
// if(dlg->exec() == QDialog::Accepted)
|
||||
// QMessageBox::information(this, "OK Clicked", "Button 1 was clicked!");
|
||||
// else
|
||||
// QMessageBox::information(this, "Cancel Clicked", "Cancel was clicked!");
|
||||
}
|
||||
|
||||
bool MainWindow::CreateJson(DeviceData* pData,OpenJson& json)
|
||||
{
|
||||
int data_type = pData->m_device_type;
|
||||
if (data_type == 81) //根据协议定义的设备id进行分类,参考DeviceData定义
|
||||
{
|
||||
TemperatureData* pTempData = (TemperatureData*)pData;
|
||||
if (pTempData->bDecodeTemp)
|
||||
{
|
||||
json["panel_type"] = CustomDisplayPanel::PANEL_TEMPERATURE;
|
||||
|
||||
auto& nodeLabel = json["text_panel"];
|
||||
nodeLabel[0]["value"] = pTempData->m_device_online_state;
|
||||
nodeLabel[0]["title"] = "Online";
|
||||
|
||||
nodeLabel[1]["value"] = pTempData->TempValue;
|
||||
nodeLabel[1]["title"] = "Temp(℃)";
|
||||
|
||||
nodeLabel[2]["value"] = pTempData->HumidityValue;
|
||||
nodeLabel[2]["title"] = "RH (%) ";
|
||||
|
||||
auto& nodeTable = json["table"];
|
||||
int i = 0;
|
||||
|
||||
nodeTable[i]["value"] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss").toStdString();
|
||||
nodeTable[i]["signal"] = "Time";
|
||||
|
||||
i++;
|
||||
nodeTable[i]["value"] = pTempData->DewPointValue;
|
||||
nodeTable[i]["signal"] = "Dew Point";
|
||||
|
||||
i++;
|
||||
nodeTable[i]["value"] = pTempData->DO;
|
||||
nodeTable[i]["signal"] = "DO";
|
||||
|
||||
i++;
|
||||
nodeTable[i]["value"] = pTempData->DI1;
|
||||
nodeTable[i]["signal"] = "DI1";
|
||||
|
||||
i++;
|
||||
nodeTable[i]["value"] = pTempData->DI2;
|
||||
nodeTable[i]["signal"] = "DI2";
|
||||
|
||||
std::string a = json.encode();
|
||||
|
||||
qDebug() << QString::fromStdString(a);
|
||||
}
|
||||
|
||||
if (pTempData->bDecodeAlarm)
|
||||
{
|
||||
json["panel_type"] = CustomDisplayPanel::PANEL_ALARM;
|
||||
auto& nodeTable = json["alarm"];
|
||||
|
||||
int i = -1;
|
||||
if(pTempData->TempHighAlarm != 0)
|
||||
{
|
||||
i++;
|
||||
nodeTable[i]["time"] = QDateTime::currentDateTime().toString("MM-dd HH:mm:ss").toStdString();
|
||||
nodeTable[i]["signal"] = "High Temperature";
|
||||
nodeTable[i]["value"] = pTempData->TempHighAlarm;
|
||||
}
|
||||
|
||||
if(pTempData->TempLowAlarm != 0)
|
||||
{
|
||||
i++;
|
||||
nodeTable[i]["time"] = QDateTime::currentDateTime().toString("MM-dd HH:mm:ss").toStdString();
|
||||
nodeTable[i]["signal"] = "High Temperature";
|
||||
nodeTable[i]["value"] = pTempData->TempLowAlarm;
|
||||
}
|
||||
|
||||
if(pTempData->HumidityHighAlarm != 0)
|
||||
{
|
||||
i++;
|
||||
nodeTable[i]["time"] = QDateTime::currentDateTime().toString("MM-dd HH:mm:ss").toStdString();
|
||||
nodeTable[i]["signal"] = "High Humidity";
|
||||
nodeTable[i]["value"] = pTempData->HumidityHighAlarm;
|
||||
}
|
||||
|
||||
std::string a = json.encode();
|
||||
|
||||
qDebug() << QString::fromStdString(a);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -5,10 +5,15 @@
|
|||
#include <QSettings>
|
||||
#include <QVector>
|
||||
#include <QLabel>
|
||||
#include <QTimer>
|
||||
|
||||
#include "libmodbus/modbus.h"
|
||||
#include "slave_define.h"
|
||||
|
||||
#include "openjson.h"
|
||||
|
||||
class CustomDisplayPanel;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui
|
||||
{
|
||||
|
@ -65,7 +70,6 @@ public:
|
|||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
|
||||
protected:
|
||||
void getConfiguration(QString iniFilePath);
|
||||
bool InitializeUI();
|
||||
|
@ -80,7 +84,7 @@ private:
|
|||
protected:
|
||||
modbus_t *m_pModbus;
|
||||
SlaveData m_SlaveData;
|
||||
|
||||
QTimer *m_pTimer;
|
||||
protected:
|
||||
QString m_version;
|
||||
int m_modbus_type;
|
||||
|
@ -93,10 +97,8 @@ protected:
|
|||
int m_modbus_stop;
|
||||
int m_modbus_slave_id;
|
||||
QSettings* m_pSettings;
|
||||
bool m_bInitializeModbus;
|
||||
|
||||
|
||||
protected:
|
||||
QVector<QLabel*> m_panel_labels;
|
||||
protected:
|
||||
//异步处理数据
|
||||
void startAsyncProcess(const QVector<uint16_t>& array,int slave_id,int start_addr,int quantity,DeviceData* pData);
|
||||
|
@ -104,6 +106,20 @@ protected:
|
|||
private slots:
|
||||
void ReadSerialPortData();
|
||||
void SettingSerialPort();
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
CustomDisplayPanel* m_pTemperaturePanel; //温湿度显示
|
||||
CustomDisplayPanel* m_pBatteryPanel; //电池显示
|
||||
CustomDisplayPanel* m_pPowerPanel; //电源显示
|
||||
CustomDisplayPanel* m_pACPanel; //空调显示
|
||||
CustomDisplayPanel* m_pHomePanel; //主柜子信息
|
||||
CustomDisplayPanel* m_pAlarmPanel; //告警
|
||||
CustomDisplayPanel* m_pInverterPanel; //逆变器
|
||||
CustomDisplayPanel* m_pPVPanel; //太阳能
|
||||
|
||||
private:
|
||||
bool CreateJson(DeviceData* pData,OpenJson& json);
|
||||
|
||||
signals:
|
||||
// 处理进度信号
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2023-, openlinyou, <linyouhappy@outlook.com>
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef HEADER_OPEN_JSON_H
|
||||
#define HEADER_OPEN_JSON_H
|
||||
|
||||
#include <string>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable: 4251 )
|
||||
# if _MSC_VER >= 1600 || defined(__MINGW32__)
|
||||
# else
|
||||
# if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
# else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
# endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# endif
|
||||
#endif // _MSC_VER
|
||||
|
||||
//#pragma warning(disable:4100)
|
||||
|
||||
class OpenJson
|
||||
{
|
||||
enum JsonType
|
||||
{
|
||||
EMPTY = 0,
|
||||
STRING,
|
||||
NUMBER,
|
||||
OBJECT,
|
||||
ARRAY,
|
||||
UNKNOWN
|
||||
};
|
||||
class Box
|
||||
{
|
||||
std::vector<OpenJson*> childs_;
|
||||
public:
|
||||
Box();
|
||||
~Box();
|
||||
inline void clear()
|
||||
{
|
||||
childs_.clear();
|
||||
}
|
||||
inline bool empty()
|
||||
{
|
||||
return childs_.empty();
|
||||
}
|
||||
inline size_t size()
|
||||
{
|
||||
return childs_.size();
|
||||
}
|
||||
inline void add(OpenJson* node)
|
||||
{
|
||||
childs_.push_back(node);
|
||||
}
|
||||
inline OpenJson* operator[](size_t idx)
|
||||
{
|
||||
return childs_[idx];
|
||||
}
|
||||
bool remove(OpenJson* node);
|
||||
friend class OpenJson;
|
||||
};
|
||||
class Context
|
||||
{
|
||||
char* data_;
|
||||
size_t size_;
|
||||
size_t offset_;
|
||||
|
||||
OpenJson* root_;
|
||||
std::string rbuffer_;
|
||||
std::string wbuffer_;
|
||||
|
||||
std::string stringNull_;
|
||||
public:
|
||||
Context();
|
||||
~Context();
|
||||
void startRead();
|
||||
void startWrite();
|
||||
friend class OpenJson;
|
||||
};
|
||||
class Segment
|
||||
{
|
||||
public:
|
||||
enum SegmentType
|
||||
{
|
||||
NIL = 0,
|
||||
BOOL,
|
||||
INT32,
|
||||
INT64,
|
||||
DOUBLE,
|
||||
STRING
|
||||
};
|
||||
SegmentType type_;
|
||||
std::string content_;
|
||||
union
|
||||
{
|
||||
bool bool_;
|
||||
int32_t int32_;
|
||||
int64_t int64_;
|
||||
double double_;
|
||||
} value_;
|
||||
|
||||
Segment(SegmentType type = NIL);
|
||||
~Segment();
|
||||
|
||||
void clear();
|
||||
void toString();
|
||||
void setType(SegmentType type);
|
||||
};
|
||||
|
||||
JsonType type_;
|
||||
Context* context_;
|
||||
Context* wcontext_;
|
||||
size_t idx_;
|
||||
size_t len_;
|
||||
Box* box_;
|
||||
OpenJson* key_;
|
||||
Segment* segment_;
|
||||
|
||||
void trimSpace();
|
||||
bool makeRContext();
|
||||
OpenJson* createNode(unsigned char code);
|
||||
JsonType codeToType(unsigned char code);
|
||||
unsigned char getCharCode();
|
||||
unsigned char getChar();
|
||||
unsigned char checkCode(unsigned char charCode);
|
||||
size_t searchCode(unsigned char charCode);
|
||||
void throwError(const char* errMsg);
|
||||
|
||||
const char* data();
|
||||
int32_t stringToInt32();
|
||||
int64_t stringToInt64();
|
||||
double stringToDouble();
|
||||
|
||||
OpenJson& array(size_t idx);
|
||||
OpenJson& object(const char* key);
|
||||
void addNode(OpenJson* node);
|
||||
void removeNode(size_t idx);
|
||||
void removeNode(const char* key);
|
||||
OpenJson(OpenJson& /*json*/) {}
|
||||
OpenJson(const OpenJson& /*json*/) {}
|
||||
void operator=(OpenJson& /*json*/) {}
|
||||
void operator=(const OpenJson& /*json*/) {}
|
||||
|
||||
const std::string& emptyString();
|
||||
static OpenJson NodeNull;
|
||||
static std::string StringNull;
|
||||
public:
|
||||
OpenJson(JsonType type = EMPTY);
|
||||
~OpenJson();
|
||||
|
||||
inline size_t size()
|
||||
{
|
||||
return box_ ? box_->size() : 0;
|
||||
}
|
||||
inline bool empty()
|
||||
{
|
||||
return box_ ? box_->empty() : true;
|
||||
}
|
||||
inline OpenJson& operator[] (int idx)
|
||||
{
|
||||
return array(idx);
|
||||
}
|
||||
inline OpenJson& operator[] (size_t idx)
|
||||
{
|
||||
return array(idx);
|
||||
}
|
||||
inline OpenJson& operator[] (const char* key)
|
||||
{
|
||||
return object(key);
|
||||
}
|
||||
inline OpenJson& operator[] (const std::string& key)
|
||||
{
|
||||
return object(key.c_str());
|
||||
}
|
||||
|
||||
inline void remove(int idx)
|
||||
{
|
||||
removeNode(idx);
|
||||
}
|
||||
inline void remove(size_t idx)
|
||||
{
|
||||
removeNode(idx);
|
||||
}
|
||||
inline void remove(const char* key)
|
||||
{
|
||||
removeNode(key);
|
||||
}
|
||||
inline void remove(const std::string& key)
|
||||
{
|
||||
removeNode(key.c_str());
|
||||
}
|
||||
void clear();
|
||||
|
||||
inline bool isNull()
|
||||
{
|
||||
return type_ == EMPTY;
|
||||
}
|
||||
inline bool isNumber()
|
||||
{
|
||||
return type_ == NUMBER;
|
||||
}
|
||||
inline bool isString()
|
||||
{
|
||||
return type_ == STRING;
|
||||
}
|
||||
inline bool isObject()
|
||||
{
|
||||
return type_ == OBJECT;
|
||||
}
|
||||
inline bool isArray()
|
||||
{
|
||||
return type_ == ARRAY;
|
||||
}
|
||||
|
||||
bool b(bool def = false);
|
||||
int32_t i32(int32_t def = 0);
|
||||
int64_t i64(int64_t def = 0);
|
||||
double d(double def = 0);
|
||||
const std::string& s();
|
||||
const std::string& key();
|
||||
|
||||
void operator=(bool val);
|
||||
void operator=(int32_t val);
|
||||
void operator=(uint32_t val);
|
||||
void operator=(int64_t val);
|
||||
void operator=(uint64_t val);
|
||||
void operator=(double val);
|
||||
void operator=(const char* val);
|
||||
void operator=(const std::string& val);
|
||||
|
||||
bool decode(const std::string& buffer);
|
||||
bool decodeFile(const std::string& filePath);
|
||||
const std::string& encode();
|
||||
void encodeFile(const std::string& filePath);
|
||||
|
||||
static void EnableLog(bool enable);
|
||||
private:
|
||||
static bool EnableLog_;
|
||||
static void Log(const char* format, ...);
|
||||
void read(Context* context, bool isRoot = false);
|
||||
void readNumber();
|
||||
void readString();
|
||||
void readObject();
|
||||
void readArray();
|
||||
|
||||
void write(Context* context, bool isRoot = false);
|
||||
void writeNumber();
|
||||
void writeString();
|
||||
void writeObject();
|
||||
void writeArray();
|
||||
};
|
||||
|
||||
|
||||
#endif /* HEADER_OPEN_JSON_H */
|
|
@ -25,5 +25,23 @@
|
|||
<file>icons/up.png</file>
|
||||
<file>icons/warn.png</file>
|
||||
<file>fonts/Alimama_DongFangDaKai_Regular.ttf</file>
|
||||
<file>icons/main_power.png</file>
|
||||
<file>icons/main_ac.png</file>
|
||||
<file>icons/main_battery.png</file>
|
||||
<file>icons/main_cab.png</file>
|
||||
<file>icons/main_door.png</file>
|
||||
<file>icons/main_fan.png</file>
|
||||
<file>icons/main_fire.png</file>
|
||||
<file>icons/main_invertor.png</file>
|
||||
<file>icons/main_multi_cab.png</file>
|
||||
<file>icons/main_peidian.png</file>
|
||||
<file>icons/main_pv.png</file>
|
||||
<file>icons/main_temp.png</file>
|
||||
<file>icons/main_thunder.png</file>
|
||||
<file>icons/main_video.png</file>
|
||||
<file>icons/main_water.png</file>
|
||||
<file>icons/main_UPS.png</file>
|
||||
<file>icons/main_alarm.png</file>
|
||||
<file>icons/logo-en.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#include "frmgaugeweather.h"
|
||||
#include "ui_frmgaugeweather.h"
|
||||
|
||||
frmGaugeWeather::frmGaugeWeather(QWidget *parent) : QWidget(parent), ui(new Ui::frmGaugeWeather)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->initForm();
|
||||
}
|
||||
|
||||
frmGaugeWeather::~frmGaugeWeather()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void frmGaugeWeather::initForm()
|
||||
{
|
||||
ui->widget->setStyleSheet("QWidget#widget{border-image: url(:/image/bg2.jpg);}");
|
||||
ui->horizontalSlider1->setValue(65);
|
||||
ui->horizontalSlider2->setValue(28);
|
||||
}
|
||||
|
||||
void frmGaugeWeather::on_horizontalSlider1_valueChanged(int value)
|
||||
{
|
||||
ui->gaugeWeather->setOuterValue(value);
|
||||
}
|
||||
|
||||
void frmGaugeWeather::on_horizontalSlider2_valueChanged(int value)
|
||||
{
|
||||
ui->gaugeWeather->setInnerValue(value);
|
||||
}
|
||||
|
||||
void frmGaugeWeather::on_comboBox_currentIndexChanged(int index)
|
||||
{
|
||||
GaugeWeather::WeatherType type = (GaugeWeather::WeatherType)index;
|
||||
ui->gaugeWeather->setWeatherType(type);
|
||||
}
|
||||
|
||||
void frmGaugeWeather::on_ckAnimation_stateChanged(int arg1)
|
||||
{
|
||||
ui->gaugeWeather->setAnimation(arg1 != 0);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef FRMGAUGEWEATHER_H
|
||||
#define FRMGAUGEWEATHER_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPainterPath>
|
||||
|
||||
namespace Ui {
|
||||
class frmGaugeWeather;
|
||||
}
|
||||
|
||||
class frmGaugeWeather : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit frmGaugeWeather(QWidget *parent = 0);
|
||||
~frmGaugeWeather();
|
||||
|
||||
private:
|
||||
Ui::frmGaugeWeather *ui;
|
||||
|
||||
private slots:
|
||||
void initForm();
|
||||
void on_horizontalSlider1_valueChanged(int value);
|
||||
void on_horizontalSlider2_valueChanged(int value);
|
||||
void on_comboBox_currentIndexChanged(int index);
|
||||
void on_ckAnimation_stateChanged(int arg1);
|
||||
};
|
||||
|
||||
#endif // FRMGAUGEWEATHER_H
|
|
@ -0,0 +1,135 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>frmGaugeWeather</class>
|
||||
<widget class="QWidget" name="frmGaugeWeather">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>455</width>
|
||||
<height>278</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="GaugeWeather" name="gaugeWeather" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider1">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider2">
|
||||
<property name="minimum">
|
||||
<number>-50</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ckAnimation">
|
||||
<property name="text">
|
||||
<string>动画</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>晴</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>雨</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>雪</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>多云</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>风</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>雪雨</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>冰雹</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>闪电</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>雾</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>局部多云</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>GaugeWeather</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gaugeweather.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,951 @@
|
|||
#pragma execution_character_set("utf-8")
|
||||
|
||||
#include "gaugeweather.h"
|
||||
//#include "qsvgrenderer.h"
|
||||
#include "qpainter.h"
|
||||
#include <QPainterPath>
|
||||
#include "qmath.h"
|
||||
#include "qtimer.h"
|
||||
#include "qfile.h"
|
||||
#include "qdebug.h"
|
||||
|
||||
GaugeWeather::GaugeWeather(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
outerMinValue = 0;
|
||||
outerMaxValue = 100;
|
||||
outerStartAngle = 0;
|
||||
outerEndAngle = 0;
|
||||
outerValue = 0;
|
||||
outerCurrValue = 0;
|
||||
outerRingBgColor = QColor(250, 250, 250);
|
||||
outerRingColor = QColor(34, 163, 169);
|
||||
|
||||
innerValue = 0;
|
||||
innerMinValue = -50;
|
||||
innerMaxValue = 50;
|
||||
innerStartAngle = 0;
|
||||
innerEndAngle = 135;
|
||||
innerCurrValue = 0;
|
||||
innerRingBgColor = QColor(250, 250, 250);
|
||||
innerRingNegativeColor = QColor(214, 5, 5);
|
||||
innerRingPositiveColor = QColor(0, 254, 254);
|
||||
|
||||
innerScaleMajor = 2;
|
||||
innerScaleMinor = 0;
|
||||
innerScaleColor = QColor(255, 255, 255);
|
||||
innerScaleNumColor = QColor(255, 255, 255);
|
||||
|
||||
centerPixMapNegativeColor = QColor(214, 5, 5);
|
||||
centerPixMapPositiveColor = QColor(0, 254, 254);
|
||||
|
||||
outerValueTextColor = QColor(34, 163, 169);
|
||||
innerNegativeValueTextColor = QColor(214, 5, 5);
|
||||
innerPositiveValueTextColor = QColor(0, 254, 254);
|
||||
|
||||
precision = 0;
|
||||
outerReverse = false;
|
||||
innerReverse = false;
|
||||
clockWise = true;
|
||||
|
||||
animation = false;
|
||||
animationStep = 2;
|
||||
weatherType = WeatherType_SUNNY;
|
||||
centerSvgPath = ":/svg/weather-sunny.svg";
|
||||
|
||||
outerTimer = new QTimer(this);
|
||||
outerTimer->setInterval(10);
|
||||
connect(outerTimer, SIGNAL(timeout()), this, SLOT(updateOuterValue()));
|
||||
|
||||
innerTimer = new QTimer(this);
|
||||
innerTimer->setInterval(10);
|
||||
connect(innerTimer, SIGNAL(timeout()), this, SLOT(updateInnerValue()));
|
||||
|
||||
setFont(QFont("Arial", 9));
|
||||
}
|
||||
|
||||
GaugeWeather::~GaugeWeather()
|
||||
{
|
||||
if (outerTimer->isActive())
|
||||
{
|
||||
outerTimer->stop();
|
||||
}
|
||||
|
||||
if(innerTimer->isActive())
|
||||
{
|
||||
innerTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::paintEvent(QPaintEvent *)
|
||||
{
|
||||
int width = this->width();
|
||||
int height = this->height();
|
||||
int side = qMin(width, height);
|
||||
|
||||
//绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
|
||||
QPainter painter(this);
|
||||
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||
painter.translate(width / 2, height / 2);
|
||||
painter.scale(side / 200.0, side / 200.0);
|
||||
|
||||
//绘制外环背景
|
||||
drawOuterRingBg(&painter);
|
||||
//绘制外环进度
|
||||
drawOuterRing(&painter);
|
||||
//绘制内环背景
|
||||
drawInnerRingBg(&painter);
|
||||
//绘制内环进度
|
||||
drawInnerRing(&painter);
|
||||
//绘制内环刻度值
|
||||
drawInnerRingScaleNum(&painter);
|
||||
//绘制中心图片
|
||||
drawCenterPixMap(&painter);
|
||||
//绘制数值
|
||||
drawValue(&painter);
|
||||
}
|
||||
|
||||
void GaugeWeather::drawOuterRingBg(QPainter *painter)
|
||||
{
|
||||
int radius = 99;
|
||||
painter->save();
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
//绘制圆弧方法绘制圆环
|
||||
int penWidth = 13;
|
||||
QRectF rect(-radius + penWidth / 2, -radius + penWidth / 2, radius * 2 - penWidth, radius * 2 - penWidth);
|
||||
//可以自行修改画笔的后三个参数,形成各种各样的效果,例如Qt::FlatCap改为Qt::RoundCap可以产生圆角效果
|
||||
QPen pen(outerRingBgColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle);
|
||||
|
||||
//计算总范围角度
|
||||
double angleAll = 360.0 - outerStartAngle - outerEndAngle;
|
||||
|
||||
//绘制总范围角度圆弧
|
||||
pen.setColor(outerRingBgColor);
|
||||
painter->setPen(pen);
|
||||
painter->drawArc(rect, (270 - outerStartAngle - angleAll) * 16, angleAll * 16);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void GaugeWeather::drawOuterRing(QPainter *painter)
|
||||
{
|
||||
int radius = 99;
|
||||
painter->save();
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
//绘制圆弧方法绘制圆环
|
||||
int penWidth = 13;
|
||||
QRectF rect(-radius + penWidth / 2, -radius + penWidth / 2, radius * 2 - penWidth, radius * 2 - penWidth);
|
||||
//可以自行修改画笔的后三个参数,形成各种各样的效果,例如Qt::FlatCap改为Qt::RoundCap可以产生圆角效果
|
||||
QPen pen(outerRingColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle);
|
||||
|
||||
//计算总范围角度,当前值范围角度,剩余值范围角度
|
||||
double angleAll = 360.0 - outerStartAngle - outerEndAngle;
|
||||
double angleCurrent = angleAll * ((outerCurrValue - outerMinValue) / (outerMaxValue - outerMinValue));
|
||||
|
||||
//绘制当前值饼圆
|
||||
painter->setPen(pen);
|
||||
painter->drawArc(rect, (270 - outerStartAngle - angleCurrent) * 16, angleCurrent * 16);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void GaugeWeather::drawInnerRingBg(QPainter *painter)
|
||||
{
|
||||
int radius = 77;
|
||||
painter->save();
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
double penWidth = 13;
|
||||
QPen pen(innerRingBgColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle);
|
||||
painter->setPen(pen);
|
||||
|
||||
double angleAll = 360.0 - innerStartAngle - innerEndAngle;
|
||||
QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
|
||||
|
||||
//零值以上背景
|
||||
painter->drawArc(rect, (270 - innerStartAngle - angleAll) * 16, angleAll * 16);
|
||||
//零值以下背景
|
||||
//painter->drawArc(rect,(270 -innerStartAngle - null2MinAngle) * 16 ,null2MinAngle * 16);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void GaugeWeather::drawInnerRing(QPainter *painter)
|
||||
{
|
||||
int radius = 77;
|
||||
painter->save();
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
int penWidth = 13.5;
|
||||
QPen pen(innerRingPositiveColor, penWidth, Qt::SolidLine, Qt::FlatCap, Qt::MPenJoinStyle);
|
||||
|
||||
double angleAll = 360.0 - innerStartAngle - innerEndAngle;
|
||||
double null2MinAngle = angleAll * (( 0 - innerMinValue) / (innerMaxValue - innerMinValue)); //零点所占的角度
|
||||
double nullUpAllAngle = angleAll - null2MinAngle; //正基本角度
|
||||
double currAngle;
|
||||
if(innerCurrValue >= 0)
|
||||
{
|
||||
//正角度
|
||||
pen.setColor(innerRingNegativeColor);
|
||||
currAngle = nullUpAllAngle * (innerCurrValue / innerMaxValue) * -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//负角度
|
||||
pen.setColor(innerRingPositiveColor);
|
||||
currAngle = null2MinAngle * (innerCurrValue / innerMinValue);
|
||||
}
|
||||
|
||||
painter->setPen(pen);
|
||||
|
||||
QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
|
||||
painter->drawArc(rect, (270 - innerStartAngle - null2MinAngle) * 16, currAngle * 16);
|
||||
|
||||
painter->restore();
|
||||
|
||||
}
|
||||
|
||||
void GaugeWeather::drawInnerRingScale(QPainter *painter)
|
||||
{
|
||||
int radius = 76;
|
||||
painter->save();
|
||||
painter->setPen(innerScaleColor);
|
||||
|
||||
painter->rotate(innerStartAngle);
|
||||
int steps = (innerScaleMajor * innerScaleMinor);
|
||||
double angleStep = (360.0 - innerStartAngle - innerEndAngle) / steps;
|
||||
QPen pen = painter->pen();
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
|
||||
for (int i = 0; i <= steps; i++)
|
||||
{
|
||||
if (i % innerScaleMinor == 0)
|
||||
{
|
||||
pen.setWidthF(1.5);
|
||||
painter->setPen(pen);
|
||||
painter->drawLine(0, radius - 12, 0, radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
pen.setWidthF(1.0);
|
||||
painter->setPen(pen);
|
||||
painter->drawLine(0, radius - 5, 0, radius);
|
||||
}
|
||||
|
||||
painter->rotate(angleStep);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void GaugeWeather::drawInnerRingScaleNum(QPainter *painter)
|
||||
{
|
||||
int radius = 60;
|
||||
painter->save();
|
||||
painter->setPen(innerScaleNumColor);
|
||||
|
||||
double startRad = (360 - innerStartAngle - 90) * (M_PI / 180);
|
||||
double deltaRad = (360 - innerStartAngle - innerEndAngle) * (M_PI / 180) / innerScaleMajor;
|
||||
|
||||
for (int i = 0; i <= innerScaleMajor; i++)
|
||||
{
|
||||
double sina = sin(startRad - i * deltaRad);
|
||||
double cosa = cos(startRad - i * deltaRad);
|
||||
double value = 1.0 * i * ((innerMaxValue - innerMinValue) / innerScaleMajor) + innerMinValue;
|
||||
|
||||
QString strValue = QString("%1").arg((double)value, 0, 'f', precision);
|
||||
double textWidth = fontMetrics().size(Qt::TextSingleLine,strValue).width();// .width(strValue);
|
||||
double textHeight = fontMetrics().height();
|
||||
int x = radius * cosa - textWidth / 2;
|
||||
int y = -radius * sina + textHeight / 4;
|
||||
painter->drawText(x, y, strValue);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void GaugeWeather::drawCenterPixMap(QPainter *painter)
|
||||
{
|
||||
painter->save();
|
||||
// int width_svg = 50;
|
||||
// int height_svg = 50;
|
||||
|
||||
// QFile file(centerSvgPath);
|
||||
// file.open(QIODevice::ReadOnly);
|
||||
// QByteArray baData = file.readAll();
|
||||
// //QDomDocument doc;
|
||||
// //doc.setContent(baData);
|
||||
// file.close();
|
||||
|
||||
// //正负角度切换不同颜色
|
||||
// if(innerCurrValue >= 0)
|
||||
// {
|
||||
// setColor(doc.documentElement(), "path", "fill", rgb2HexStr(centerPixMapNegativeColor));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// setColor(doc.documentElement(), "path", "fill", rgb2HexStr(centerPixMapPositiveColor));
|
||||
// }
|
||||
|
||||
// QSvgRenderer m_svgRender(doc.toByteArray());
|
||||
// m_svgRender.render(painter, QRectF(-width_svg, -height_svg / 2, width_svg, height_svg));
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void GaugeWeather::drawValue(QPainter *painter)
|
||||
{
|
||||
painter->save();
|
||||
|
||||
QFont font;
|
||||
font.setPixelSize(12);
|
||||
painter->setFont(font);
|
||||
painter->setPen(outerValueTextColor);
|
||||
|
||||
QFontMetrics fm = painter->fontMetrics();
|
||||
QString outerStrValue = QString(tr("湿度: %1%")).arg(QString::number(outerCurrValue, 'f', 0));
|
||||
QRectF titleRect(5, 0, fm.size(Qt::TextSingleLine,outerStrValue).width(),fm.height());//width(outerStrValue), fm.height());
|
||||
painter->drawText(titleRect, Qt::AlignHCenter | Qt::AlignTop, outerStrValue);
|
||||
if(innerCurrValue >= 0 )
|
||||
{
|
||||
painter->setPen(innerNegativeValueTextColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(innerPositiveValueTextColor);
|
||||
}
|
||||
|
||||
QString innerDir = innerCurrValue >= 0 ? "+" : "-";
|
||||
QString innerStrValue = QString(tr("温度: %1%2 ℃")).arg(innerDir).arg(QString::number(abs(innerCurrValue), 'f', 0));
|
||||
QRectF innerTitleRect(5, 0, fm.size(Qt::TextSingleLine,innerStrValue).width(),-fm.height()); //fm.width(innerStrValue), -fm.height());
|
||||
painter->drawText(innerTitleRect, Qt::AlignHCenter | Qt::AlignVCenter, innerStrValue);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QString GaugeWeather::rgb2HexStr(const QColor &color)
|
||||
{
|
||||
QString redStr = QString("%1").arg(color.red(), 2, 16, QChar('0'));
|
||||
QString greenStr = QString("%1").arg(color.green(), 2, 16, QChar('0'));
|
||||
QString blueStr = QString("%1").arg(color.blue(), 2, 16, QChar('0'));
|
||||
QString key = "#" + redStr + greenStr + blueStr;
|
||||
return key;
|
||||
}
|
||||
|
||||
// void GaugeWeather::setColor(QDomElement elem, QString strtagname, QString strattr, QString strattrval)
|
||||
// {
|
||||
// if (elem.tagName().compare(strtagname) == 0) {
|
||||
// elem.setAttribute(strattr, strattrval);
|
||||
// }
|
||||
|
||||
// for (int i = 0; i < elem.childNodes().count(); i++) {
|
||||
// if (!elem.childNodes().at(i).isElement()) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// setColor(elem.childNodes().at(i).toElement(), strtagname, strattr, strattrval);
|
||||
// }
|
||||
// }
|
||||
|
||||
double GaugeWeather::getOuterValue() const
|
||||
{
|
||||
return this->outerValue;
|
||||
}
|
||||
|
||||
double GaugeWeather::getOuterMinValue() const
|
||||
{
|
||||
return this->outerMinValue;
|
||||
}
|
||||
|
||||
double GaugeWeather::getOuterMaxValue() const
|
||||
{
|
||||
return this->outerMaxValue;
|
||||
}
|
||||
|
||||
int GaugeWeather::getOuterStartAngle() const
|
||||
{
|
||||
return this->outerStartAngle;
|
||||
}
|
||||
|
||||
int GaugeWeather::getOuterEndAngle() const
|
||||
{
|
||||
return this->outerEndAngle;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getOuterRingBgColor() const
|
||||
{
|
||||
return this->outerRingBgColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getOuterRingColor() const
|
||||
{
|
||||
return this->outerRingColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getOuterValueTextColor() const
|
||||
{
|
||||
return this->outerValueTextColor;
|
||||
}
|
||||
|
||||
double GaugeWeather::getInnerMinValue() const
|
||||
{
|
||||
return this->innerMinValue;
|
||||
}
|
||||
|
||||
double GaugeWeather::getInnerMaxValue() const
|
||||
{
|
||||
return this->innerMaxValue;
|
||||
}
|
||||
|
||||
double GaugeWeather::getInnerValue() const
|
||||
{
|
||||
return this->innerValue;
|
||||
}
|
||||
|
||||
int GaugeWeather::getInnerStartAngle() const
|
||||
{
|
||||
return this->innerStartAngle;
|
||||
}
|
||||
|
||||
int GaugeWeather::getInnerEndAngle() const
|
||||
{
|
||||
return this->innerEndAngle;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getInnerRingBgColor() const
|
||||
{
|
||||
return this->innerRingBgColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getInnerNegativeColor() const
|
||||
{
|
||||
return this->innerRingNegativeColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getInnerPositiveColor() const
|
||||
{
|
||||
return this->innerRingPositiveColor;
|
||||
}
|
||||
|
||||
int GaugeWeather::getInnerScaleMajor() const
|
||||
{
|
||||
return this->innerScaleMajor;
|
||||
}
|
||||
|
||||
int GaugeWeather::getInnerScaleMinor() const
|
||||
{
|
||||
return this->innerScaleMinor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getInnerScaleColor() const
|
||||
{
|
||||
return this->innerScaleColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getInnerScaleNumColor() const
|
||||
{
|
||||
return this->innerScaleNumColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getInnerNegativeValueTextColor() const
|
||||
{
|
||||
return this->innerNegativeValueTextColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getInnerPositiveValueTextColor() const
|
||||
{
|
||||
return this->innerPositiveValueTextColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getCenterPixMapNegativeColor() const
|
||||
{
|
||||
return this->centerPixMapNegativeColor;
|
||||
}
|
||||
|
||||
QColor GaugeWeather::getCenterPixMapPositiveColor() const
|
||||
{
|
||||
return this->centerPixMapPositiveColor;
|
||||
}
|
||||
|
||||
bool GaugeWeather::getAnimation() const
|
||||
{
|
||||
return this->animation;
|
||||
}
|
||||
|
||||
double GaugeWeather::getAnimationStep() const
|
||||
{
|
||||
return this->animationStep;
|
||||
}
|
||||
|
||||
GaugeWeather::WeatherType GaugeWeather::getWeatherType() const
|
||||
{
|
||||
return this->weatherType;
|
||||
}
|
||||
|
||||
QSize GaugeWeather::sizeHint() const
|
||||
{
|
||||
return QSize(200, 200);
|
||||
}
|
||||
|
||||
QSize GaugeWeather::minimumSizeHint() const
|
||||
{
|
||||
return QSize(50, 50);
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterRange(double minValue, double maxValue)
|
||||
{
|
||||
//如果最小值大于或者等于最大值则不设置
|
||||
if (minValue >= maxValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->outerMinValue = minValue;
|
||||
this->outerMaxValue = maxValue;
|
||||
|
||||
//如果目标值不在范围值内,则重新设置目标值
|
||||
if (outerValue < minValue || outerValue > maxValue)
|
||||
{
|
||||
setOuterValue(outerValue);
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterMinValue(double value)
|
||||
{
|
||||
setOuterRange(value, outerMaxValue);
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterMaxValue(double value)
|
||||
{
|
||||
setOuterRange(outerMinValue, value);
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterValue(double value)
|
||||
{
|
||||
//值小于最小值或者值大于最大值或者值和当前值一致则无需处理
|
||||
if (value < outerMinValue || value > outerMaxValue || value == this->outerValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (value > this->outerValue)
|
||||
{
|
||||
outerReverse = false;
|
||||
}
|
||||
else if (value < this->outerValue)
|
||||
{
|
||||
outerReverse = true;
|
||||
}
|
||||
|
||||
this->outerValue = value;
|
||||
emit valueChanged(value);
|
||||
|
||||
if (!animation)
|
||||
{
|
||||
outerCurrValue = this->outerValue;
|
||||
this->update();
|
||||
}
|
||||
else
|
||||
{
|
||||
outerTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterStartAngle(int startAngle)
|
||||
{
|
||||
if (this->outerStartAngle != startAngle)
|
||||
{
|
||||
this->outerStartAngle = startAngle;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterEndAngle(int endAngle)
|
||||
{
|
||||
if (this->outerEndAngle != endAngle)
|
||||
{
|
||||
this->outerEndAngle = endAngle;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterRingBgColor(const QColor &color)
|
||||
{
|
||||
if (this->outerRingBgColor != color)
|
||||
{
|
||||
this->outerRingBgColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterRingColor(const QColor &color)
|
||||
{
|
||||
if (this->outerRingColor != color)
|
||||
{
|
||||
this->outerRingColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setOuterValueTextColor(const QColor &color)
|
||||
{
|
||||
if (this->outerValueTextColor != color)
|
||||
{
|
||||
this->outerValueTextColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerRange(double minValue, double maxValue)
|
||||
{
|
||||
//如果最小值大于或者等于最大值则不设置
|
||||
if (minValue >= maxValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->innerMinValue = minValue;
|
||||
this->innerMaxValue = maxValue;
|
||||
|
||||
//如果目标值不在范围值内,则重新设置目标值
|
||||
if (innerValue < minValue || innerValue > maxValue)
|
||||
{
|
||||
setInnerValue(innerValue);
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerMinValue(double value)
|
||||
{
|
||||
setInnerRange(value, innerMaxValue);
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerMaxValue(double value)
|
||||
{
|
||||
setInnerRange(innerMinValue, value);
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerValue(double value)
|
||||
{
|
||||
//值小于最小值或者值大于最大值或者值和当前值一致则无需处理
|
||||
if (value < innerMinValue || value > innerMaxValue || value == this->innerValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(this->innerValue >= 0)
|
||||
{
|
||||
clockWise = true;
|
||||
if(value < this->innerValue)
|
||||
{
|
||||
//如果要设置的值小于已有的值,需要回滚
|
||||
innerReverse = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
innerReverse = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clockWise = false;
|
||||
if(value > this->innerValue)
|
||||
{
|
||||
//如果要设置的值大于已有的值,需要回滚
|
||||
innerReverse = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
innerReverse = false;
|
||||
}
|
||||
}
|
||||
|
||||
this->innerValue = value;
|
||||
emit valueChanged(value);
|
||||
|
||||
if (!animation)
|
||||
{
|
||||
innerCurrValue = this->innerValue;
|
||||
this->update();
|
||||
}
|
||||
else
|
||||
{
|
||||
innerTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerStartAngle(int startAngle)
|
||||
{
|
||||
if (this->innerStartAngle != startAngle)
|
||||
{
|
||||
this->innerStartAngle = startAngle;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerEndAngle(int endAngle)
|
||||
{
|
||||
if (this->innerEndAngle != endAngle)
|
||||
{
|
||||
this->innerEndAngle = endAngle;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerRingBgColor(const QColor &color)
|
||||
{
|
||||
if (this->innerRingBgColor != color)
|
||||
{
|
||||
this->innerRingBgColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerNegativeColor(const QColor &color)
|
||||
{
|
||||
if (this->innerRingNegativeColor != color)
|
||||
{
|
||||
this->innerRingNegativeColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerPositiveColor(const QColor &color)
|
||||
{
|
||||
if (this->innerRingPositiveColor != color)
|
||||
{
|
||||
this->innerRingPositiveColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerScaleMajor(int value)
|
||||
{
|
||||
if (this->innerScaleMajor != value)
|
||||
{
|
||||
this->innerScaleMajor = value;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerScaleMinor(int value)
|
||||
{
|
||||
if (this->innerScaleMinor != value)
|
||||
{
|
||||
this->innerScaleMinor = value;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerScaleColor(const QColor &color)
|
||||
{
|
||||
if (this->innerScaleColor != color)
|
||||
{
|
||||
this->innerScaleColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerScaleNumColor(const QColor &color)
|
||||
{
|
||||
if (this->innerScaleNumColor != color)
|
||||
{
|
||||
this->innerScaleNumColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerNegativeValueTextColor(const QColor &color)
|
||||
{
|
||||
if (this->innerNegativeValueTextColor != color)
|
||||
{
|
||||
this->innerNegativeValueTextColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setInnerPositiveValueTextColor(const QColor &color)
|
||||
{
|
||||
if (this->innerPositiveValueTextColor != color)
|
||||
{
|
||||
this->innerPositiveValueTextColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setCenterPixMapNegativeColor(const QColor &color)
|
||||
{
|
||||
if (this->centerPixMapNegativeColor != color)
|
||||
{
|
||||
this->centerPixMapNegativeColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setCenterPixMapPositiveColor(const QColor &color)
|
||||
{
|
||||
if (this->centerPixMapPositiveColor != color)
|
||||
{
|
||||
this->centerPixMapPositiveColor = color;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setAnimation(bool animation)
|
||||
{
|
||||
if (this->animation != animation)
|
||||
{
|
||||
this->animation = animation;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setAnimationStep(double animationStep)
|
||||
{
|
||||
if (this->animationStep != animationStep)
|
||||
{
|
||||
this->animationStep = animationStep;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::setWeatherType(GaugeWeather::WeatherType &type)
|
||||
{
|
||||
if(this->weatherType != type)
|
||||
{
|
||||
this->weatherType = type;
|
||||
switch (type)
|
||||
{
|
||||
case WeatherType_SUNNY:
|
||||
centerSvgPath = ":/svg/weather-sunny.svg";
|
||||
break;
|
||||
case WeatherType_RAINY:
|
||||
centerSvgPath = ":/svg/weather-rainy.svg";
|
||||
break;
|
||||
case WeatherType_SNOWY:
|
||||
centerSvgPath = ":/svg/weather-snowy.svg";
|
||||
break;
|
||||
case WeatherType_CLOUDY:
|
||||
centerSvgPath = ":/svg/weather-cloudy.svg";
|
||||
break;
|
||||
case WeatherType_WINDY:
|
||||
centerSvgPath = ":/svg/weather-windy.svg";
|
||||
break;
|
||||
case WeatherType_SNOWY_RAINY:
|
||||
centerSvgPath = ":/svg/weather-snowy-rainy.svg";
|
||||
break;
|
||||
case WeatherType_HAIL:
|
||||
centerSvgPath = ":/svg/weather-hail.svg";
|
||||
break;
|
||||
case WeatherType_LIGHTNING:
|
||||
centerSvgPath = ":/svg/weather-lightning.svg";
|
||||
break;
|
||||
case WeatherType_FOG:
|
||||
centerSvgPath = ":/svg/weather-fog.svg";
|
||||
break;
|
||||
case WeatherType_PARTLYCLOUDY:
|
||||
centerSvgPath = ":/svg/weather-partlycloudy.svg";
|
||||
break;
|
||||
default:
|
||||
centerSvgPath = ":/svg/weather-sunny.svg";
|
||||
break;
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GaugeWeather::updateOuterValue()
|
||||
{
|
||||
if (!outerReverse)
|
||||
{
|
||||
if (outerCurrValue >= outerValue)
|
||||
{
|
||||
outerCurrValue = outerValue;
|
||||
outerTimer->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
outerCurrValue += animationStep;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outerCurrValue <= outerValue)
|
||||
{
|
||||
outerCurrValue = outerValue;
|
||||
outerTimer->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
outerCurrValue -= animationStep;
|
||||
}
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
|
||||
void GaugeWeather::updateInnerValue()
|
||||
{
|
||||
//currValue变成Value的过程
|
||||
if(clockWise)
|
||||
{
|
||||
//针对value大于零时,当currValue 小于 Value,需要回滚,否则前滚,
|
||||
if (!innerReverse)
|
||||
{
|
||||
if (innerCurrValue >= innerValue)
|
||||
{
|
||||
innerCurrValue = innerValue;
|
||||
innerTimer->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
innerCurrValue += animationStep;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (innerCurrValue <= innerValue)
|
||||
{
|
||||
innerCurrValue = innerValue;
|
||||
innerTimer->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
innerCurrValue -= animationStep;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//针对value大于零时,当currValue 大于 Value,需要回滚,否则前滚,
|
||||
if (!innerReverse)
|
||||
{
|
||||
if (innerCurrValue <= innerValue)
|
||||
{
|
||||
innerCurrValue = innerValue;
|
||||
innerTimer->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
innerCurrValue -= animationStep;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (innerCurrValue >= innerValue)
|
||||
{
|
||||
innerCurrValue = innerValue;
|
||||
innerTimer->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
innerCurrValue += animationStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
#ifndef GAUGEWEATHER_H
|
||||
#define GAUGEWEATHER_H
|
||||
|
||||
/**
|
||||
* 天气仪表盘控件 作者:东门吹雪(QQ:709102202) 整理:飞扬青云(QQ:517216493) 2019-4-23
|
||||
* 1:可设置两种值,比如温度+湿度
|
||||
* 2:可设置两种值的背景颜色+文字颜色
|
||||
* 3:可设置零度值左侧右侧两种颜色
|
||||
* 4:可设置圆的起始角度和结束角度
|
||||
* 5:可设置10种天气,晴天+雨天+阴天+大风等
|
||||
* 6:可设置各种其他颜色
|
||||
* 7:科设置是否启用动画显示进度以及动画步长
|
||||
*/
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPainterPath>
|
||||
//#include <QDomElement>
|
||||
|
||||
#ifdef quc
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
|
||||
#include <QtDesigner/QDesignerExportWidget>
|
||||
#else
|
||||
#include <QtUiPlugin/QDesignerExportWidget>
|
||||
#endif
|
||||
|
||||
class QDESIGNER_WIDGET_EXPORT GaugeWeather : public QWidget
|
||||
#else
|
||||
class GaugeWeather : public QWidget
|
||||
#endif
|
||||
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(WeatherType)
|
||||
|
||||
Q_PROPERTY(double outerValue READ getOuterValue WRITE setOuterValue)
|
||||
Q_PROPERTY(double outerMinValue READ getOuterMinValue WRITE setOuterMinValue)
|
||||
Q_PROPERTY(double outerMaxValue READ getOuterMaxValue WRITE setOuterMaxValue)
|
||||
|
||||
Q_PROPERTY(int outerStartAngle READ getOuterStartAngle WRITE setOuterStartAngle)
|
||||
Q_PROPERTY(int outerEndAngle READ getOuterEndAngle WRITE setOuterEndAngle)
|
||||
|
||||
Q_PROPERTY(QColor outerRingBgColor READ getOuterRingBgColor WRITE setOuterRingBgColor)
|
||||
Q_PROPERTY(QColor outerRingColor READ getOuterRingColor WRITE setOuterRingColor)
|
||||
|
||||
Q_PROPERTY(double innerValue READ getInnerValue WRITE setInnerValue)
|
||||
Q_PROPERTY(double innerMinValue READ getInnerMinValue WRITE setInnerMinValue)
|
||||
Q_PROPERTY(double innerMaxValue READ getInnerMaxValue WRITE setInnerMaxValue)
|
||||
|
||||
Q_PROPERTY(int innerStartAngle READ getInnerStartAngle WRITE setInnerStartAngle)
|
||||
Q_PROPERTY(int innerEndAngle READ getInnerEndAngle WRITE setInnerEndAngle)
|
||||
|
||||
Q_PROPERTY(QColor innerRingBgColor READ getInnerRingBgColor WRITE setInnerRingBgColor)
|
||||
Q_PROPERTY(QColor innerRingNegativeColor READ getInnerNegativeColor WRITE setInnerNegativeColor)
|
||||
Q_PROPERTY(QColor innerRingPositiveColor READ getInnerPositiveColor WRITE setInnerPositiveColor)
|
||||
|
||||
Q_PROPERTY(int innerScaleMajor READ getInnerScaleMajor WRITE setInnerScaleMajor)
|
||||
Q_PROPERTY(int innerScaleMinor READ getInnerScaleMinor WRITE setInnerScaleMinor)
|
||||
Q_PROPERTY(QColor innerScaleColor READ getInnerScaleColor WRITE setInnerScaleColor)
|
||||
Q_PROPERTY(QColor innerScaleNumColor READ getInnerScaleNumColor WRITE setInnerScaleNumColor)
|
||||
|
||||
Q_PROPERTY(QColor centerPixMapNegativeColor READ getCenterPixMapNegativeColor WRITE setCenterPixMapNegativeColor)
|
||||
Q_PROPERTY(QColor centerPixMapPositiveColor READ getCenterPixMapPositiveColor WRITE setCenterPixMapPositiveColor)
|
||||
|
||||
Q_PROPERTY(QColor outerValueTextColor READ getOuterValueTextColor WRITE setOuterValueTextColor)
|
||||
Q_PROPERTY(QColor innerNegativeValueTextColor READ getInnerNegativeValueTextColor WRITE setInnerNegativeValueTextColor)
|
||||
Q_PROPERTY(QColor innerPositiveValueTextColor READ getInnerPositiveValueTextColor WRITE setInnerPositiveValueTextColor)
|
||||
|
||||
Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
|
||||
Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep)
|
||||
Q_PROPERTY(WeatherType weatherType READ getWeatherType WRITE setWeatherType)
|
||||
|
||||
public:
|
||||
enum WeatherType
|
||||
{
|
||||
WeatherType_SUNNY = 0, //晴天
|
||||
WeatherType_RAINY = 1, //雨天
|
||||
WeatherType_SNOWY = 2, //雪天
|
||||
WeatherType_CLOUDY = 3, //多云
|
||||
WeatherType_WINDY = 4, //风
|
||||
WeatherType_SNOWY_RAINY = 5, //雪雨
|
||||
WeatherType_HAIL = 6, //冰雹
|
||||
WeatherType_LIGHTNING = 7, //闪电
|
||||
WeatherType_FOG = 8, //雾
|
||||
WeatherType_PARTLYCLOUDY = 9 //局部多云
|
||||
};
|
||||
|
||||
explicit GaugeWeather(QWidget *parent = 0);
|
||||
~GaugeWeather();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *);
|
||||
void drawOuterRingBg(QPainter *painter);
|
||||
void drawOuterRing(QPainter *painter);
|
||||
void drawInnerRingBg(QPainter *painter);
|
||||
void drawInnerRing(QPainter *painter);
|
||||
void drawInnerRingScale(QPainter *painter);
|
||||
void drawInnerRingScaleNum(QPainter *painter);
|
||||
void drawCenterPixMap(QPainter *painter);
|
||||
void drawValue(QPainter *painter);
|
||||
|
||||
private slots:
|
||||
void updateOuterValue(); //更新外圈数值
|
||||
void updateInnerValue(); //更新内圈数值
|
||||
|
||||
private:
|
||||
double outerMaxValue; //外圈最大值
|
||||
double outerMinValue; //外圈最小值
|
||||
double outerValue; //外圈值
|
||||
double outerCurrValue; //外圈当前值
|
||||
|
||||
int outerStartAngle; //外环开始旋转角度
|
||||
int outerEndAngle; //外环结束旋转角度
|
||||
|
||||
QColor outerRingBgColor; //外圈背景色
|
||||
QColor outerRingColor; //外圈当前色
|
||||
|
||||
double innerMaxValue; //内圈最大值
|
||||
double innerMinValue; //内圈最小值
|
||||
double innerValue; //内圈值
|
||||
double innerCurrValue; //内圈当前值
|
||||
|
||||
int innerStartAngle; //内环开始旋转角度
|
||||
int innerEndAngle; //内环结束旋转角度
|
||||
|
||||
QColor innerRingBgColor; //内圈背景色
|
||||
QColor innerRingNegativeColor; //内圈负值当前色
|
||||
QColor innerRingPositiveColor; //内圈正值当前色
|
||||
|
||||
int innerScaleMajor; //内环大刻度数量
|
||||
int innerScaleMinor; //内环小刻度数量
|
||||
QColor innerScaleColor; //内环刻度颜色
|
||||
QColor innerScaleNumColor; //内环刻度值颜色
|
||||
int precision; //精确度,小数点后几位
|
||||
|
||||
QColor centerPixMapNegativeColor; //中心图片颜色
|
||||
QColor centerPixMapPositiveColor; //中心图片颜色
|
||||
QString centerSvgPath; //当前svg图片路径
|
||||
WeatherType weatherType; //天气类型
|
||||
|
||||
QColor outerValueTextColor; //外环值文本颜色
|
||||
QColor innerNegativeValueTextColor; //内环正值文本颜色
|
||||
QColor innerPositiveValueTextColor; //内环负值文本颜色
|
||||
|
||||
bool animation; //是否启用动画显示
|
||||
double animationStep; //动画显示时步长
|
||||
|
||||
bool outerReverse; //是否往回走
|
||||
bool innerReverse; //是否往回走
|
||||
bool clockWise; //顺时针
|
||||
|
||||
QTimer *outerTimer; //外环定时器绘制动画
|
||||
QTimer *innerTimer; //内环定时器绘制动画
|
||||
|
||||
//将svg文件中的xml数据颜色替换
|
||||
//void setColor(QDomElement elem, QString strtagname, QString strattr, QString strattrval);
|
||||
QString rgb2HexStr(const QColor &color);
|
||||
|
||||
public:
|
||||
double getOuterMinValue() const;
|
||||
double getOuterMaxValue() const;
|
||||
double getOuterValue() const;
|
||||
int getOuterStartAngle() const;
|
||||
int getOuterEndAngle() const;
|
||||
|
||||
QColor getOuterRingBgColor() const;
|
||||
QColor getOuterRingColor() const;
|
||||
|
||||
double getInnerMaxValue() const;
|
||||
double getInnerMinValue() const;
|
||||
double getInnerValue() const;
|
||||
int getInnerStartAngle() const;
|
||||
int getInnerEndAngle() const;
|
||||
|
||||
QColor getInnerRingBgColor() const;
|
||||
QColor getInnerNegativeColor() const;
|
||||
QColor getInnerPositiveColor() const;
|
||||
|
||||
int getInnerScaleMajor() const;
|
||||
int getInnerScaleMinor() const;
|
||||
QColor getInnerScaleColor() const;
|
||||
QColor getInnerScaleNumColor() const;
|
||||
|
||||
bool getAnimation() const;
|
||||
double getAnimationStep() const;
|
||||
|
||||
WeatherType getWeatherType() const;
|
||||
|
||||
QColor getCenterPixMapNegativeColor() const;
|
||||
QColor getCenterPixMapPositiveColor() const;
|
||||
|
||||
QColor getOuterValueTextColor() const;
|
||||
QColor getInnerNegativeValueTextColor() const;
|
||||
QColor getInnerPositiveValueTextColor() const;
|
||||
|
||||
QSize sizeHint() const;
|
||||
QSize minimumSizeHint() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setWeatherType(WeatherType &type);
|
||||
|
||||
//设置范围值
|
||||
void setOuterRange(double minValue, double maxValue);
|
||||
//设置外环最大最小值
|
||||
void setOuterMinValue(double value);
|
||||
void setOuterMaxValue(double value);
|
||||
|
||||
//设置外环值
|
||||
void setOuterValue(double value);
|
||||
//设置外环开始旋转角度
|
||||
void setOuterStartAngle(int startAngle);
|
||||
//设置外环结束旋转角度
|
||||
void setOuterEndAngle(int endAngle);
|
||||
//设置外环背景色
|
||||
void setOuterRingBgColor(const QColor &color);
|
||||
//设置外环进度色
|
||||
void setOuterRingColor(const QColor &color);
|
||||
|
||||
//设置范围值
|
||||
void setInnerRange(double minValue, double maxValue);
|
||||
void setInnerMinValue(double value);
|
||||
void setInnerMaxValue(double value);
|
||||
void setInnerValue(double value);
|
||||
void setInnerStartAngle(int startAngle);
|
||||
void setInnerEndAngle(int endAngle);
|
||||
|
||||
void setInnerRingBgColor(const QColor &color);
|
||||
void setInnerNegativeColor(const QColor &color);
|
||||
void setInnerPositiveColor(const QColor &color);
|
||||
|
||||
void setInnerScaleMajor(int value);
|
||||
void setInnerScaleMinor(int value);
|
||||
void setInnerScaleColor(const QColor &color);
|
||||
void setInnerScaleNumColor(const QColor &color);
|
||||
|
||||
//设置中心图标颜色
|
||||
void setCenterPixMapNegativeColor(const QColor &color);
|
||||
void setCenterPixMapPositiveColor(const QColor &color);
|
||||
|
||||
void setOuterValueTextColor(const QColor &color);
|
||||
void setInnerNegativeValueTextColor(const QColor &color);
|
||||
void setInnerPositiveValueTextColor(const QColor &color);
|
||||
|
||||
//设置是否启用动画显示
|
||||
void setAnimation(bool animation);
|
||||
//设置动画显示的步长
|
||||
void setAnimationStep(double animationStep);
|
||||
|
||||
Q_SIGNALS:
|
||||
void valueChanged(double value);
|
||||
};
|
||||
|
||||
#endif // GAUGEWEATHER_H
|
After Width: | Height: | Size: 46 KiB |
|
@ -0,0 +1,5 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>image/bg2.png</file>
|
||||
</qresource>
|
||||
</RCC>
|