1. 程式人生 > 其它 >Qt編寫視覺化大屏電子看板系統26-模組4模具進度

Qt編寫視覺化大屏電子看板系統26-模組4模具進度

一、前言

模具進度主要用來展示不同的模具類別加工進度,表格的形式展示,顯示內容包括模具編號、版本號、型別、狀態、產品名稱、計劃交期、當前進度,其中進度條採用自定義控制元件三態進度條,有三種狀態顯示進度;右側有兩個小模組分別是模具狀態統計、加工中模具數量,其中模具狀態統計分別顯示正常交付比例、加工中比例、延期比例;加工中模具數量採用自定義控制元件儀表盤顯示數量值。

由於之前就編寫過接近200個自定義控制元件,所以對自定義控制元件這塊非常熟悉,在整個大屏系統中好多控制元件直接利用現成的,部分需求直接改改換個程式碼就能用,不得不感謝Qt在這方面封裝的特別好。

子模組表名對應表:

子模組標題 子模組表名
模具進度 t_4_1_mold_progress
模具狀態統計 t_4_2_mold_status_parcent
加工中模具數量 t_4_3_mold_processing_num

1 模具進度

表名:t_3_2_oee

欄位名 中文名 型別 長度 說明
internal_id 序號 INTEGER 11 主鍵自增
mold_no 模具編號 VARCHAR 11
tn_no 版本號 VARCHAR 11
type 型別 VARCHAR 255
status 狀態 VARCHAR 255
product_name 產品名稱 VARCHAR 255
plan_date 計劃交期 VARCHAR 255
green 當前進度綠色 INTEGER 11
yellow 當前進度黃色 INTEGER 11
red 當前進度紅色 INTEGER 11

預設資料:

internal_id mold_no tn_no type status product_name plan_date green yellow red
1 IK19001 T0 新模 加工中 後蓋 2019/3/29 60 20 20
2 IK19002 T1 修模 加工中 前蓋 2019/4/3 50 50 0
3 IK29003 T2 修模 加工中 外殼 2019/4/8 30 70 0
4 IK19004 T0 新模 加工中 側邊 2019/4/18 90 5 5
5 IK19005 T3 修模 加工中 邊框 2019/4/3 60 40 0
6 IK19006 T0 新模 加工中 後蓋 2019/4/26 70 25 5
7 IK19007 T0 新模 加工中 面板 2019/4/7 25 25 50
8 IK19008 T0 新模 加工中 外掛 2019/3/31 20 40 40
9 IK19009 T1 修模 加工中 面板 2019/3/12 10 60 30
10 IK19010 T2 修模 加工中 後蓋 2019/2/12 0 100 0

2 模具狀態統計

表名:t_4_2_mold_status_parcent

欄位名 中文名 型別 長度 說明
internal_id 序號 INTEGER 11 主鍵自增
finished 正常交付百分比 INTEGER 11 不為空
processing 加工中百分比 INTEGER 11 不為空
delay 延期百分比 INTEGER 11 不為空

預設資料:1 60 25 15

3 加工中模具數量

表名:t_4_3_mold_processing_num

欄位名 中文名 型別 長度 說明
internal_id 序號 INTEGER 11 主鍵自增
mold_processing_number 加工中數量 INTEGER 11 不為空

預設資料:87

