一、前言

能夠新建布局,也是數據可視化大屏界面電子看板系統中的必備功能之一,新建布局這樣的功能一般做到右鍵菜單中,單擊新建布局菜單,彈出輸入框要求輸入新的布局的名稱,為了更符合國情,直接支持中文名稱,保存成配置文件直接中文名稱命名,這樣方便用戶理解,Qt5以來對亂碼的問題解決的就比較好了,不像Qt4時代稍不留神就亂碼了,Qt5隻要保證源碼文件utf-8編碼基本上就很少遇到亂碼問題了。新建布局必須要有個默認的窗體排列,Qt中的dock窗體,默認布局會以窗體的sizehint作為大小參照標準,也不一定是完全正確的,還跟窗體中的子控制項有關係,不過這些都不影響布局以後重新從配置文件載入的布局,QMainWindow提供saveState()函數直接保存當前窗體的所有布局位置大小等信息到配置文件,至於配置文件的內容格式,那是人類無法理解的格式,反正我是看不懂,這些都沒有關係的,你重新用restoreState()函數載入讀取配置文件的信息時,會自動應用,這樣就很爽很完美了。

二、電子看板介紹

電子看板是目視化管理的一種表現形式,即對數據的狀況一目了然地表現,主要是對於管理項目,它通過利用形象直觀而又色彩適宜的各種視覺感知信息來組織現場生產活動,目視管理依據人類的生理特徵,在生產現場充分利用信號燈、標識牌、符號顏色等方式來發出視覺信號,鮮明準確地刺激人的神經末梢,快速地傳遞信息,形象直觀地將潛在的問題和浪費現象都顯現出來。以便任何人都可以及時掌握管理現狀和必要的情報,從而能夠快速制定並實施應對措施。因此,管理看板是發現問題、解決問題的非常有效且直觀的手段,是優秀的現場管理必不可少的工具之一。

三、功能特點

1. 整體總共分三級界面,一級界面是整體布局,二級界面是單個功能模塊,三級界面是單個控制項。

2. 子控制項包括餅圖+圓環圖+曲線圖+柱狀圖+柱狀分組圖+橫向柱狀圖+橫向柱狀分組圖+合格率控制項+百分比控制項+進度控制項+設備狀態面板+表格數據+地圖控制項+視頻控制項+其他控制項等。

3. 二級界面可以自由拖動懸浮,支持最小化最大化關閉,響應雙擊自定義標題欄。

4. 數據源支持資料庫採集(默認)、網路通信、網路請求等,可自由設定每個子界面的採集間隔即數據刷新頻率。

5. 採用純QWidget編寫,支持Qt4.6到Qt5.12.3任何版本,支持嵌入式linux比如樹莓派、香橙派、全志、imx6等。

6. 提供三個內核版本,自定義控制項版本+qchart版本+echart版本。

7. 內置多套配色風格樣式,默認紫色,支持任何解析度。

8. 可設置標題+目標解析度+布局方案,啟動立即應用。

9. 可設置主背景顏色+面板顏色+十字線游標顏色。

10. 可設置多條曲線顏色,沒有設置顏色的情況下內置15套精美顏色隨機應用。

11. 可設置標題欄背景顏色+文字顏色。

12. 可設置曲線圖表背景顏色+文字顏色+網格顏色。

13. 可設置正常顏色+警戒顏色+報警顏色+禁用顏色+百分比進度顏色。

14. 可分別設置各種字體大小,比如全局+軟體名稱+標題欄+子標題欄+加粗標籤等。

15. 可設置標題欄高度+表頭高度+行高度。

16. 曲線支持游標+懸停高亮數據點和顯示值,柱狀圖支持頂部(可設置頂端+上部+中間+底部)顯示數據,全部自適應計算位置。

17. 主界面直接滑鼠右鍵切換布局+配色方案+關閉開啟某個二級窗體。

18. 自動記憶所有子窗口的大小和位置,下次啟動立即應用。

19. 動態載入布局方案菜單,可以動態新建布局、恢復布局、保存布局、另存布局等,用戶可以製造任意布局。

20. 二級窗體,雙擊從主窗體分離出來浮動,可以自由調整大小。再次雙擊標題欄最大化,再次雙擊還原。

21. 每個模塊都可以自定義採集速度,如果是資料庫採集會自動排隊處理。

五、特別說明

1. 可執行文件同級文件夾有layout+layout_1440+layout_1920,程序默認自動識別解析度並載入對應的布局文件夾,比如1920解析度則從layout_1920文件夾載入布局,並作為整體布局文件夾。

2. 程序默認是模擬數據,如果需要從資料庫採集則修改配置文件WorkMode=db即可。

3. 如果發現布局拖動亂了,可以直接滑鼠右鍵選擇恢復布局即可,在保存布局以前。

4. 在中間地圖模塊滑鼠右鍵可以彈出菜單,切換布局和配色方案等。

5. 在模塊的標題欄上右鍵可以彈出默認的dock菜單,用來顯示和隱藏各模塊。

6. 軟體關閉過程中會自動保存布局,下次啟動以後自動應用。

7. 如果使用的默認的默認的配色方案比如紫色風格,則配置文件中的顏色全部無效,會自動應用代碼中的顏色,如果需要啟用自定義的顏色,則將配置文件的 Theme=x81eax5b9ax4e49x98cex683c 即可。此時打開軟體會應用配置文件中的顏色。

