diff --git a/applications/EmsShower/EmsShower.pro b/applications/EmsShower/EmsShower.pro index 37e54cc..97c7e88 100644 --- a/applications/EmsShower/EmsShower.pro +++ b/applications/EmsShower/EmsShower.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui serialport serialbus greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -10,6 +10,8 @@ CONFIG += c++17 SOURCES += \ appinit.cpp \ + customwidget.cpp \ + formserialportsettingdialog.cpp \ libmodbus/modbus-data.c \ libmodbus/modbus-rtu.c \ libmodbus/modbus-tcp.c \ @@ -19,6 +21,8 @@ SOURCES += \ HEADERS += \ appinit.h \ + customwidget.h \ + formserialportsettingdialog.h \ libmodbus/config.h \ libmodbus/modbus-private.h \ libmodbus/modbus-rtu-private.h \ @@ -31,6 +35,7 @@ HEADERS += \ slave_define.h FORMS += \ + formserialportsettingdialog.ui \ mainwindow.ui LIBS += -lws2_32 diff --git a/applications/EmsShower/customwidget.cpp b/applications/EmsShower/customwidget.cpp new file mode 100644 index 0000000..1a47df8 --- /dev/null +++ b/applications/EmsShower/customwidget.cpp @@ -0,0 +1,100 @@ +#include "customwidget.h" +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/applications/EmsShower/customwidget.h b/applications/EmsShower/customwidget.h new file mode 100644 index 0000000..bc0a364 --- /dev/null +++ b/applications/EmsShower/customwidget.h @@ -0,0 +1,21 @@ +#ifndef CUSTOMWIDGET_H +#define CUSTOMWIDGET_H + +#include + + +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 diff --git a/applications/EmsShower/fonts/Alimama_DongFangDaKai_Regular.ttf b/applications/EmsShower/fonts/Alimama_DongFangDaKai_Regular.ttf new file mode 100644 index 0000000..2af05b2 Binary files /dev/null and b/applications/EmsShower/fonts/Alimama_DongFangDaKai_Regular.ttf differ diff --git a/applications/EmsShower/formserialportsettingdialog.cpp b/applications/EmsShower/formserialportsettingdialog.cpp new file mode 100644 index 0000000..ae04171 --- /dev/null +++ b/applications/EmsShower/formserialportsettingdialog.cpp @@ -0,0 +1,160 @@ +#include "formserialportsettingdialog.h" +#include "ui_formserialportsettingdialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +FormSerialPortSettingDialog::FormSerialPortSettingDialog(QWidget *parent) + : QDialog(parent) + , ui(new Ui::FormSerialPortSettingDialog) +{ + ui->setupUi(this); + InitializeUi(); +} + +FormSerialPortSettingDialog::~FormSerialPortSettingDialog() +{ + delete ui; +} + +void FormSerialPortSettingDialog::InitializeUi() +{ + this->setStyleSheet("background-color: white;"); + this->setProperty("canMove",true); + //设置窗体透明 + this->setAttribute(Qt::WA_TranslucentBackground, true); + //设置无边框 + this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + //实例阴影shadow + QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this); + //设置阴影距离 + shadow->setOffset(0, 0); + //设置阴影颜色 + shadow->setColor(QColor(44,44,44)); + //设置阴影圆角 + shadow->setBlurRadius(16); + //给嵌套QDialog设置阴影 + ui->w_bg->setGraphicsEffect(shadow); + //给垂直布局器设置边距(此步很重要, 设置宽度为阴影的宽度) + //ui->lay_bg->setMargin(12); + + QApplication::setOverrideCursor(Qt::WaitCursor); + + ui->delay_timeout->setText("1000"); + ui->slave_id->setText("1"); + + //设置奇偶校验 + ui->cb_parity->setView(new QListView(this)); + ui->cb_parity->addItem("NoParity", QVariant::fromValue(QSerialPort::NoParity)); + ui->cb_parity->addItem("Even", QVariant::fromValue(QSerialPort::EvenParity)); + ui->cb_parity->addItem("Odd", QVariant::fromValue(QSerialPort::OddParity)); + ui->cb_parity->setCurrentIndex(0); + + //设置数据位 + ui->cb_data->setView(new QListView(this)); + ui->cb_data->addItem("5", QVariant::fromValue(QSerialPort::Data5)); + ui->cb_data->addItem("6", QVariant::fromValue(QSerialPort::Data6)); + ui->cb_data->addItem("7", QVariant::fromValue(QSerialPort::Data7)); + ui->cb_data->addItem("8", QVariant::fromValue(QSerialPort::Data8)); + ui->cb_data->setCurrentIndex(3); + + //设置数据位 + ui->cb_stop->setView(new QListView(this)); + ui->cb_stop->addItem("1", QVariant::fromValue(QSerialPort::OneStop)); + ui->cb_stop->addItem("2", QVariant::fromValue(QSerialPort::TwoStop)); + ui->cb_stop->addItem("3", QVariant::fromValue(QSerialPort::OneAndHalfStop)); + ui->cb_stop->setCurrentIndex(0); + + + //设置串口模式 + //ui->cb_baund->setView(new QListView(this)); + //QStandardItemModel* model_baund = new QStandardItemModel(this); + + ui->cb_baund->addItem("4800", QVariant::fromValue(QSerialPort::Baud4800)); + ui->cb_baund->addItem("9600", QVariant::fromValue(QSerialPort::Baud9600)); + ui->cb_baund->addItem("19200", QVariant::fromValue(QSerialPort::Baud19200)); + ui->cb_baund->addItem("38400", QVariant::fromValue(QSerialPort::Baud38400)); + ui->cb_baund->addItem("57600", QVariant::fromValue(QSerialPort::Baud57600)); + ui->cb_baund->addItem("115200", QVariant::fromValue(QSerialPort::Baud115200)); + ui->cb_baund->setCurrentIndex(1); + + //设置串口类型 + ui->cb_type->setView(new QListView(this)); + ui->cb_type->addItem("Modbus RTU"); + + //设置串口号 + ui->cb_serialport->setView(new QListView(this)); + QStringList comport = get_avail_sp_(); + foreach (const QString& str, comport) + { + QStringList parts = str.split("-", Qt::SkipEmptyParts); + ui->cb_serialport->addItem(str,parts[0].trimmed()); + } + + ui->buttonBox->clear(); + QPushButton *okButton = ui->buttonBox->addButton(QDialogButtonBox::Ok); + QPushButton *cancelButton = ui->buttonBox->addButton(QDialogButtonBox::Cancel); + okButton->setFixedSize(100, 30); + cancelButton->setFixedSize(100, 30); + + connect(okButton, &QPushButton::clicked, this, &FormSerialPortSettingDialog::onOkClicked); + connect(cancelButton, &QPushButton::clicked, this, &FormSerialPortSettingDialog::onCancelClicked); + + // 恢复默认光标 + QApplication::restoreOverrideCursor(); +} + +QStringList FormSerialPortSettingDialog::get_avail_sp_() noexcept +{ + QStringList list_avail_sp; + + foreach (const QSerialPortInfo &port, QSerialPortInfo::availablePorts()) + { + list_avail_sp.append(port.portName() + " - " + port.description()); + } + + list_avail_sp.sort(); + + return list_avail_sp; +} + +void FormSerialPortSettingDialog::onOkClicked() +{ + //写到INI文件 + QString appDir = QCoreApplication::applicationDirPath(); + QString iniFilePath = appDir + QString::fromStdString("/emsshower.ini"); + QSettings* pSettings = new QSettings(iniFilePath, QSettings::IniFormat,this); + + //写选中的串口 + int baund = ui->cb_baund->currentData().toInt(); + QString com = ui->cb_serialport->currentData().toString(); + int data = ui->cb_data->currentData().toInt(); + int parity = ui->cb_parity->currentData().toInt(); + int stop = ui->cb_stop->currentData().toInt(); + int slave_id = ui->slave_id->text().toInt(); + + pSettings->setValue("modbus/baund",baund); + pSettings->setValue("modbus/com",com); + pSettings->setValue("modbus/data",data); + pSettings->setValue("modbus/parity",parity); + pSettings->setValue("modbus/stop",stop); + pSettings->setValue("slaves/slave_id",slave_id); + + accept(); +} + +void FormSerialPortSettingDialog::onCancelClicked() +{ + QDialog::reject(); +} + diff --git a/applications/EmsShower/formserialportsettingdialog.h b/applications/EmsShower/formserialportsettingdialog.h new file mode 100644 index 0000000..b7d37d6 --- /dev/null +++ b/applications/EmsShower/formserialportsettingdialog.h @@ -0,0 +1,32 @@ +#ifndef FORMSERIALPORTSETTINGDIALOG_H +#define FORMSERIALPORTSETTINGDIALOG_H + +#include +#include + +namespace Ui +{ +class FormSerialPortSettingDialog; +} + +class FormSerialPortSettingDialog : public QDialog +{ + Q_OBJECT + +public: + explicit FormSerialPortSettingDialog(QWidget *parent = nullptr); + ~FormSerialPortSettingDialog(); + +private: + Ui::FormSerialPortSettingDialog *ui; + +protected: + void InitializeUi(); + QStringList get_avail_sp_() noexcept; + +private slots: + void onOkClicked(); + void onCancelClicked(); +}; + +#endif // FORMSERIALPORTSETTINGDIALOG_H diff --git a/applications/EmsShower/formserialportsettingdialog.ui b/applications/EmsShower/formserialportsettingdialog.ui new file mode 100644 index 0000000..750525a --- /dev/null +++ b/applications/EmsShower/formserialportsettingdialog.ui @@ -0,0 +1,265 @@ + + + FormSerialPortSettingDialog + + + + 0 + 0 + 665 + 320 + + + + Dialog + + + + + 7 + 6 + 651 + 310 + + + + + + 30 + 20 + 69 + 19 + + + + 串口类型 + + + cb_type + + + + + + 341 + 102 + 69 + 19 + + + + 停止位 + + + cb_stop + + + + + + 280 + 243 + 341 + 32 + + + + Qt::Horizontal + + + + + + 30 + 183 + 91 + 19 + + + + 响应超时 + + + delay_timeout + + + + + + 30 + 140 + 69 + 19 + + + + 数据位 + + + cb_data + + + + + + 340 + 140 + 69 + 19 + + + + 校验位 + + + cb_parity + + + + + + 30 + 60 + 69 + 19 + + + + 串口号 + + + + + + 421 + 102 + 201 + 25 + + + + + + + 110 + 140 + 181 + 25 + + + + + + + 230 + 186 + 41 + 19 + + + + + 12 + + + + ms + + + + + + 30 + 101 + 69 + 19 + + + + 波特率 + + + cb_baund + + + + + + 110 + 183 + 113 + 30 + + + + + + + 110 + 20 + 181 + 25 + + + + + + + 420 + 140 + 201 + 25 + + + + + + + 420 + 20 + 201 + 30 + + + + + + + 110 + 60 + 511 + 25 + + + + + + + 340 + 20 + 69 + 19 + + + + 从机地址 + + + slave_id + + + + + + 110 + 101 + 181 + 25 + + + + + + + + diff --git a/applications/EmsShower/mainwindow.cpp b/applications/EmsShower/mainwindow.cpp index 8a3fae5..4b2f918 100644 --- a/applications/EmsShower/mainwindow.cpp +++ b/applications/EmsShower/mainwindow.cpp @@ -9,9 +9,16 @@ #include #include #include +#include +#include +#include #include "libmodbus/modbus.h" +#include "customwidget.h" + +#include "formserialportsettingdialog.h" + #define _DEBUG_VSPD_ #define TH08D_TEMPERATURE_EQUIPMENT_81_00_09 40000 @@ -100,13 +107,10 @@ MainWindow::MainWindow(QWidget *parent) m_modbus_slave_id = 1; InitializeUI(); - InitializeModbus(); } MainWindow::~MainWindow() { - delete ui; - if (m_pModbus) { modbus_close(m_pModbus); @@ -126,6 +130,7 @@ MainWindow::~MainWindow() delete m_pSettings; m_pSettings = nullptr; } + delete ui; } void MainWindow::getConfiguration(QString iniFilePath) @@ -197,25 +202,43 @@ void MainWindow::getConfiguration(QString iniFilePath) bool MainWindow::InitializeUI() { +#ifndef NDEBUG + this->showMaximized(); +#endif + //初始化窗口边框 - this->setAttribute(Qt::WA_TranslucentBackground, true); - this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint); - QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this); - shadow->setOffset(0, 0); - shadow->setColor(QColor("#444444")); - shadow->setBlurRadius(16); - // ui->w_bg->setGraphicsEffect(shadow); - //ui->lay_bg->setMargin(12); - QWidget *centralWidget = new QWidget(this); + QWidget *centralWidget = this->centralWidget(); // new QWidget(this); QGridLayout *mainLayout = new QGridLayout(centralWidget); + this->setStyleSheet("background-color: white;"); + //this->setProperty("canMove",true); + + //设置窗体透明 + this->setAttribute(Qt::WA_TranslucentBackground, true); + //设置无边框 + this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + //实例阴影shadow + QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this); + //设置阴影距离 + shadow->setOffset(0, 0); + //设置阴影颜色 + shadow->setColor(QColor(44,44,44)); + //设置阴影圆角 + shadow->setBlurRadius(16); + //给嵌套QDialog设置阴影 + ui->centralwidget->setGraphicsEffect(shadow); + + //给垂直布局器设置边距(此步很重要, 设置宽度为阴影的宽度) + //->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);" + label->setStyleSheet("background-color: rgb(192,192,192);" "color: #333333;" "border-radius: 8px;" "font: bold 14px;"); @@ -224,37 +247,88 @@ bool MainWindow::InitializeUI() 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); } } // 设置布局的间距和边距 mainLayout->setSpacing(5); //mainLayout->setContentsMargins(10, 40, 10, 10); // 顶部留出工具栏空间 - setCentralWidget(centralWidget); + //setCentralWidget(centralWidget); QToolBar *toolBar = new QToolBar(this); toolBar->setMovable(false); + toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); toolBar->setIconSize(QSize(64,64)); + // 设置按钮悬停效果(通过样式表) + // toolBar->setStyleSheet( + // "QToolButton { background: transparent; border: none; }" + // "QToolButton:hover { background: #e0e0e0; border-radius: 4px; }" + // ); // 添加工具栏按钮 QAction *actionRead = new QAction(QIcon(":/icons/modular.png"), tr("Read"), this); actionRead->setToolTip(tr("Read Data")); + QAction *actionSetting = new QAction(QIcon(":/icons/setting.png"), tr("Setting"), this); + actionSetting->setToolTip(tr("Setting Modbud Port")); + QAction *actionClose = new QAction(QIcon(":/icons/close.png"), tr("Close"), this); actionClose->setToolTip(tr("Close Application")); + //添加按钮 toolBar->addAction(actionRead); toolBar->addSeparator(); - toolBar->addAction(actionClose); + + // 添加间隔控件 + QWidget *spacer = new QWidget(); + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + toolBar->addWidget(spacer); + + // 添加中央标签 + QLabel *label = new QLabel(tr("综合电源柜监测"), this); + + // 加载字体 + int fontId = QFontDatabase::addApplicationFont(":/fonts/Alimama_DongFangDaKai_Regular.ttf"); + if (fontId == -1) + { + qDebug() << "字体加载失败"; + return -1; + } + //QFont customFont("Alimama DongFangDaKai", 48); + //customFont.setBold(true); + //label->setFont(customFont); + //label->setStyleSheet("color: #2E86C1;"); + label->setStyleSheet( + "QLabel {" + " font-family: 'Alimama DongFangDaKai';" // 需确保字体已加载 + " font-size: 52px;" + " color: #2E86C1;" + //" font-weight: bold;" + "}" + ); + toolBar->addWidget(label); + + QWidget *spacerWidget = new QWidget(); + spacerWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + toolBar->addWidget(spacerWidget); + + toolBar->addAction(actionSetting); toolBar->addSeparator(); - // 将工具栏定位到窗口顶部 + toolBar->addAction(actionClose); + + // 将工具栏定位到窗口顶部· addToolBar(Qt::TopToolBarArea, toolBar); connect(actionClose, &QAction::triggered, this, &QMainWindow::close); + connect(actionSetting, &QAction::triggered, this, &MainWindow::SettingSerialPort); connect(actionRead, &QAction::triggered, this, &MainWindow::ReadSerialPortData); - return false; + ui->statusbar->showMessage(tr("Ready"), 0); + return true; } bool MainWindow::InitializeModbus() @@ -339,6 +413,8 @@ bool MainWindow::InitializeTcp() bool MainWindow::readRegister(int addr,int nb,uint16_t* dest) { + InitializeModbus(); + for (auto it = m_SlaveData.begin(); it != m_SlaveData.end(); ++it) { SlaveItem* pItem = (SlaveItem*)(*it); @@ -367,10 +443,11 @@ bool MainWindow::readRegister(int addr,int nb,uint16_t* dest) { TemperatureData* pData = (TemperatureData*)pDevice; assert(pData); + QString value; if (pData->bDecodeTemp) { //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)); + //m_panel_labels[0]->setText(QString(tr("温度: %1\n湿度: %2\n露点: %3\n")).arg(pData->TempValue).arg(pData->HumidityValue).arg(pData->DewPointValue)); } if (pData->bDecodeAlarm) { @@ -427,3 +504,15 @@ void MainWindow::ReadSerialPortData() readRegister(0,0,0); } +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!"); +} + diff --git a/applications/EmsShower/mainwindow.h b/applications/EmsShower/mainwindow.h index 7fe9b31..da21cf9 100644 --- a/applications/EmsShower/mainwindow.h +++ b/applications/EmsShower/mainwindow.h @@ -103,6 +103,7 @@ protected: private slots: void ReadSerialPortData(); + void SettingSerialPort(); signals: // 处理进度信号 diff --git a/applications/EmsShower/qss.qrc b/applications/EmsShower/qss.qrc index 50413a4..c7a43a6 100644 --- a/applications/EmsShower/qss.qrc +++ b/applications/EmsShower/qss.qrc @@ -24,5 +24,6 @@ icons/umbrella.png icons/up.png icons/warn.png + fonts/Alimama_DongFangDaKai_Regular.ttf diff --git a/applications/examples/quc_demo/battery.cpp b/applications/examples/quc_demo/battery.cpp new file mode 100644 index 0000000..6f370fd --- /dev/null +++ b/applications/examples/quc_demo/battery.cpp @@ -0,0 +1,416 @@ +#pragma execution_character_set("utf-8") + +#include "battery.h" +#include "qpainter.h" +#include +#include "qtimer.h" +//#include "qdebug.h" + +Battery::Battery(QWidget *parent) : QWidget(parent) +{ + minValue = 0; + maxValue = 100; + value = 0; + alarmValue = 30; + step = 0.5; + + borderRadius = 8; + bgRadius = 5; + headRadius = 3; + + borderColorStart = QColor(100, 100, 100); + borderColorEnd = QColor(80, 80, 80); + alarmColorStart = QColor(250, 118, 113); + alarmColorEnd = QColor(204, 38, 38); + normalColorStart = QColor(50, 205, 51); + normalColorEnd = QColor(60, 179, 133); + + isForward = false; + currentValue = 0; + + timer = new QTimer(this); + timer->setInterval(10); + connect(timer, SIGNAL(timeout()), this, SLOT(updateValue())); +} + +Battery::~Battery() +{ + if (timer->isActive()) + { + timer->stop(); + } +} + +void Battery::paintEvent(QPaintEvent *) +{ + //绘制准备工作,启用反锯齿 + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); + + //绘制边框 + drawBorder(&painter); + //绘制背景 + drawBg(&painter); + //绘制头部 + drawHead(&painter); +} + +void Battery::drawBorder(QPainter *painter) +{ + painter->save(); + + double headWidth = width() / 10; + double batteryWidth = width() - headWidth; + + //绘制电池边框 + QPointF topLeft(5, 5); + QPointF bottomRight(batteryWidth, height() - 5); + batteryRect = QRectF(topLeft, bottomRight); + + painter->setPen(QPen(borderColorStart, 5)); + painter->setBrush(Qt::NoBrush); + painter->drawRoundedRect(batteryRect, borderRadius, borderRadius); + + painter->restore(); +} + +void Battery::drawBg(QPainter *painter) +{ + painter->save(); + + QLinearGradient batteryGradient(QPointF(0, 0), QPointF(0, height())); + if (currentValue <= alarmValue) + { + batteryGradient.setColorAt(0.0, alarmColorStart); + batteryGradient.setColorAt(1.0, alarmColorEnd); + } + else + { + batteryGradient.setColorAt(0.0, normalColorStart); + batteryGradient.setColorAt(1.0, normalColorEnd); + } + + int margin = qMin(width(), height()) / 20; + double unit = (batteryRect.width() - (margin * 2)) / 100; + double width = currentValue * unit; + QPointF topLeft(batteryRect.topLeft().x() + margin, batteryRect.topLeft().y() + margin); + QPointF bottomRight(width + margin + 5, batteryRect.bottomRight().y() - margin); + QRectF rect(topLeft, bottomRight); + + painter->setPen(Qt::NoPen); + painter->setBrush(batteryGradient); + painter->drawRoundedRect(rect, bgRadius, bgRadius); + + painter->restore(); +} + +void Battery::drawHead(QPainter *painter) +{ + painter->save(); + + QPointF headRectTopLeft(batteryRect.topRight().x(), height() / 3); + QPointF headRectBottomRight(width(), height() - height() / 3); + QRectF headRect(headRectTopLeft, headRectBottomRight); + + QLinearGradient headRectGradient(headRect.topLeft(), headRect.bottomLeft()); + headRectGradient.setColorAt(0.0, borderColorStart); + headRectGradient.setColorAt(1.0, borderColorEnd); + + painter->setPen(Qt::NoPen); + painter->setBrush(headRectGradient); + painter->drawRoundedRect(headRect, headRadius, headRadius); + + painter->restore(); +} + +void Battery::updateValue() +{ + if (isForward) + { + currentValue -= step; + + if (currentValue <= value) + { + timer->stop(); + } + } + else + { + currentValue += step; + + if (currentValue >= value) + { + timer->stop(); + } + } + + this->update(); +} + +double Battery::getMinValue() const +{ + return this->minValue; +} + +double Battery::getMaxValue() const +{ + return this->maxValue; +} + +double Battery::getValue() const +{ + return this->value; +} + +double Battery::getAlarmValue() const +{ + return this->alarmValue; +} + +double Battery::getStep() const +{ + return this->step; +} + +int Battery::getBorderRadius() const +{ + return this->borderRadius; +} + +int Battery::getBgRadius() const +{ + return this->bgRadius; +} + +int Battery::getHeadRadius() const +{ + return this->headRadius; +} + +QColor Battery::getBorderColorStart() const +{ + return this->borderColorStart; +} + +QColor Battery::getBorderColorEnd() const +{ + return this->borderColorEnd; +} + +QColor Battery::getAlarmColorStart() const +{ + return this->alarmColorStart; +} + +QColor Battery::getAlarmColorEnd() const +{ + return this->alarmColorEnd; +} + +QColor Battery::getNormalColorStart() const +{ + return this->normalColorStart; +} + +QColor Battery::getNormalColorEnd() const +{ + return this->normalColorEnd; +} + +QSize Battery::sizeHint() const +{ + return QSize(150, 80); +} + +QSize Battery::minimumSizeHint() const +{ + return QSize(30, 10); +} + +void Battery::setRange(double minValue, double maxValue) +{ + //如果最小值大于或者等于最大值则不设置 + if (minValue >= maxValue) + { + return; + } + + this->minValue = minValue; + this->maxValue = maxValue; + + //如果目标值不在范围值内,则重新设置目标值 + if (value < minValue || value > maxValue) + { + setValue(value); + } + + this->update(); +} + +void Battery::setRange(int minValue, int maxValue) +{ + setRange((double)minValue, (double)maxValue); +} + +void Battery::setMinValue(double minValue) +{ + setRange(minValue, maxValue); +} + +void Battery::setMaxValue(double maxValue) +{ + setRange(minValue, maxValue); +} + +void Battery::setValue(double value) +{ + //值和当前值一致则无需处理 + if (value == this->value) + { + return; + } + + //值小于最小值则取最小值,大于最大值则取最大值 + if (value < minValue) + { + value = minValue; + } + else if (value > maxValue) + { + value = maxValue; + } + + emit valueChanged(value); + this->value = value; + + if (value > currentValue) + { + isForward = false; + } + else if (value < currentValue) + { + isForward = true; + } + else + { + return ; + } + + timer->start(); + this->update(); +} + +void Battery::setValue(int value) +{ + setValue((double)value); +} + +void Battery::setAlarmValue(double alarmValue) +{ + if (this->alarmValue != alarmValue) + { + this->alarmValue = alarmValue; + this->update(); + } +} + +void Battery::setAlarmValue(int alarmValue) +{ + setAlarmValue((double)alarmValue); +} + +void Battery::setStep(double step) +{ + if (this->step != step) + { + this->step = step; + this->update(); + } +} + +void Battery::setStep(int step) +{ + setStep((double)step); +} + +void Battery::setBorderRadius(int borderRadius) +{ + if (this->borderRadius != borderRadius) + { + this->borderRadius = borderRadius; + this->update(); + } +} + +void Battery::setBgRadius(int bgRadius) +{ + if (this->bgRadius != bgRadius) + { + this->bgRadius = bgRadius; + this->update(); + } +} + +void Battery::setHeadRadius(int headRadius) +{ + if (this->headRadius != headRadius) + { + this->headRadius = headRadius; + this->update(); + } +} + +void Battery::setBorderColorStart(const QColor &borderColorStart) +{ + if (this->borderColorStart != borderColorStart) + { + this->borderColorStart = borderColorStart; + this->update(); + } +} + +void Battery::setBorderColorEnd(const QColor &borderColorEnd) +{ + if (this->borderColorEnd != borderColorEnd) + { + this->borderColorEnd = borderColorEnd; + this->update(); + } +} + +void Battery::setAlarmColorStart(const QColor &alarmColorStart) +{ + if (this->alarmColorStart != alarmColorStart) + { + this->alarmColorStart = alarmColorStart; + this->update(); + } +} + +void Battery::setAlarmColorEnd(const QColor &alarmColorEnd) +{ + if (this->alarmColorEnd != alarmColorEnd) + { + this->alarmColorEnd = alarmColorEnd; + this->update(); + } +} + +void Battery::setNormalColorStart(const QColor &normalColorStart) +{ + if (this->normalColorStart != normalColorStart) + { + this->normalColorStart = normalColorStart; + this->update(); + } +} + +void Battery::setNormalColorEnd(const QColor &normalColorEnd) +{ + if (this->normalColorEnd != normalColorEnd) + { + this->normalColorEnd = normalColorEnd; + this->update(); + } +} + diff --git a/applications/examples/quc_demo/battery.h b/applications/examples/quc_demo/battery.h new file mode 100644 index 0000000..d5192a2 --- /dev/null +++ b/applications/examples/quc_demo/battery.h @@ -0,0 +1,155 @@ +#ifndef BATTERY_H +#define BATTERY_H + +/** + * 电池电量控件 作者:feiyangqingyun(QQ:517216493) 2016-10-23 + * 1:可设置电池电量,动态切换电池电量变化 + * 2:可设置电池电量警戒值 + * 3:可设置电池电量正常颜色和报警颜色 + * 4:可设置边框渐变颜色 + * 5:可设置电量变化时每次移动的步长 + * 6:可设置边框圆角角度/背景进度圆角角度/头部圆角角度 + */ + +#include +#include + +#ifdef quc +#if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) +#include +#else +#include +#endif + +class QDESIGNER_WIDGET_EXPORT Battery : public QWidget +#else +class Battery : public QWidget +#endif + +{ + Q_OBJECT + Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue) + Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue) + Q_PROPERTY(double value READ getValue WRITE setValue) + Q_PROPERTY(double alarmValue READ getAlarmValue WRITE setAlarmValue) + + Q_PROPERTY(double step READ getStep WRITE setStep) + Q_PROPERTY(int borderRadius READ getBorderRadius WRITE setBorderRadius) + Q_PROPERTY(int bgRadius READ getBgRadius WRITE setBgRadius) + Q_PROPERTY(int headRadius READ getHeadRadius WRITE setHeadRadius) + + Q_PROPERTY(QColor borderColorStart READ getBorderColorStart WRITE setBorderColorStart) + Q_PROPERTY(QColor borderColorEnd READ getBorderColorEnd WRITE setBorderColorEnd) + + Q_PROPERTY(QColor alarmColorStart READ getAlarmColorStart WRITE setAlarmColorStart) + Q_PROPERTY(QColor alarmColorEnd READ getAlarmColorEnd WRITE setAlarmColorEnd) + + Q_PROPERTY(QColor normalColorStart READ getNormalColorStart WRITE setNormalColorStart) + Q_PROPERTY(QColor normalColorEnd READ getNormalColorEnd WRITE setNormalColorEnd) + +public: + explicit Battery(QWidget *parent = 0); + ~Battery(); + +protected: + void paintEvent(QPaintEvent *); + void drawBorder(QPainter *painter); + void drawBg(QPainter *painter); + void drawHead(QPainter *painter); + +private slots: + void updateValue(); + +private: + double minValue; //最小值 + double maxValue; //最大值 + double value; //目标电量 + double alarmValue; //电池电量警戒值 + + double step; //每次移动的步长 + int borderRadius; //边框圆角角度 + int bgRadius; //背景进度圆角角度 + int headRadius; //头部圆角角度 + + QColor borderColorStart; //边框渐变开始颜色 + QColor borderColorEnd; //边框渐变结束颜色 + + QColor alarmColorStart; //电池低电量时的渐变开始颜色 + QColor alarmColorEnd; //电池低电量时的渐变结束颜色 + + QColor normalColorStart; //电池正常电量时的渐变开始颜色 + QColor normalColorEnd; //电池正常电量时的渐变结束颜色 + + bool isForward; //是否往前移 + double currentValue; //当前电量 + QRectF batteryRect; //电池主体区域 + QTimer *timer; //绘制定时器 + +public: + double getMinValue() const; + double getMaxValue() const; + double getValue() const; + double getAlarmValue() const; + + double getStep() const; + int getBorderRadius() const; + int getBgRadius() const; + int getHeadRadius() const; + + QColor getBorderColorStart() const; + QColor getBorderColorEnd() const; + + QColor getAlarmColorStart() const; + QColor getAlarmColorEnd() const; + + QColor getNormalColorStart() const; + QColor getNormalColorEnd() const; + + QSize sizeHint() const; + QSize minimumSizeHint() const; + +public Q_SLOTS: + //设置范围值 + void setRange(double minValue, double maxValue); + void setRange(int minValue, int maxValue); + + //设置最大最小值 + void setMinValue(double minValue); + void setMaxValue(double maxValue); + + //设置电池电量值 + void setValue(double value); + void setValue(int value); + + //设置电池电量警戒值 + void setAlarmValue(double alarmValue); + void setAlarmValue(int alarmValue); + + //设置步长 + void setStep(double step); + void setStep(int step); + + //设置边框圆角角度 + void setBorderRadius(int borderRadius); + //设置背景圆角角度 + void setBgRadius(int bgRadius); + //设置头部圆角角度 + void setHeadRadius(int headRadius); + + //设置边框渐变颜色 + void setBorderColorStart(const QColor &borderColorStart); + void setBorderColorEnd(const QColor &borderColorEnd); + + //设置电池电量报警时的渐变颜色 + void setAlarmColorStart(const QColor &alarmColorStart); + void setAlarmColorEnd(const QColor &alarmColorEnd); + + //设置电池电量正常时的渐变颜色 + void setNormalColorStart(const QColor &normalColorStart); + void setNormalColorEnd(const QColor &normalColorEnd); + +Q_SIGNALS: + void valueChanged(double value); +}; + +#endif // BATTERY_H diff --git a/applications/examples/quc_demo/frmbattery.cpp b/applications/examples/quc_demo/frmbattery.cpp new file mode 100644 index 0000000..e6d157e --- /dev/null +++ b/applications/examples/quc_demo/frmbattery.cpp @@ -0,0 +1,21 @@ +#pragma execution_character_set("utf-8") + +#include "frmbattery.h" +#include "ui_frmbattery.h" + +frmBattery::frmBattery(QWidget *parent) : QWidget(parent), ui(new Ui::frmBattery) +{ + ui->setupUi(this); + this->initForm(); +} + +frmBattery::~frmBattery() +{ + delete ui; +} + +void frmBattery::initForm() +{ + connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), ui->battery, SLOT(setValue(int))); + ui->horizontalSlider->setValue(30); +} diff --git a/applications/examples/quc_demo/frmbattery.h b/applications/examples/quc_demo/frmbattery.h new file mode 100644 index 0000000..4f221bb --- /dev/null +++ b/applications/examples/quc_demo/frmbattery.h @@ -0,0 +1,27 @@ +#ifndef FRMBATTERY_H +#define FRMBATTERY_H + +#include +#include + +namespace Ui +{ +class frmBattery; +} + +class frmBattery : public QWidget +{ + Q_OBJECT + +public: + explicit frmBattery(QWidget *parent = 0); + ~frmBattery(); + +private: + Ui::frmBattery *ui; + +private slots: + void initForm(); +}; + +#endif // FRMBATTERY_H diff --git a/applications/examples/quc_demo/frmbattery.ui b/applications/examples/quc_demo/frmbattery.ui new file mode 100644 index 0000000..59270b5 --- /dev/null +++ b/applications/examples/quc_demo/frmbattery.ui @@ -0,0 +1,56 @@ + + + frmBattery + + + + 0 + 0 + 500 + 300 + + + + Form + + + + + 9 + 9 + 482 + 257 + + + + + + + 9 + 272 + 481 + 19 + + + + 100 + + + Qt::Horizontal + + + false + + + + + + Battery + QWidget +
battery.h
+ 1 +
+
+ + +
diff --git a/applications/examples/quc_demo/frmgaugepanel.cpp b/applications/examples/quc_demo/frmgaugepanel.cpp new file mode 100644 index 0000000..4a288e8 --- /dev/null +++ b/applications/examples/quc_demo/frmgaugepanel.cpp @@ -0,0 +1,99 @@ +#pragma execution_character_set("utf-8") + +#include "frmgaugepanel.h" +#include "ui_frmgaugepanel.h" +#include "qdebug.h" + +frmGaugePanel::frmGaugePanel(QWidget *parent) : QWidget(parent), ui(new Ui::frmGaugePanel) +{ + ui->setupUi(this); + this->initForm(); +} + +frmGaugePanel::~frmGaugePanel() +{ + delete ui; +} + +void frmGaugePanel::initForm() +{ +#if 0 + ui->horizontalSlider1->setVisible(false); + ui->horizontalSlider2->setVisible(false); + ui->horizontalSlider3->setVisible(false); + ui->horizontalSlider4->setVisible(false); + ui->horizontalSlider5->setVisible(false); + ui->horizontalSlider6->setVisible(false); +#endif + + //设置样式 + QStringList list; + list.append("#widget{background:#222939;}"); + list.append("GaugePanel{qproperty-ringColor:#393F4D;qproperty-scaleColor:#03B7C9;" + "qproperty-pointerColor:#03B7C9;qproperty-textColor:#EEEEEE;}"); + ui->widget->setStyleSheet(list.join("")); + + //设置单位 + ui->gaugePanel1->setUnit("V"); + ui->gaugePanel2->setUnit("A"); + ui->gaugePanel3->setUnit("m"); + ui->gaugePanel4->setUnit("kW"); + ui->gaugePanel5->setUnit("kWh"); + ui->gaugePanel6->setUnit("Hz"); + + //设置名称 + ui->gaugePanel1->setText("电压"); + ui->gaugePanel2->setText("电流"); + ui->gaugePanel3->setText("水位"); + ui->gaugePanel4->setText("有功功率"); + ui->gaugePanel5->setText("有功电能"); + ui->gaugePanel6->setText("电网频率"); + + //设置小数点 + ui->gaugePanel3->setPrecision(1); + ui->gaugePanel4->setPrecision(2); + ui->gaugePanel5->setPrecision(1); + ui->gaugePanel3->setScalePrecision(1); + + //设置启用动画 + ui->gaugePanel4->setAnimation(true); + ui->gaugePanel5->setAnimation(true); + ui->gaugePanel5->setAnimationStep(0.2); + + //设置范围值 + ui->gaugePanel1->setRange(0, 500); + ui->gaugePanel2->setRange(0, 60); + ui->gaugePanel3->setRange(0, 2); + ui->gaugePanel4->setRange(0, 50); + ui->gaugePanel5->setRange(0, 70); + ui->gaugePanel6->setRange(0, 100); + + ui->horizontalSlider1->setRange(0, 500); + ui->horizontalSlider2->setRange(0, 60); + ui->horizontalSlider3->setRange(0, 200); + ui->horizontalSlider4->setRange(0, 50); + ui->horizontalSlider5->setRange(0, 70); + ui->horizontalSlider6->setRange(0, 100); + + //绑定滑块 + connect(ui->horizontalSlider1, SIGNAL(valueChanged(int)), ui->gaugePanel1, SLOT(setValue(int))); + connect(ui->horizontalSlider2, SIGNAL(valueChanged(int)), ui->gaugePanel2, SLOT(setValue(int))); + //connect(ui->horizontalSlider3, SIGNAL(valueChanged(int)), ui->gaugePanel3, SLOT(setValue(int))); + connect(ui->horizontalSlider4, SIGNAL(valueChanged(int)), ui->gaugePanel4, SLOT(setValue(int))); + connect(ui->horizontalSlider5, SIGNAL(valueChanged(int)), ui->gaugePanel5, SLOT(setValue(int))); + connect(ui->horizontalSlider6, SIGNAL(valueChanged(int)), ui->gaugePanel6, SLOT(setValue(int))); + + //设置初始值 + ui->horizontalSlider1->setValue(220); + ui->horizontalSlider2->setValue(32); + ui->horizontalSlider3->setValue(150); + ui->horizontalSlider4->setValue(6.34); + ui->horizontalSlider5->setValue(6.28); + ui->horizontalSlider6->setValue(50); +} + +void frmGaugePanel::on_horizontalSlider3_valueChanged(int value) +{ + double v = (double)value / 100; + ui->gaugePanel3->setValue(v); +} diff --git a/applications/examples/quc_demo/frmgaugepanel.h b/applications/examples/quc_demo/frmgaugepanel.h new file mode 100644 index 0000000..37d14e2 --- /dev/null +++ b/applications/examples/quc_demo/frmgaugepanel.h @@ -0,0 +1,27 @@ +#ifndef FRMGAUGEPANEL_H +#define FRMGAUGEPANEL_H + +#include +#include + +namespace Ui { +class frmGaugePanel; +} + +class frmGaugePanel : public QWidget +{ + Q_OBJECT + +public: + explicit frmGaugePanel(QWidget *parent = 0); + ~frmGaugePanel(); + +private: + Ui::frmGaugePanel *ui; + +private slots: + void initForm(); + void on_horizontalSlider3_valueChanged(int value); +}; + +#endif // FRMGAUGEPANEL_H diff --git a/applications/examples/quc_demo/frmgaugepanel.ui b/applications/examples/quc_demo/frmgaugepanel.ui new file mode 100644 index 0000000..04ea391 --- /dev/null +++ b/applications/examples/quc_demo/frmgaugepanel.ui @@ -0,0 +1,98 @@ + + + frmGaugePanel + + + + 0 + 0 + 500 + 300 + + + + Form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + + + + + + GaugePanel + QWidget +
gaugepanel.h
+
+
+ + +
diff --git a/applications/examples/quc_demo/gaugepanel.cpp b/applications/examples/quc_demo/gaugepanel.cpp new file mode 100644 index 0000000..f836645 --- /dev/null +++ b/applications/examples/quc_demo/gaugepanel.cpp @@ -0,0 +1,568 @@ +#pragma execution_character_set("utf-8") + +#include "gaugepanel.h" +#include "qpainter.h" +#include +#include "qmath.h" +#include "qtimer.h" +#include "qlcdnumber.h" +#include "qdebug.h" + +GaugePanel::GaugePanel(QWidget *parent) : QWidget(parent) +{ + minValue = 0; + maxValue = 100; + value = 0; + precision = 0; + scalePrecision = 0; + + scaleMajor = 10; + scaleMinor = 5; + startAngle = 45; + endAngle = 45; + + animation = false; + animationStep = 0.5; + + ringWidth = 10; + ringColor = QColor(54, 192, 254); + + scaleColor = QColor(34, 163, 169); + pointerColor = QColor(34, 163, 169); + bgColor = Qt::transparent; + textColor = QColor(50, 50, 50); + unit = "V"; + text = "电压"; + + reverse = false; + currentValue = 0; + timer = new QTimer(this); + timer->setInterval(10); + connect(timer, SIGNAL(timeout()), this, SLOT(updateValue())); + + //setFont(QFont("Arial", 9)); +} + +GaugePanel::~GaugePanel() +{ + if (timer->isActive()) + { + timer->stop(); + } +} + +void GaugePanel::paintEvent(QPaintEvent *) +{ + int width = this->width(); + int height = this->height(); + int side = qMin(width, height); + + //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放 + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); + + //绘制背景 + if (bgColor != Qt::transparent) + { + painter.setPen(Qt::NoPen); + painter.fillRect(this->rect(), bgColor); + } + + painter.translate(width / 2, height / 2); + painter.scale(side / 200.0, side / 200.0); + + //绘制圆环 + drawRing(&painter); + + //绘制刻度线 + drawScale(&painter); + + //绘制刻度值 + drawScaleNum(&painter); + + //绘制指示器 + drawPointer(&painter); + + //绘制当前值 + drawValue(&painter); +} + +void GaugePanel::drawRing(QPainter *painter) +{ + int radius = 70; + painter->save(); + + QPen pen; + pen.setCapStyle(Qt::FlatCap); + pen.setWidthF(ringWidth); + pen.setColor(ringColor); + painter->setPen(pen); + + radius = radius - ringWidth; + QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2); + double angleAll = 360.0 - startAngle - endAngle; + painter->drawArc(rect, (270 - startAngle - angleAll) * 16, angleAll * 16); + + painter->restore(); +} + +void GaugePanel::drawScale(QPainter *painter) +{ + int radius = 80; + painter->save(); + + painter->rotate(startAngle); + int steps = (scaleMajor * scaleMinor); + double angleStep = (360.0 - startAngle - endAngle) / steps; + + QPen pen; + pen.setCapStyle(Qt::RoundCap); + pen.setColor(scaleColor); + + for (int i = 0; i <= steps; i++) + { + if (i % scaleMinor == 0) + { + pen.setWidthF(1.5); + painter->setPen(pen); + painter->drawLine(0, radius - 8, 0, radius + 5); + } + else + { + pen.setWidthF(0.5); + painter->setPen(pen); + painter->drawLine(0, radius - 8, 0, radius - 3); + } + + painter->rotate(angleStep); + } + + painter->restore(); +} + +void GaugePanel::drawScaleNum(QPainter *painter) +{ + int radius = 95; + painter->save(); + painter->setPen(scaleColor); + + double startRad = (360 - startAngle - 90) * (M_PI / 180); + double deltaRad = (360 - startAngle - endAngle) * (M_PI / 180) / scaleMajor; + + for (int i = 0; i <= scaleMajor; i++) + { + double sina = qSin(startRad - i * deltaRad); + double cosa = qCos(startRad - i * deltaRad); + double value = 1.0 * i * ((maxValue - minValue) / scaleMajor) + minValue; + + QString strValue = QString("%1").arg((double)value, 0, 'f', scalePrecision); + 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 GaugePanel::drawPointer(QPainter *painter) +{ + int radius = 70; + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(pointerColor); + + QPolygon pts; + pts.setPoints(4, -5, 0, 0, -8, 5, 0, 0, radius); + + painter->rotate(startAngle); + double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue); + painter->rotate(degRotate); + painter->drawConvexPolygon(pts); + + painter->restore(); +} + +void GaugePanel::drawValue(QPainter *painter) +{ + int radius = 100; + painter->save(); + painter->setPen(textColor); + + QFont font; + font.setPixelSize(15); + painter->setFont(font); + + QString strValue = QString("%1").arg((double)currentValue, 0, 'f', precision); + strValue = QString("%1 %2").arg(strValue).arg(unit); + QRectF valueRect(-radius, radius / 3.5, radius * 2, radius / 3.5); + painter->drawText(valueRect, Qt::AlignCenter, strValue); + + QRectF textRect(-radius, radius / 2.5, radius * 2, radius / 2.5); + font.setPixelSize(12); + painter->setFont(font); + painter->drawText(textRect, Qt::AlignCenter, text); + + painter->restore(); +} + +void GaugePanel::updateValue() +{ + if (!reverse) + { + if (currentValue >= value) + { + timer->stop(); + } + else + { + currentValue += animationStep; + } + } + else + { + if (currentValue <= value) + { + timer->stop(); + } + else + { + currentValue -= animationStep; + } + } + + this->update(); +} + +double GaugePanel::getMinValue() const +{ + return this->minValue; +} + +double GaugePanel::getMaxValue() const +{ + return this->maxValue; +} + +double GaugePanel::getValue() const +{ + return this->value; +} + +int GaugePanel::getPrecision() const +{ + return this->precision; +} + +int GaugePanel::getScalePrecision() const +{ + return this->scalePrecision; +} + +int GaugePanel::getScaleMajor() const +{ + return this->scaleMajor; +} + +int GaugePanel::getScaleMinor() const +{ + return this->scaleMinor; +} + +int GaugePanel::getStartAngle() const +{ + return this->startAngle; +} + +int GaugePanel::getEndAngle() const +{ + return this->endAngle; +} + +bool GaugePanel::getAnimation() const +{ + return this->animation; +} + +double GaugePanel::getAnimationStep() const +{ + return this->animationStep; +} + +int GaugePanel::getRingWidth() const +{ + return this->ringWidth; +} + +QColor GaugePanel::getRingColor() const +{ + return this->ringColor; +} + +QColor GaugePanel::getScaleColor() const +{ + return this->scaleColor; +} + +QColor GaugePanel::getPointerColor() const +{ + return this->pointerColor; +} + +QColor GaugePanel::getBgColor() const +{ + return this->bgColor; +} + +QColor GaugePanel::getTextColor() const +{ + return this->textColor; +} + +QString GaugePanel::getUnit() const +{ + return this->unit; +} + +QString GaugePanel::getText() const +{ + return this->text; +} + +QSize GaugePanel::sizeHint() const +{ + return QSize(200, 200); +} + +QSize GaugePanel::minimumSizeHint() const +{ + return QSize(50, 50); +} + +void GaugePanel::setRange(double minValue, double maxValue) +{ + //如果最小值大于或者等于最大值则不设置 + if (minValue >= maxValue) + { + return; + } + + this->minValue = minValue; + this->maxValue = maxValue; + + //如果目标值不在范围值内,则重新设置目标值 + if (value < minValue || value > maxValue) + { + setValue(value); + } + + this->update(); +} + +void GaugePanel::setRange(int minValue, int maxValue) +{ + setRange((double)minValue, (double)maxValue); +} + +void GaugePanel::setMinValue(double minValue) +{ + setRange(minValue, maxValue); +} + +void GaugePanel::setMaxValue(double maxValue) +{ + setRange(minValue, maxValue); +} + +void GaugePanel::setValue(double value) +{ + //值和当前值一致则无需处理 + if (value == this->value) + { + return; + } + + //值小于最小值则取最小值,大于最大值则取最大值 + if (value < minValue) + { + value = minValue; + } + else if (value > maxValue) + { + value = maxValue; + } + + if (value > this->value) + { + reverse = false; + } + else if (value < this->value) + { + reverse = true; + } + + this->value = value; + emit valueChanged(value); + + if (!animation) + { + currentValue = this->value; + this->update(); + } + else + { + timer->start(); + } +} + +void GaugePanel::setValue(int value) +{ + setValue((double)value); +} + +void GaugePanel::setPrecision(int precision) +{ + //最大精确度为 3 + if (precision <= 3 && this->precision != precision) + { + this->precision = precision; + this->update(); + } +} + +void GaugePanel::setScalePrecision(int scalePrecision) +{ + //最大精确度为 2 + if (scalePrecision <= 2 && this->scalePrecision != scalePrecision) + { + this->scalePrecision = scalePrecision; + this->update(); + } +} + +void GaugePanel::setScaleMajor(int scaleMajor) +{ + if (this->scaleMajor != scaleMajor) + { + this->scaleMajor = scaleMajor; + this->update(); + } +} + +void GaugePanel::setScaleMinor(int scaleMinor) +{ + if (this->scaleMinor != scaleMinor) + { + this->scaleMinor = scaleMinor; + this->update(); + } +} + +void GaugePanel::setStartAngle(int startAngle) +{ + if (this->startAngle != startAngle) + { + this->startAngle = startAngle; + this->update(); + } +} + +void GaugePanel::setEndAngle(int endAngle) +{ + if (this->endAngle != endAngle) + { + this->endAngle = endAngle; + this->update(); + } +} + +void GaugePanel::setAnimation(bool animation) +{ + if (this->animation != animation) + { + this->animation = animation; + this->update(); + } +} + +void GaugePanel::setAnimationStep(double animationStep) +{ + if (this->animationStep != animationStep) + { + this->animationStep = animationStep; + this->update(); + } +} + +void GaugePanel::setRingWidth(int ringWidth) +{ + if (this->ringWidth != ringWidth) + { + this->ringWidth = ringWidth; + this->update(); + } +} + +void GaugePanel::setRingColor(const QColor &ringColor) +{ + if (this->ringColor != ringColor) + { + this->ringColor = ringColor; + this->update(); + } +} + +void GaugePanel::setScaleColor(const QColor &scaleColor) +{ + if (this->scaleColor != scaleColor) + { + this->scaleColor = scaleColor; + this->update(); + } +} + +void GaugePanel::setPointerColor(const QColor &pointerColor) +{ + if (this->pointerColor != pointerColor) + { + this->pointerColor = pointerColor; + this->update(); + } +} + +void GaugePanel::setBgColor(const QColor &bgColor) +{ + if (this->bgColor != bgColor) + { + this->bgColor = bgColor; + this->update(); + } +} + +void GaugePanel::setTextColor(const QColor &textColor) +{ + if (this->textColor != textColor) + { + this->textColor = textColor; + this->update(); + } +} + +void GaugePanel::setUnit(const QString &unit) +{ + if (this->unit != unit) + { + this->unit = unit; + this->update(); + } +} + +void GaugePanel::setText(const QString &text) +{ + if (this->text != text) + { + this->text = text; + this->update(); + } +} diff --git a/applications/examples/quc_demo/gaugepanel.h b/applications/examples/quc_demo/gaugepanel.h new file mode 100644 index 0000000..3a4dae3 --- /dev/null +++ b/applications/examples/quc_demo/gaugepanel.h @@ -0,0 +1,182 @@ +#ifndef GAUGEPANEL_H +#define GAUGEPANEL_H + +/** + * 面板仪表盘控件 作者:feiyangqingyun(QQ:517216493) 2019-7-3 + * 1:可设置范围值,支持负数值 + * 2:可设置精确度+刻度尺精确度,最大支持小数点后3位 + * 3:可设置大刻度数量/小刻度数量 + * 4:可设置开始旋转角度/结束旋转角度 + * 5:可设置是否启用动画效果以及动画效果每次移动的步长 + * 6:可设置刻度颜色+文字颜色+圆环的宽度和颜色 + * 7:自适应窗体拉伸,刻度尺和文字自动缩放 + * 8:可设置单位以及仪表盘名称 + */ + +#include +#include + +#ifdef quc +#if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) +#include +#else +#include +#endif + +class QDESIGNER_WIDGET_EXPORT GaugePanel : public QWidget +#else +class GaugePanel : public QWidget +#endif + +{ + Q_OBJECT + Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue) + Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue) + Q_PROPERTY(double value READ getValue WRITE setValue) + Q_PROPERTY(int precision READ getPrecision WRITE setPrecision) + Q_PROPERTY(int scalePrecision READ getScalePrecision WRITE setScalePrecision) + + Q_PROPERTY(int scaleMajor READ getScaleMajor WRITE setScaleMajor) + Q_PROPERTY(int scaleMinor READ getScaleMinor WRITE setScaleMinor) + Q_PROPERTY(int startAngle READ getStartAngle WRITE setStartAngle) + Q_PROPERTY(int endAngle READ getEndAngle WRITE setEndAngle) + + Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation) + Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep) + + Q_PROPERTY(int ringWidth READ getRingWidth WRITE setRingWidth) + Q_PROPERTY(QColor ringColor READ getRingColor WRITE setRingColor) + + Q_PROPERTY(QColor scaleColor READ getScaleColor WRITE setScaleColor) + Q_PROPERTY(QColor pointerColor READ getPointerColor WRITE setPointerColor) + Q_PROPERTY(QColor bgColor READ getBgColor WRITE setBgColor) + Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor) + Q_PROPERTY(QString unit READ getUnit WRITE setUnit) + Q_PROPERTY(QString text READ getText WRITE setText) + +public: + explicit GaugePanel(QWidget *parent = 0); + ~GaugePanel(); + +protected: + void paintEvent(QPaintEvent *); + void drawRing(QPainter *painter); + void drawScale(QPainter *painter); + void drawScaleNum(QPainter *painter); + void drawPointer(QPainter *painter); + void drawValue(QPainter *painter); + +private slots: + void updateValue(); + +private: + double minValue; //最小值 + double maxValue; //最大值 + double value; //目标值 + int precision; //精确度,小数点后几位 + int scalePrecision; //刻度尺精确度,小数点后几位 + + int scaleMajor; //大刻度数量 + int scaleMinor; //小刻度数量 + int startAngle; //开始旋转角度 + int endAngle; //结束旋转角度 + + bool animation; //是否启用动画显示 + double animationStep; //动画显示时步长 + + int ringWidth; //圆环宽度 + QColor ringColor; //圆环颜色 + + QColor scaleColor; //刻度颜色 + QColor pointerColor; //指针颜色 + QColor bgColor; //背景颜色 + QColor textColor; //文字颜色 + QString unit; //单位 + QString text; //描述文字 + + bool reverse; //是否往回走 + double currentValue; //当前值 + QTimer *timer; //定时器绘制动画 + +public: + double getMinValue() const; + double getMaxValue() const; + double getValue() const; + int getPrecision() const; + int getScalePrecision() const; + + int getScaleMajor() const; + int getScaleMinor() const; + int getStartAngle() const; + int getEndAngle() const; + + bool getAnimation() const; + double getAnimationStep() const; + + int getRingWidth() const; + QColor getRingColor() const; + + QColor getScaleColor() const; + QColor getPointerColor() const; + QColor getBgColor() const; + QColor getTextColor() const; + QString getUnit() const; + QString getText() const; + + QSize sizeHint() const; + QSize minimumSizeHint() const; + +public Q_SLOTS: + //设置范围值 + void setRange(double minValue, double maxValue); + void setRange(int minValue, int maxValue); + + //设置最大最小值 + void setMinValue(double minValue); + void setMaxValue(double maxValue); + + //设置目标值 + void setValue(double value); + void setValue(int value); + + //设置精确度 + void setPrecision(int precision); + //设置刻度尺精确度 + void setScalePrecision(int scalePrecision); + + //设置主刻度数量 + void setScaleMajor(int scaleMajor); + //设置小刻度数量 + void setScaleMinor(int scaleMinor); + //设置开始旋转角度 + void setStartAngle(int startAngle); + //设置结束旋转角度 + void setEndAngle(int endAngle); + + //设置是否启用动画显示 + void setAnimation(bool animation); + //设置动画显示的步长 + void setAnimationStep(double animationStep); + + //设置圆环宽度+颜色 + void setRingWidth(int ringWidth); + void setRingColor(const QColor &ringColor); + + //设置刻度颜色 + void setScaleColor(const QColor &scaleColor); + //设置指针颜色 + void setPointerColor(const QColor &pointerColor); + //设置背景颜色 + void setBgColor(const QColor &bgColor); + //设置文本颜色 + void setTextColor(const QColor &textColor); + //设置单位 + void setUnit(const QString &unit); + //设置中间描述文字 + void setText(const QString &text); + +Q_SIGNALS: + void valueChanged(int value); +}; + +#endif // GAUGEPANEL_H