完成更新数据到Panel
|
@ -10,18 +10,19 @@ CONFIG += c++17
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
appinit.cpp \
|
appinit.cpp \
|
||||||
customwidget.cpp \
|
customdisplaypanel.cpp \
|
||||||
formserialportsettingdialog.cpp \
|
formserialportsettingdialog.cpp \
|
||||||
libmodbus/modbus-data.c \
|
libmodbus/modbus-data.c \
|
||||||
libmodbus/modbus-rtu.c \
|
libmodbus/modbus-rtu.c \
|
||||||
libmodbus/modbus-tcp.c \
|
libmodbus/modbus-tcp.c \
|
||||||
libmodbus/modbus.c \
|
libmodbus/modbus.c \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
mainwindow.cpp
|
mainwindow.cpp \
|
||||||
|
openjson.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
appinit.h \
|
appinit.h \
|
||||||
customwidget.h \
|
customdisplaypanel.h \
|
||||||
formserialportsettingdialog.h \
|
formserialportsettingdialog.h \
|
||||||
libmodbus/config.h \
|
libmodbus/config.h \
|
||||||
libmodbus/modbus-private.h \
|
libmodbus/modbus-private.h \
|
||||||
|
@ -32,6 +33,7 @@ HEADERS += \
|
||||||
libmodbus/modbus-version.h \
|
libmodbus/modbus-version.h \
|
||||||
libmodbus/modbus.h \
|
libmodbus/modbus.h \
|
||||||
mainwindow.h \
|
mainwindow.h \
|
||||||
|
openjson.h \
|
||||||
slave_define.h
|
slave_define.h
|
||||||
|
|
||||||
FORMS += \
|
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 <QMessageBox>
|
||||||
#include <QSizePolicy>
|
#include <QSizePolicy>
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
#include "libmodbus/modbus.h"
|
#include "libmodbus/modbus.h"
|
||||||
|
|
||||||
#include "customwidget.h"
|
#include "customdisplaypanel.h"
|
||||||
|
|
||||||
#include "formserialportsettingdialog.h"
|
#include "formserialportsettingdialog.h"
|
||||||
|
|
||||||
|
@ -91,7 +92,10 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
, ui(new Ui::MainWindow)
|
, ui(new Ui::MainWindow)
|
||||||
,m_pModbus(nullptr)
|
,m_pModbus(nullptr)
|
||||||
|
,m_pTimer(nullptr)
|
||||||
,m_pSettings(nullptr)
|
,m_pSettings(nullptr)
|
||||||
|
,m_bInitializeModbus(false)
|
||||||
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
@ -203,9 +207,11 @@ void MainWindow::getConfiguration(QString iniFilePath)
|
||||||
bool MainWindow::InitializeUI()
|
bool MainWindow::InitializeUI()
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
this->showMaximized();
|
//this->showMaximized();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ui->statusbar->showMessage(tr("Ready"), 0);
|
||||||
|
|
||||||
//初始化窗口边框
|
//初始化窗口边框
|
||||||
QWidget *centralWidget = this->centralWidget(); // new QWidget(this);
|
QWidget *centralWidget = this->centralWidget(); // new QWidget(this);
|
||||||
QGridLayout *mainLayout = new QGridLayout(centralWidget);
|
QGridLayout *mainLayout = new QGridLayout(centralWidget);
|
||||||
|
@ -231,27 +237,102 @@ bool MainWindow::InitializeUI()
|
||||||
//给垂直布局器设置边距(此步很重要, 设置宽度为阴影的宽度)
|
//给垂直布局器设置边距(此步很重要, 设置宽度为阴影的宽度)
|
||||||
//->setMargin(12);
|
//->setMargin(12);
|
||||||
|
|
||||||
// 创建2行4列布局(共8个控件示例)
|
//温度
|
||||||
for(int row=0; row<2; ++row)
|
m_pTemperaturePanel = new CustomDisplayPanel(this);
|
||||||
{
|
m_pTemperaturePanel->setImage(":/icons/main_temp.png");
|
||||||
for(int col=0; col<4; ++col)
|
QStringList l1{tr("Online"),tr("Temperature"),tr("Humidity")};
|
||||||
{
|
m_pTemperaturePanel->setLableCount(l1.count());
|
||||||
#if 0
|
m_pTemperaturePanel->setTableRowsCount(10);
|
||||||
QLabel *label = new QLabel(QString("Cell %1-%2").arg(row).arg(col),this);
|
m_pTemperaturePanel->setLables(l1);
|
||||||
label->setStyleSheet("background-color: rgb(192,192,192);"
|
m_pTemperaturePanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
|
||||||
"color: #333333;"
|
m_pTemperaturePanel->setMainLabel(tr("Temp&RH"));
|
||||||
"border-radius: 8px;"
|
m_pTemperaturePanel->Build();
|
||||||
"font: bold 14px;");
|
mainLayout->addWidget(m_pTemperaturePanel, 0, 0);
|
||||||
label->setAutoFillBackground(true);
|
|
||||||
label->setAlignment(Qt::AlignCenter);
|
//电源
|
||||||
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
m_pPowerPanel = new CustomDisplayPanel(this);
|
||||||
mainLayout->addWidget(label, row, col);
|
m_pPowerPanel->setImage(":/icons/main_power.png");
|
||||||
m_panel_labels.push_back(label);
|
QStringList l2{QStringList{tr("Online"),tr("Input Voltage"),tr("Output Voltage"),tr("Output Current"),tr("Module Temp.")}};
|
||||||
#endif
|
m_pPowerPanel->setLableCount(l2.count());
|
||||||
CustomWidget* pWidget = new CustomWidget(this);
|
m_pPowerPanel->setTableRowsCount(10);
|
||||||
mainLayout->addWidget(pWidget, row, col);
|
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);
|
mainLayout->setSpacing(5);
|
||||||
|
@ -278,6 +359,13 @@ bool MainWindow::InitializeUI()
|
||||||
QAction *actionClose = new QAction(QIcon(":/icons/close.png"), tr("Close"), this);
|
QAction *actionClose = new QAction(QIcon(":/icons/close.png"), tr("Close"), this);
|
||||||
actionClose->setToolTip(tr("Close Application"));
|
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->addAction(actionRead);
|
||||||
toolBar->addSeparator();
|
toolBar->addSeparator();
|
||||||
|
@ -288,25 +376,26 @@ bool MainWindow::InitializeUI()
|
||||||
toolBar->addWidget(spacer);
|
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");
|
// int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf");
|
||||||
if (fontId == -1)
|
// if (fontId == -1)
|
||||||
{
|
// {
|
||||||
qDebug() << "字体加载失败";
|
// ui->statusbar->showMessage(tr("Failed to load font"));
|
||||||
return -1;
|
// }
|
||||||
}
|
|
||||||
//QFont customFont("Alimama DongFangDaKai", 48);
|
//QFont customFont("Alimama DongFangDaKai", 48);
|
||||||
//customFont.setBold(true);
|
//customFont.setBold(true);
|
||||||
//label->setFont(customFont);
|
//label->setFont(customFont);
|
||||||
//label->setStyleSheet("color: #2E86C1;");
|
//label->setStyleSheet("color: #2E86C1;");
|
||||||
label->setStyleSheet(
|
label->setStyleSheet(
|
||||||
"QLabel {"
|
"QLabel {"
|
||||||
" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
|
//" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
|
||||||
|
" font-family: 'Arial';" // 需确保字体已加载
|
||||||
" font-size: 52px;"
|
" font-size: 52px;"
|
||||||
" color: #2E86C1;"
|
" color: #2E86C1;"
|
||||||
//" font-weight: bold;"
|
" font-weight: bold;"
|
||||||
|
" font-style: black;"
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
toolBar->addWidget(label);
|
toolBar->addWidget(label);
|
||||||
|
@ -327,17 +416,20 @@ bool MainWindow::InitializeUI()
|
||||||
connect(actionSetting, &QAction::triggered, this, &MainWindow::SettingSerialPort);
|
connect(actionSetting, &QAction::triggered, this, &MainWindow::SettingSerialPort);
|
||||||
connect(actionRead, &QAction::triggered, this, &MainWindow::ReadSerialPortData);
|
connect(actionRead, &QAction::triggered, this, &MainWindow::ReadSerialPortData);
|
||||||
|
|
||||||
ui->statusbar->showMessage(tr("Ready"), 0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::InitializeModbus()
|
bool MainWindow::InitializeModbus()
|
||||||
{
|
{
|
||||||
|
if (m_bInitializeModbus)
|
||||||
|
return true;
|
||||||
|
|
||||||
QString appDir = QCoreApplication::applicationDirPath();
|
QString appDir = QCoreApplication::applicationDirPath();
|
||||||
QString iniFilePath = appDir + QString::fromStdString("/emsshower.ini");
|
QString iniFilePath = appDir + QString::fromStdString("/emsshower.ini");
|
||||||
|
|
||||||
getConfiguration(iniFilePath);
|
getConfiguration(iniFilePath);
|
||||||
|
|
||||||
|
m_bInitializeModbus = true;
|
||||||
switch (m_modbus_type)
|
switch (m_modbus_type)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -413,7 +505,11 @@ bool MainWindow::InitializeTcp()
|
||||||
|
|
||||||
bool MainWindow::readRegister(int addr,int nb,uint16_t* dest)
|
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)
|
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;
|
TemperatureData* pData = (TemperatureData*)pDevice;
|
||||||
assert(pData);
|
assert(pData);
|
||||||
QString value;
|
OpenJson json;
|
||||||
if (pData->bDecodeTemp)
|
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));
|
if(pData->bDecodeTemp)
|
||||||
//m_panel_labels[0]->setText(QString(tr("温度: %1\n湿度: %2\n露点: %3\n")).arg(pData->TempValue).arg(pData->HumidityValue).arg(pData->DewPointValue));
|
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));
|
ui->statusbar->showMessage(tr("Failed to decode temperaure data")); //解析温度数据失败!"));
|
||||||
//m_panel_labels[0]->setText(QString(tr("高温告警: %1\n低温告警: %2\n湿度告警: %3\n")).arg(pData->TempHighAlarm).arg(pData->TempLowAlarm).arg(pData->HumidityHighAlarm));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,6 +597,26 @@ void MainWindow::startAsyncProcess(const QVector<uint16_t>& array,int slave_id,i
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::ReadSerialPortData()
|
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);
|
readRegister(0,0,0);
|
||||||
}
|
}
|
||||||
|
@ -508,11 +625,98 @@ void MainWindow::SettingSerialPort()
|
||||||
{
|
{
|
||||||
FormSerialPortSettingDialog* dlg = new FormSerialPortSettingDialog(this);
|
FormSerialPortSettingDialog* dlg = new FormSerialPortSettingDialog(this);
|
||||||
dlg->setWindowFlags(dlg->windowFlags()&~(Qt::WindowMinMaxButtonsHint|Qt::WindowContextHelpButtonHint));
|
dlg->setWindowFlags(dlg->windowFlags()&~(Qt::WindowMinMaxButtonsHint|Qt::WindowContextHelpButtonHint));
|
||||||
//dlg.setModal(true);
|
dlg->exec();
|
||||||
//dlg->show();
|
|
||||||
if(dlg->exec() == QDialog::Accepted)
|
// if(dlg->exec() == QDialog::Accepted)
|
||||||
QMessageBox::information(this, "OK Clicked", "Button 1 was clicked!");
|
// QMessageBox::information(this, "OK Clicked", "Button 1 was clicked!");
|
||||||
else
|
// else
|
||||||
QMessageBox::information(this, "Cancel Clicked", "Cancel was clicked!");
|
// 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 <QSettings>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "libmodbus/modbus.h"
|
#include "libmodbus/modbus.h"
|
||||||
#include "slave_define.h"
|
#include "slave_define.h"
|
||||||
|
|
||||||
|
#include "openjson.h"
|
||||||
|
|
||||||
|
class CustomDisplayPanel;
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
|
@ -65,7 +70,6 @@ public:
|
||||||
MainWindow(QWidget *parent = nullptr);
|
MainWindow(QWidget *parent = nullptr);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void getConfiguration(QString iniFilePath);
|
void getConfiguration(QString iniFilePath);
|
||||||
bool InitializeUI();
|
bool InitializeUI();
|
||||||
|
@ -80,7 +84,7 @@ private:
|
||||||
protected:
|
protected:
|
||||||
modbus_t *m_pModbus;
|
modbus_t *m_pModbus;
|
||||||
SlaveData m_SlaveData;
|
SlaveData m_SlaveData;
|
||||||
|
QTimer *m_pTimer;
|
||||||
protected:
|
protected:
|
||||||
QString m_version;
|
QString m_version;
|
||||||
int m_modbus_type;
|
int m_modbus_type;
|
||||||
|
@ -93,10 +97,8 @@ protected:
|
||||||
int m_modbus_stop;
|
int m_modbus_stop;
|
||||||
int m_modbus_slave_id;
|
int m_modbus_slave_id;
|
||||||
QSettings* m_pSettings;
|
QSettings* m_pSettings;
|
||||||
|
bool m_bInitializeModbus;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QVector<QLabel*> m_panel_labels;
|
|
||||||
protected:
|
protected:
|
||||||
//异步处理数据
|
//异步处理数据
|
||||||
void startAsyncProcess(const QVector<uint16_t>& array,int slave_id,int start_addr,int quantity,DeviceData* pData);
|
void startAsyncProcess(const QVector<uint16_t>& array,int slave_id,int start_addr,int quantity,DeviceData* pData);
|
||||||
|
@ -104,6 +106,20 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
void ReadSerialPortData();
|
void ReadSerialPortData();
|
||||||
void SettingSerialPort();
|
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:
|
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/up.png</file>
|
||||||
<file>icons/warn.png</file>
|
<file>icons/warn.png</file>
|
||||||
<file>fonts/Alimama_DongFangDaKai_Regular.ttf</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>
|
</qresource>
|
||||||
</RCC>
|
</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>
|