二、功能特點

  1. 採用分層設計,整體總共分三級介面,一級介面是整體佈局,二級介面是單個功能模組,三級介面是單個控制元件。
  2. 子控制元件包括餅圖、圓環圖、曲線圖、柱狀圖、柱狀分組圖、橫向柱狀圖、橫向柱狀分組圖、合格率控制元件、百分比控制元件、進度控制元件、裝置狀態面板、表格資料、地圖控制元件、視訊控制元件等。
  3. 二級介面可以自由拖動懸浮,支援最小化隱藏、最大化關閉、響應雙擊自定義標題欄。
  4. 資料來源支援模擬資料(預設)、資料庫採集、串列埠通訊(需定製)、網路通訊(需定製)、網路請求等,可自由設定每個子介面的採集間隔即資料重新整理頻率。
  5. 採用純QWidget編寫,親測Qt4.6到Qt6.2任意版本,理論上支援後續其他Qt版本。
  6. 超強跨平臺,親測windows、linux、mac、國產uos、國產銀河麒麟kylin等系統,效果完美,同時還支援嵌入式linux比如樹莓派、香橙派、全志、imx6等。
  7. 同時集成了自定義控制元件、qchart餅圖、echart地圖等功能。
  8. 內建多套配色風格樣式(紫色、藍色、深藍、黑色),預設紫色,自適應任意解析度。
  9. 可設定系統標題、目標解析度、佈局方案,啟動立即應用。
  10. 可設定主背景顏色、面板顏色、十字線遊標顏色等各種顏色。
  11. 可設定多條曲線不同顏色,沒有設定顏色的情況下內建多套精美顏色隨機應用。
  12. 可設定標題欄背景顏色、文字顏色。
  13. 可設定曲線圖表背景顏色、文字顏色、網格顏色。
  14. 可設定正常顏色、警戒顏色、報警顏色、禁用顏色、百分比進度顏色。
  15. 可分別設定各種字型大小,比如全域性字型、軟體名稱、標題欄、子標題欄、加粗標籤等。
  16. 可設定標題欄高度、表頭高度、行高度。
  17. 曲線支援遊標、定位線、懸停高亮資料點、懸停顯示值。
  18. 柱狀圖支援頂部(可設定頂端、上部、中間、底部)顯示資料,全部自適應計算位置。
  19. 支援平滑曲線,內建多種平滑曲線演算法,還支援面積圖平滑。
  20. 面積圖填充顏色可選多種規則比如單色透明度填充、透明度漸變填充等。
  21. 資料庫支援sqlite、mysql、postgresql、oracle、國產人大金倉等資料庫。
  22. 主介面直接滑鼠右鍵切換佈局、配色方案、關閉開啟某個二級窗體。
  23. 自動記憶所有子視窗的大小和位置,下次啟動立即應用。
  24. 動態載入佈局方案選單,可以動態新建佈局、恢復佈局、儲存佈局、另存佈局等,使用者可以製造任意佈局。
  25. 二級窗體,雙擊從主窗體分離出來浮動,可以自由調整大小。再次雙擊標題欄最大化,再次雙擊還原。
  26. 子模組也可以全屏顯示作為一個大屏,這樣就可以一個大屏拓展出多個子大屏,放大檢視子模組的資料詳情,適用多屏展示。
  27. 每個模組都可以自定義採集速度,如果是資料庫採集會自動排隊處理,後期還可以拓展每個子模組都獨立的資料庫採集。
  28. 提供系統設定模組進行整體的配置引數設定,效果立即應用。
  29. 提供精美炫酷的大屏地圖模組,包括靜態圖片、閃爍效果、遷徙效果、世界地圖、區域地圖等,可指定點的經緯度座標,識別單擊響應,可以做地圖跳轉等,每個點都可以不同的顏色和提示資訊。
  30. 除了提供大屏系統外,還將每個模組都做了獨立的模組示例介面,每個模組都可以獨立學習使用,裡面用到的控制元件也單獨做了控制元件示例介面,方便學習每個控制元件如何使用。
  31. 非常詳細的開發和使用手冊,其中包括資料庫說明、模組對照圖、控制元件對照圖、專案結構、程式碼說明(精確到每個類)、演示demo、使用方法等。

三、體驗地址

  1. 體驗地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取碼:01jf 檔名:bin_bigscreen.zip。
  2. 國內站點:https://gitee.com/feiyangqingyun
  3. 國際站點:https://github.com/feiyangqingyun
  4. 個人主頁:https://blog.csdn.net/feiyangqingyun
  5. 知乎主頁:https://www.zhihu.com/people/feiyangqingyun/
  6. 線上文件:https://feiyangqingyun.gitee.io/qwidgetdemo/bigscreen/

四、效果圖

五、核心程式碼

#include "frmmodule4.h"
#include "ui_frmmodule4.h"
#include "quihelper.h"
#include "progressthree.h"

frmModule4::frmModule4(QWidget *parent) : QWidget(parent), ui(new Ui::frmModule4)
{
    ui->setupUi(this);
    this->initForm();
    this->initPie();
    this->initGauge();
    this->initTable();
}

frmModule4::~frmModule4()
{
    delete ui;
}

