完成更新数据到Panel

main
HwangKC 2025-03-07 16:16:57 +08:00
parent 67df1624b7
commit 05b0cb4320
35 changed files with 3940 additions and 177 deletions

View File

@ -10,18 +10,19 @@ CONFIG += c++17
SOURCES += \
appinit.cpp \
customwidget.cpp \
customdisplaypanel.cpp \
formserialportsettingdialog.cpp \
libmodbus/modbus-data.c \
libmodbus/modbus-rtu.c \
libmodbus/modbus-tcp.c \
libmodbus/modbus.c \
main.cpp \
mainwindow.cpp
mainwindow.cpp \
openjson.cpp
HEADERS += \
appinit.h \
customwidget.h \
customdisplaypanel.h \
formserialportsettingdialog.h \
libmodbus/config.h \
libmodbus/modbus-private.h \
@ -32,6 +33,7 @@ HEADERS += \
libmodbus/modbus-version.h \
libmodbus/modbus.h \
mainwindow.h \
openjson.h \
slave_define.h
FORMS += \

View File

@ -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);
}

View File

@ -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

View File

@ -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/3QLabel
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);
}

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -12,10 +12,11 @@
#include <QMessageBox>
#include <QSizePolicy>
#include <QFontDatabase>
#include <QDateTime>
#include "libmodbus/modbus.h"
#include "customwidget.h"
#include "customdisplaypanel.h"
#include "formserialportsettingdialog.h"
@ -91,7 +92,10 @@ MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
,m_pModbus(nullptr)
,m_pTimer(nullptr)
,m_pSettings(nullptr)
,m_bInitializeModbus(false)
{
ui->setupUi(this);
@ -203,9 +207,11 @@ void MainWindow::getConfiguration(QString iniFilePath)
bool MainWindow::InitializeUI()
{
#ifndef NDEBUG
this->showMaximized();
//this->showMaximized();
#endif
ui->statusbar->showMessage(tr("Ready"), 0);
//初始化窗口边框
QWidget *centralWidget = this->centralWidget(); // new QWidget(this);
QGridLayout *mainLayout = new QGridLayout(centralWidget);
@ -231,27 +237,102 @@ bool MainWindow::InitializeUI()
//给垂直布局器设置边距(此步很重要, 设置宽度为阴影的宽度)
//->setMargin(12);
// 创建2行4列布局共8个控件示例
for(int row=0; row<2; ++row)
{
for(int col=0; col<4; ++col)
{
#if 0
QLabel *label = new QLabel(QString("Cell %1-%2").arg(row).arg(col),this);
label->setStyleSheet("background-color: rgb(192,192,192);"
"color: #333333;"
"border-radius: 8px;"
"font: bold 14px;");
label->setAutoFillBackground(true);
label->setAlignment(Qt::AlignCenter);
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
mainLayout->addWidget(label, row, col);
m_panel_labels.push_back(label);
#endif
CustomWidget* pWidget = new CustomWidget(this);
mainLayout->addWidget(pWidget, row, col);
}
}
//温度
m_pTemperaturePanel = new CustomDisplayPanel(this);
m_pTemperaturePanel->setImage(":/icons/main_temp.png");
QStringList l1{tr("Online"),tr("Temperature"),tr("Humidity")};
m_pTemperaturePanel->setLableCount(l1.count());
m_pTemperaturePanel->setTableRowsCount(10);
m_pTemperaturePanel->setLables(l1);
m_pTemperaturePanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
m_pTemperaturePanel->setMainLabel(tr("Temp&RH"));
m_pTemperaturePanel->Build();
mainLayout->addWidget(m_pTemperaturePanel, 0, 0);
//电源
m_pPowerPanel = new CustomDisplayPanel(this);
m_pPowerPanel->setImage(":/icons/main_power.png");
QStringList l2{QStringList{tr("Online"),tr("Input Voltage"),tr("Output Voltage"),tr("Output Current"),tr("Module Temp.")}};
m_pPowerPanel->setLableCount(l2.count());
m_pPowerPanel->setTableRowsCount(10);
m_pPowerPanel->setLables(l2);
m_pPowerPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
m_pPowerPanel->setMainLabel(tr("Power"));
m_pPowerPanel->Build();
mainLayout->addWidget(m_pPowerPanel, 0, 1);
//电池
m_pBatteryPanel = new CustomDisplayPanel(this);
m_pBatteryPanel->setImage(":/icons/main_battery.png");
QStringList l3{QStringList{tr("Online"),tr("SOC"),tr("SOH"),tr("Group Voltage"),tr("Cell V.Avg"),tr("Cell V.Max"),tr("Cell V.Min")}};
m_pBatteryPanel->setLableCount(l3.count());
m_pBatteryPanel->setTableRowsCount(10);
m_pBatteryPanel->setLables(l3);
m_pBatteryPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
m_pBatteryPanel->setMainLabel(tr("Battery Pack"));
m_pBatteryPanel->Build();
mainLayout->addWidget(m_pBatteryPanel, 0, 2);
//空调
m_pACPanel = new CustomDisplayPanel(this);
m_pACPanel->setImage(":/icons/main_ac.png");
QStringList l4{QStringList{tr("Online"),tr("Machine"),tr("IFM"),tr("Compressor"),tr("OFM"),tr("Discharge Temp."),tr("Room Temp.")}};
m_pACPanel->setLableCount(l4.count());
m_pACPanel->setTableRowsCount(10);
m_pACPanel->setLables(l4);
m_pACPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
m_pACPanel->setMainLabel(tr("HVACR"));
m_pACPanel->Build();
mainLayout->addWidget(m_pACPanel, 0, 3);
//交流配电
m_pInverterPanel = new CustomDisplayPanel(this);
m_pInverterPanel->setImage(":/icons/main_invertor.png");
QStringList l5{QStringList{tr("Online"),tr("Input Voltage"),tr("Input Current"),tr("Module Temp.")}};
m_pInverterPanel->setLableCount(l5.count());
m_pInverterPanel->setTableRowsCount(10);
m_pInverterPanel->setLables(l5);
m_pInverterPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
m_pInverterPanel->setMainLabel(tr("AC Power"));
m_pInverterPanel->Build();
mainLayout->addWidget(m_pInverterPanel, 1, 0);
//PV太阳能
m_pPVPanel = new CustomDisplayPanel(this);
m_pPVPanel->setImage(":/icons/main_pv.png");
QStringList l6{QStringList{tr("Online"),tr("Output Voltage"),tr("Output Current"),tr("Module Temp.")}};
m_pPVPanel->setLableCount(l6.count());
m_pPVPanel->setTableRowsCount(10);
m_pPVPanel->setLables(l6);
m_pPVPanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
m_pPVPanel->setMainLabel(tr("PV Module"));
m_pPVPanel->Build();
mainLayout->addWidget(m_pPVPanel, 1, 1);
//门禁
m_pHomePanel = new CustomDisplayPanel(this);
m_pHomePanel->setImage(":/icons/main_cab.png");
QStringList l7{QStringList{tr("Online"),tr("Output Voltage"),tr("Output Current"),tr("Module Temp.")}};
m_pHomePanel->setLableCount(l7.count());
m_pHomePanel->setTableRowsCount(10);
m_pHomePanel->setLables(l7);
m_pHomePanel->setRowItems(QStringList{tr("露点"),tr("DO"),tr("DI1"),tr("DI2"),tr("高温"),tr("低温"),tr("高湿")});
m_pHomePanel->setMainLabel(tr("Sensors"));
m_pHomePanel->Build();
mainLayout->addWidget(m_pHomePanel, 1, 2);
//告警
m_pAlarmPanel = new CustomWarningPanel(this);
m_pAlarmPanel->setImage(":/icons/main_alarm.png");
QStringList l8{QStringList{tr("Warning Board")}};
m_pAlarmPanel->setLableCount(l8.count());
m_pAlarmPanel->setTableRowsCount(10);
m_pAlarmPanel->setTableRolCount(3);
m_pAlarmPanel->setLables(l8);
m_pAlarmPanel->setRowItems(QStringList{tr("")});
m_pAlarmPanel->setMainLabel(tr("Warning"));
m_pAlarmPanel->Build();
mainLayout->addWidget(m_pAlarmPanel, 1, 3);
// 设置布局的间距和边距
mainLayout->setSpacing(5);
@ -278,6 +359,13 @@ bool MainWindow::InitializeUI()
QAction *actionClose = new QAction(QIcon(":/icons/close.png"), tr("Close"), this);
actionClose->setToolTip(tr("Close Application"));
//添加logo
QLabel *logoLabel = new QLabel(this);
QPixmap pixmap(":/icons/logo-en.png"); // 替换为实际图片路径
logoLabel->setPixmap(pixmap.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
toolBar->addWidget(logoLabel);
toolBar->addSeparator();
//添加按钮
toolBar->addAction(actionRead);
toolBar->addSeparator();
@ -288,25 +376,26 @@ bool MainWindow::InitializeUI()
toolBar->addWidget(spacer);
// 添加中央标签
QLabel *label = new QLabel(tr("综合电源柜监测"), this);
QLabel *label = new QLabel(tr("Integrated Power Cabinet Monitoring"), this);
// 加载字体
int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf");
if (fontId == -1)
{
qDebug() << "字体加载失败";
return -1;
}
// // 加载字体
// int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf");
// if (fontId == -1)
// {
// ui->statusbar->showMessage(tr("Failed to load font"));
// }
//QFont customFont("Alimama DongFangDaKai", 48);
//customFont.setBold(true);
//label->setFont(customFont);
//label->setStyleSheet("color: #2E86C1;");
label->setStyleSheet(
"QLabel {"
" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
//" font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载
" font-family: 'Arial';" // 需确保字体已加载
" font-size: 52px;"
" color: #2E86C1;"
//" font-weight: bold;"
" font-weight: bold;"
" font-style: black;"
"}"
);
toolBar->addWidget(label);
@ -327,17 +416,20 @@ bool MainWindow::InitializeUI()
connect(actionSetting, &QAction::triggered, this, &MainWindow::SettingSerialPort);
connect(actionRead, &QAction::triggered, this, &MainWindow::ReadSerialPortData);
ui->statusbar->showMessage(tr("Ready"), 0);
return true;
}
bool MainWindow::InitializeModbus()
{
if (m_bInitializeModbus)
return true;
QString appDir = QCoreApplication::applicationDirPath();
QString iniFilePath = appDir + QString::fromStdString("/emsshower.ini");
getConfiguration(iniFilePath);
m_bInitializeModbus = true;
switch (m_modbus_type)
{
case 0:
@ -413,7 +505,11 @@ bool MainWindow::InitializeTcp()
bool MainWindow::readRegister(int addr,int nb,uint16_t* dest)
{
InitializeModbus();
if(!InitializeModbus()) //这里有问题,如果是虚拟串口,连接的通常会返回成功
{
ui->statusbar->showMessage(tr("Failed to open Modbus device,Check modbus connection please!")); //打开MODBUS设备失败请检查设备连接情况!"));
return false;
}
for (auto it = m_SlaveData.begin(); it != m_SlaveData.end(); ++it)
{
@ -443,16 +539,17 @@ bool MainWindow::readRegister(int addr,int nb,uint16_t* dest)
{
TemperatureData* pData = (TemperatureData*)pDevice;
assert(pData);
QString value;
if (pData->bDecodeTemp)
OpenJson json;
if(CreateJson(pData,json))
{
//ui->txt_content_1->append(QString(tr("温度:%1\n湿度: %2\n露点: %3\n")).arg(pData->TempValue).arg(pData->HumidityValue).arg(pData->DewPointValue));
//m_panel_labels[0]->setText(QString(tr("温度: %1\n湿度: %2\n露点: %3\n")).arg(pData->TempValue).arg(pData->HumidityValue).arg(pData->DewPointValue));
if(pData->bDecodeTemp)
m_pTemperaturePanel->UpdateData(json);
if(pData->bDecodeAlarm)
m_pAlarmPanel->UpdateAlarm(json);
}
if (pData->bDecodeAlarm)
else
{
//ui->txt_content_1->append(QString(tr("高温告警: %1\n低温告警: %2\n湿度告警: %3\n")).arg(pData->TempHighAlarm).arg(pData->TempLowAlarm).arg(pData->HumidityHighAlarm));
//m_panel_labels[0]->setText(QString(tr("高温告警: %1\n低温告警: %2\n湿度告警: %3\n")).arg(pData->TempHighAlarm).arg(pData->TempLowAlarm).arg(pData->HumidityHighAlarm));
ui->statusbar->showMessage(tr("Failed to decode temperaure data")); //解析温度数据失败!"));
}
}
@ -500,6 +597,26 @@ void MainWindow::startAsyncProcess(const QVector<uint16_t>& array,int slave_id,i
void MainWindow::ReadSerialPortData()
{
if (!m_pTimer)
m_pTimer = new QTimer(this);
if (m_pTimer->isActive())
{
m_pTimer->stop();
ui->statusbar->showMessage(tr("Stop Reading"));
}
else
{
m_pTimer->setInterval(10000); // 10秒
connect(m_pTimer, &QTimer::timeout, this, &MainWindow::onTimeout);
ui->statusbar->showMessage(tr("Begin Readding"));
m_pTimer->start();
onTimeout();
}
}
void MainWindow::onTimeout()
{
readRegister(0,0,0);
}
@ -508,11 +625,98 @@ void MainWindow::SettingSerialPort()
{
FormSerialPortSettingDialog* dlg = new FormSerialPortSettingDialog(this);
dlg->setWindowFlags(dlg->windowFlags()&~(Qt::WindowMinMaxButtonsHint|Qt::WindowContextHelpButtonHint));
//dlg.setModal(true);
//dlg->show();
if(dlg->exec() == QDialog::Accepted)
QMessageBox::information(this, "OK Clicked", "Button 1 was clicked!");
else
QMessageBox::information(this, "Cancel Clicked", "Cancel was clicked!");
dlg->exec();
// if(dlg->exec() == QDialog::Accepted)
// QMessageBox::information(this, "OK Clicked", "Button 1 was clicked!");
// else
// QMessageBox::information(this, "Cancel Clicked", "Cancel was clicked!");
}
bool MainWindow::CreateJson(DeviceData* pData,OpenJson& json)
{
int data_type = pData->m_device_type;
if (data_type == 81) //根据协议定义的设备id进行分类参考DeviceData定义
{
TemperatureData* pTempData = (TemperatureData*)pData;
if (pTempData->bDecodeTemp)
{
json["panel_type"] = CustomDisplayPanel::PANEL_TEMPERATURE;
auto& nodeLabel = json["text_panel"];
nodeLabel[0]["value"] = pTempData->m_device_online_state;
nodeLabel[0]["title"] = "Online";
nodeLabel[1]["value"] = pTempData->TempValue;
nodeLabel[1]["title"] = "Temp(℃)";
nodeLabel[2]["value"] = pTempData->HumidityValue;
nodeLabel[2]["title"] = "RH (%) ";
auto& nodeTable = json["table"];
int i = 0;
nodeTable[i]["value"] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss").toStdString();
nodeTable[i]["signal"] = "Time";
i++;
nodeTable[i]["value"] = pTempData->DewPointValue;
nodeTable[i]["signal"] = "Dew Point";
i++;
nodeTable[i]["value"] = pTempData->DO;
nodeTable[i]["signal"] = "DO";
i++;
nodeTable[i]["value"] = pTempData->DI1;
nodeTable[i]["signal"] = "DI1";
i++;
nodeTable[i]["value"] = pTempData->DI2;
nodeTable[i]["signal"] = "DI2";
std::string a = json.encode();
qDebug() << QString::fromStdString(a);
}
if (pTempData->bDecodeAlarm)
{
json["panel_type"] = CustomDisplayPanel::PANEL_ALARM;
auto& nodeTable = json["alarm"];
int i = -1;
if(pTempData->TempHighAlarm != 0)
{
i++;
nodeTable[i]["time"] = QDateTime::currentDateTime().toString("MM-dd HH:mm:ss").toStdString();
nodeTable[i]["signal"] = "High Temperature";
nodeTable[i]["value"] = pTempData->TempHighAlarm;
}
if(pTempData->TempLowAlarm != 0)
{
i++;
nodeTable[i]["time"] = QDateTime::currentDateTime().toString("MM-dd HH:mm:ss").toStdString();
nodeTable[i]["signal"] = "High Temperature";
nodeTable[i]["value"] = pTempData->TempLowAlarm;
}
if(pTempData->HumidityHighAlarm != 0)
{
i++;
nodeTable[i]["time"] = QDateTime::currentDateTime().toString("MM-dd HH:mm:ss").toStdString();
nodeTable[i]["signal"] = "High Humidity";
nodeTable[i]["value"] = pTempData->HumidityHighAlarm;
}
std::string a = json.encode();
qDebug() << QString::fromStdString(a);
}
return true;
}
return false;
}

View File

@ -5,10 +5,15 @@
#include <QSettings>
#include <QVector>
#include <QLabel>
#include <QTimer>
#include "libmodbus/modbus.h"
#include "slave_define.h"
#include "openjson.h"
class CustomDisplayPanel;
QT_BEGIN_NAMESPACE
namespace Ui
{
@ -65,7 +70,6 @@ public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void getConfiguration(QString iniFilePath);
bool InitializeUI();
@ -80,7 +84,7 @@ private:
protected:
modbus_t *m_pModbus;
SlaveData m_SlaveData;
QTimer *m_pTimer;
protected:
QString m_version;
int m_modbus_type;
@ -93,10 +97,8 @@ protected:
int m_modbus_stop;
int m_modbus_slave_id;
QSettings* m_pSettings;
bool m_bInitializeModbus;
protected:
QVector<QLabel*> m_panel_labels;
protected:
//异步处理数据
void startAsyncProcess(const QVector<uint16_t>& array,int slave_id,int start_addr,int quantity,DeviceData* pData);
@ -104,6 +106,20 @@ protected:
private slots:
void ReadSerialPortData();
void SettingSerialPort();
void onTimeout();
private:
CustomDisplayPanel* m_pTemperaturePanel; //温湿度显示
CustomDisplayPanel* m_pBatteryPanel; //电池显示
CustomDisplayPanel* m_pPowerPanel; //电源显示
CustomDisplayPanel* m_pACPanel; //空调显示
CustomDisplayPanel* m_pHomePanel; //主柜子信息
CustomDisplayPanel* m_pAlarmPanel; //告警
CustomDisplayPanel* m_pInverterPanel; //逆变器
CustomDisplayPanel* m_pPVPanel; //太阳能
private:
bool CreateJson(DeviceData* pData,OpenJson& json);
signals:
// 处理进度信号

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -25,5 +25,23 @@
<file>icons/up.png</file>
<file>icons/warn.png</file>
<file>fonts/Alimama_DongFangDaKai_Regular.ttf</file>
<file>icons/main_power.png</file>
<file>icons/main_ac.png</file>
<file>icons/main_battery.png</file>
<file>icons/main_cab.png</file>
<file>icons/main_door.png</file>
<file>icons/main_fan.png</file>
<file>icons/main_fire.png</file>
<file>icons/main_invertor.png</file>
<file>icons/main_multi_cab.png</file>
<file>icons/main_peidian.png</file>
<file>icons/main_pv.png</file>
<file>icons/main_temp.png</file>
<file>icons/main_thunder.png</file>
<file>icons/main_video.png</file>
<file>icons/main_water.png</file>
<file>icons/main_UPS.png</file>
<file>icons/main_alarm.png</file>
<file>icons/logo-en.png</file>
</qresource>
</RCC>

View File

@ -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);
}

View File

@ -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

View File

@ -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>

View File

@ -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();
}

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>image/bg2.png</file>
</qresource>
</RCC>