8. 右鍵菜單可以截圖保存,默認命名為 配色方案名稱_布局方案名稱.png 保存在snap目錄下。

9. 如果是XP系統請先執行fixff.cmd,用來修復ffmpeg在XP上不可用的BUG。

10. 可執行文件下載地址:pan.baidu.com/s/1o97IGv 提取碼:r2bv ,會不定期更新程序,歡迎各位提出批評和建議。

六、效果圖

七、核心代碼

#include "frmmodulecenter.h"
#include "ui_frmmodulecenter.h"
#include "quiwidget.h"

frmModuleCenter::frmModuleCenter(QWidget *parent) : QWidget(parent), ui(new Ui::frmModuleCenter)
{
ui->setupUi(this);
this->initForm();
}

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

bool frmModuleCenter::eventFilter(QObject *watched, QEvent *event)
{
if (watched == this) {
if (event->type() == QEvent::MouseButtonPress) {
if (qApp->mouseButtons() == Qt::RightButton) {
menuMain->exec(QCursor::pos());
}
}
}

return QWidget::eventFilter(watched, event);
}

void frmModuleCenter::initForm()
{
ui->labName->setText(App::Title);
this->installEventFilter(this);

//滑鼠右鍵菜單
menuMain = new QMenu(this);

//從目錄下找布局文件自動生成菜單
menuLayout = menuMain->addMenu("布局方案");
QDir dir(App::LayoutPath);
QStringList files = dir.entryList(QStringList() << "*.ini");
foreach (QString file, files) {
QString name = file.split(".").first();
menuLayout->addAction(name, this, SLOT(changeLayout()));
}

menuTheme = menuMain->addMenu("配色方案");
menuTheme->addAction("紫色風格", this, SLOT(changeTheme()));
menuTheme->addAction("藍色風格", this, SLOT(changeTheme()));
menuTheme->addAction("深藍風格", this, SLOT(changeTheme()));
menuTheme->addAction("黑色風格", this, SLOT(changeTheme()));
menuTheme->addAction("自定義風格", this, SLOT(changeTheme()));
menuMain->addSeparator();

menuMain->addAction("新建布局", this, SLOT(doAction()));
menuMain->addAction("恢復布局", this, SLOT(doAction()));
menuMain->addAction("保存布局", this, SLOT(doAction()));
menuMain->addAction("布局另存", this, SLOT(doAction()));
menuMain->addSeparator();

menuMain->addAction("截取屏幕", this, SLOT(doAction()));
menuMain->addAction("退出系統", this, SLOT(doAction()));

//設置菜單允許複選框+選中配置文件對應菜單
actionLayout = menuLayout->actions();
foreach (QAction *action, actionLayout) {
action->setCheckable(true);
action->setChecked(action->text() == App::Layout);
}

actionTheme = menuTheme->actions();
foreach (QAction *action, actionTheme) {
action->setCheckable(true);
action->setChecked(action->text() == App::Theme);
}
}

void frmModuleCenter::changeLayout()
{
QAction *ac = (QAction *)sender();
emit changeLayout(ac->text());
foreach (QAction *action, actionLayout) {
action->setChecked(action == ac);
}
}

void frmModuleCenter::changeTheme()
{
QAction *ac = (QAction *)sender();
emit changeTheme(ac->text());
foreach (QAction *action, actionTheme) {
action->setChecked(action == ac);
}
}

void frmModuleCenter::addLayout(const QString &layout, int type)
{
if (!layout.isEmpty()) {
//判斷名稱不能重複
foreach (QAction *action, actionLayout) {
if (action->text() == layout) {
QUIHelper::showMessageBoxError("布局已經存在,請重新輸入!", 3);
return;
}
}

//增加右鍵菜單中的布局子菜單
QAction *action = menuLayout->addAction(layout, this, SLOT(changeLayout()));
//取消原有所有選中
foreach (QAction *action, actionLayout) {
action->setChecked(false);
}

action->setCheckable(true);
action->setChecked(true);
actionLayout.append(action);
emit saveLayout(layout, type);
}
}

void frmModuleCenter::doAction()
{
QAction *action = (QAction *)sender();
QString text = action->text();

if (text == "新建布局") {
QString layout = QUIHelper::showInputBox("布局名稱");
addLayout(layout, 0);
} else if (text == "恢復布局") {
emit saveLayout("", 1);
} else if (text == "保存布局") {
if (QUIHelper::showMessageBoxQuestion("確定要保存嗎?保存後不可恢復!") == QMessageBox::Yes) {
emit saveLayout(App::Layout, 2);
QUIHelper::showMessageBoxInfo("恭喜,保存當前布局成功!", 3);
}
} else if (text == "布局另存") {
QString layout = QUIHelper::showInputBox("布局名稱");
addLayout(layout, 3);
} else if (text == "截取屏幕") {
QWidget *w = (QWidget *)this->parent();
if (w == 0) {
return;
}

QPixmap pix;
int x = 0;
int y = 0;
int width = w->width() - 0;
int height = w->height() - 0;

#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
pix = pix.grabWindow(w->winId(), x, y, width, height);
#else
QScreen *pscreen = QApplication::primaryScreen();
pix = pscreen->grabWindow(w->winId(), x, y, width, height);
#endif

QString file = QString("%1/snap/%2_%3.png").arg(QUIHelper::appPath()).arg(App::Theme).arg(App::Layout);
pix.save(file, "png");
} else if (text == "退出系統") {
emit closeAll();
}
}

推薦閱讀:

相关文章