void frmModule4::initForm()
{
    //設定對應的屬性應用特定樣式
    ui->labTitle1->setProperty("flag", "title");
    ui->labTitle2->setProperty("flag", "title");
    ui->labTitle3->setProperty("flag", "title");

    ui->widgetSub1->setProperty("flag", "sub");
    ui->widgetSub2->setProperty("flag", "sub");
    ui->widgetSub3->setProperty("flag", "sub");

#ifdef qchart
    pie = new CustomChart;
#else
    pie = new CustomPie;
#endif

    pie->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    ui->widgetSub1->layout()->addWidget(pie);

    //定時器模擬資料
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(loadPie()));
    connect(timer, SIGNAL(timeout()), this, SLOT(loadGauge()));
    connect(timer, SIGNAL(timeout()), this, SLOT(loadTable()));

    //繫結訊號槽處理接收的資料+傳送執查詢語句
    connect(DbData::DbLocal, SIGNAL(receiveData(QString, QStringList, int)),
            this, SLOT(receiveData(QString, QStringList, int)));
    connect(DbData::DbHttp, SIGNAL(receiveData(QString, QStringList, int)),
            this, SLOT(receiveData(QString, QStringList, int)));
}

void frmModule4::receiveData(const QString &tag, const QStringList &data, int mesc)
{
    int count = data.count();
    if (tag == "t_4_2_mold_status_parcent") {
        if (count == 3) {
            int value1 = data.at(0).toDouble();
            int value2 = data.at(1).toDouble();
            int value3 = data.at(2).toDouble();
            loadPie(value1, value2, value3);
        }
    } else if (tag == "t_4_3_mold_processing_num") {
        if (count == 1) {
            int value1 = data.at(0).toDouble();
            loadGauge(value1);
        }
    } else if (tag == "t_4_1_mold_progress") {
        if (count % 10 == 0) {
            lstringl values;
            ui->tableWidget->setRowCount(count / 10);
            for (int i = 0; i < count; i = i + 10) {
                QStringList value;
                value << data.at(i);
                value << data.at(i + 1);
                value << data.at(i + 2);
                value << data.at(i + 3);
                value << data.at(i + 4);
                value << data.at(i + 5);
                value << data.at(i + 6);
                int green = data.at(i + 7).toInt();
                int yellow = data.at(i + 8).toInt();
                int red = data.at(i + 9).toInt();
                value << QString("%1|%2|%3").arg(green).arg(yellow).arg(red);
                values << value;
            }

            loadTable(values);
        }
    }
}

void frmModule4::initPie()
{
    lcolor colors;
    colors << QColor(0, 176, 80) << QColor(65, 176, 255) << QColor(255, 192, 0) << QColor(255, 0, 0);

    pie->setColors(colors);
    pie->setDefaultColor(false);
    pie->initPie();
}

void frmModule4::loadPie()
{
    QString tableName = "t_4_2_mold_status_parcent";
    QString columnName = "finished,processing,delay";

    if (AppConfig::WorkMode == "timer") {
        int value1 = QUIHelper::getRandValue(30, 60);
        int value2 = QUIHelper::getRandValue(30, 60);
        int value3 = QUIHelper::getRandValue(30, 60);
        loadPie(value1, value2, value3);
    } else if (AppConfig::WorkMode == "db") {
        DbData::DbLocal->select(tableName, columnName, true);
    } else if (AppConfig::WorkMode == "http") {
        DbData::DbHttp->select(tableName, columnName, true);
    }
}

void frmModule4::loadPie(int value1, int value2, int value3)
{
    pie->clearPie();
    pie->appendPie("正常交付", value1);
    pie->appendPie("加工中", value2);
    pie->appendPie("延期", value3);
    pie->loadPercent();
}

void frmModule4::initGauge()
{
    ui->gaugeSpeed->setUnit("");
    ui->gaugeSpeed->setText("模具數");
    ui->gaugeSpeed->setPrecision(0);
    ui->gaugeSpeed->setRange(0, 100);
}

void frmModule4::loadGauge()
{
    QString tableName = "t_4_3_mold_processing_num";
    QString columnName = "mold_processing_number";

    if (AppConfig::WorkMode == "timer") {
        loadGauge(QUIHelper::getRandValue(30, 100));
    } else if (AppConfig::WorkMode == "db") {
        DbData::DbLocal->select(tableName, columnName, true);
    } else if (AppConfig::WorkMode == "http") {
        DbData::DbHttp->select(tableName, columnName, true);
    }
}

void frmModule4::loadGauge(int value)
{
    //最大值=值往上取百整數
    int max = (value / 100 + 1) * 100;
    ui->gaugeSpeed->setDigitCount(QString::number(max).length());
    ui->gaugeSpeed->setRange(0, max);
    ui->gaugeSpeed->setValue(value);
}

void frmModule4::initTable()
{
    QStringList headText;
    headText << "序號" << "模具編號" << "版本號" << "型別" << "狀態" << "產品名稱" << "計劃交期" << "當前進度";

    int columnCount = headText.count();
    ui->tableWidget->setColumnCount(columnCount);
    ui->tableWidget->setHorizontalHeaderLabels(headText);
    ui->tableWidget->horizontalHeader()->setMinimumHeight(AppConfig::HeadHeight);
    ui->tableWidget->verticalHeader()->setDefaultSectionSize(AppConfig::RowHeight);

    QList<int> widths;
    widths << 50 << 80 << 60 << 70 << 70 << 80 << 130 << 80;
    for (int i = 0; i < columnCount; i++) {
        ui->tableWidget->setColumnWidth(i, widths.at(i));
    }

    ui->tableWidget->setFocusPolicy(Qt::NoFocus);
    ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    //ui->tableWidget->setAlternatingRowColors(true);
    ui->tableWidget->verticalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
    ui->tableWidget->horizontalHeader()->setHighlightSections(false);
}

void frmModule4::loadTable()
{
    QString tableName = "t_4_1_mold_progress";
    QString columnName = "internal_id,mold_no,tn_no,type,status,product_name,plan_date,green,yellow,red";

    if (AppConfig::WorkMode == "timer") {
        lstringl values;
        int rowCount = 21;
        ui->tableWidget->setRowCount(rowCount);
        for (int i = 0; i < rowCount; i++) {
            QStringList value;
            value << QString::number(i + 1);
            value << QString("FK%1").arg(i + 1);
            value << QString("V%1").arg(i + 1);
            value << (QUIHelper::getRandValue(1, 3) == 1 ? "修模" : "新模");
            value << QString("加工中");
            value << (QUIHelper::getRandValue(1, 3) == 1 ? "後蓋" : "面板");
            value << QString("2019-04-%1").arg(i + 10);

            QStringList list;
            for (int i = 0; i < 3; ++i) {
                list << QString::number(QUIHelper::getRandValue(10, 50));
            }
            value << list.join("|");
            values << value;
        }

        loadTable(values);
    } else if (AppConfig::WorkMode == "db") {
        DbData::DbLocal->select(tableName, columnName, true);
    } else if (AppConfig::WorkMode == "http") {
        DbData::DbHttp->select(tableName, columnName, true);
    }
}

void frmModule4::loadTable(const lstringl &values)
{
    int rowCount = values.count();
    for (int i = 0; i < rowCount; i++) {
        QStringList value = values.at(i);
        int columnCount = value.count();
        for (int j = 0; j < columnCount; j++) {
            //末尾資料為進度條
            if (j == columnCount - 1) {
                QString data = value.at(j);
                QStringList list = data.split("|");
                if (list.count() != 3) {
                    continue;
                }

                //自定義多型進度條
                ProgressThree *progress = new ProgressThree;
                progress->setValue1(list.at(0).toInt());
                progress->setValue2(list.at(1).toInt());
                progress->setValue3(list.at(2).toInt());
                progress->setFixedHeight(15);

                //增加widget+佈局巧妙實現居中
                QWidget *widget = new QWidget;
                QHBoxLayout *layout = new QHBoxLayout;
                layout->setSpacing(0);
                layout->setContentsMargins(0, 0, 0, 0);
                layout->addWidget(progress);
                widget->setLayout(layout);
                ui->tableWidget->setCellWidget(i, j, widget);
            } else {
                QTableWidgetItem *item = new QTableWidgetItem(value.at(j));
                item->setTextAlignment(Qt::AlignCenter);
                ui->tableWidget->setItem(i, j, item);
            }
        }
    }
}

void frmModule4::start(int interval)
{
    this->loadGauge();
    this->loadPie();
    this->loadTable();

    //如果間隔太短表示不需要重新整理,執行一次即可
    if (interval > 2000) {
        timer->start(interval);
    }
}

void frmModule4::stop()
{
    if (timer->isActive()) {
        timer->stop();
    }
}