前言
目前大屏大数据可视化UI这块非常火,趁热也用Qt来实现一个,Qt这个一站式超大型GUI超市,没有什么他做不了的,大屏电子看板当然也不在话下,有了QSS和QPainter这两个无敌的工具组合,借用几个Qt高手朋友的话来说,都是分分钟。在整个系统的编写过程中,发现数学知识真的还是蛮重要的,在重要的几个算法点上,需要多次用到二元一次方程才能搞定几个算法,比如如何分组绘制柱状图。
电子看板介绍
电子看板是目视化管理的一种表现形式,即对数据的状况一目了然地表现,主要是对于管理项目,它通过利用形象直观而又色彩适宜的各种视觉感知信息来组织现场生产活动,目视管理依据人类的生理特征,在生产现场充分利用信号灯、标识牌、符号颜色等方式来发出视觉信号,鲜明准确地刺激人的神经末梢,快速地传递信息,形象直观地将潜在的问题和浪费现象都显现出来。以便任何人都可以及时掌握管理现状和必要的情报,从而能够快速制定并实施应对措施。因此,管理看板是发现问题、解决问题的非常有效且直观的手段,是优秀的现场管理必不可少的工具之一。(这段是复制的,哈哈!)
架构分析
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:曲线支持游标+悬停高亮数据点和显示值,柱状图支持顶部(可设置顶端+上部+中间+底部)显示数据,全部自适应计算位置。




部分代码
#include "appinit.h"
#include "quiwidget.h"
QScopedPointer<AppInit> AppInit::self;
AppInit *AppInit::Instance()
{
if (self.isNull()) {
static QMutex mutex;
QMutexLocker locker(&mutex);
if (self.isNull()) {
self.reset(new AppInit);
}
}
return self.data();
}
AppInit::AppInit(QObject *parent) : QObject(parent)
{
}
bool AppInit::eventFilter(QObject *watched, QEvent *event)
{
QWidget *w = (QWidget *)watched;
if (!w->property("canMove").toBool()) {
return QObject::eventFilter(watched, event);
}
static QPoint mousePoint;
static bool mousePressed = false;
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->type() == QEvent::MouseButtonPress) {
if (mouseEvent->button() == Qt::LeftButton) {
mousePressed = true;
mousePoint = mouseEvent->globalPos() - w->pos();
return true;
}
} else if (mouseEvent->type() == QEvent::MouseButtonRelease) {
mousePressed = false;
return true;
} else if (mouseEvent->type() == QEvent::MouseMove) {
if (mousePressed && (mouseEvent->buttons() && Qt::LeftButton)) {
w->move(mouseEvent->globalPos() - mousePoint);
return true;
}
}
return QObject::eventFilter(watched, event);
}
void AppInit::start()
{
//绑定全局事件过滤器用于无边框窗体移动和其他处理
qApp->installEventFilter(this);
//初始化随机数
QUIHelper::initRand();
//设置编码
QUIHelper::setCode();
//设置翻译文件
QUIHelper::setTranslator(":/image/qt_zh_CN.qm");
QUIHelper::setTranslator(":/image/widgets.qm");
//载入配置文件
App::ConfigFile = QString("%1/config/%2.ini").arg(QUIHelper::appPath()).arg(QUIHelper::appName());
App::readConfig();
//初始化配色方案
this->initTheme();
//初始化字体
this->initFont();
//初始化数据库
this->initDb();
//初始化样式表
this->initStyle();
}
void AppInit::initTheme()
{
//根据选定风格设置配色方案,如果想用自己的配色方案则Theme设置为不是下面的几种即可
if (App::Theme == "purple") {
App::ColorMainBg = QColor(4, 7, 38).name();
App::ColorPanelBg = QColor(26, 29, 60).name();
App::ColorLine = QColor(255, 0, 0).name();
App::ColorLine1 = QColor(0, 176, 180).name();
App::ColorLine2 = QColor(32, 159, 223).name();
App::ColorLine3 = QColor(255, 192, 0).name();
App::ColorTitleBg = QColor(48, 48, 85).name();
App::ColorTitleText = QColor(255, 255, 255).name();
App::ColorChartBg = QColor(38, 41, 74).name();
App::ColorChartText = QColor(250, 250, 250).name();
App::ColorChartGrid = QColor(180, 180, 180).name();
App::ColorOk = QColor(0, 176, 180).name();
App::ColorLow = QColor(255, 192, 0).name();
App::ColorAlarm = QColor(214, 77, 84).name();
App::ColorDisable = QColor(210, 210, 210).name();
App::ColorPercent = QColor(0, 254, 254).name();
} else if (App::Theme == "blue") {
App::ColorMainBg = QColor(4, 26, 72).name();
App::ColorPanelBg = QColor(4, 31, 84).name();
App::ColorLine = QColor(214, 77, 84).name();
App::ColorLine1 = QColor(42, 167, 247).name();
App::ColorLine2 = QColor(40, 219, 216).name();
App::ColorLine3 = QColor(223, 126, 49).name();
App::ColorTitleBg = QColor(4, 46, 106).name();
App::ColorTitleText = QColor(245, 252, 254).name();
App::ColorChartBg = QColor(17, 60, 120).name();
App::ColorChartText = QColor(250, 250, 250).name();
App::ColorChartGrid = QColor(41, 167, 245).name();
App::ColorOk = QColor(41, 165, 243).name();
App::ColorLow = QColor(255, 192, 0).name();
App::ColorAlarm = QColor(214, 77, 84).name();
App::ColorDisable = QColor(210, 210, 210).name();
App::ColorPercent = QColor(0, 254, 254).name();
} else if (App::Theme == "darkblue") {
App::ColorMainBg = QColor(18, 27, 58).name();
App::ColorPanelBg = QColor(26, 48, 80).name();
App::ColorLine = QColor(214, 77, 84).name();
App::ColorLine1 = QColor(105, 207, 255).name();
App::ColorLine2 = QColor(54, 232, 184).name();
App::ColorLine3 = QColor(255, 217, 84).name();
App::ColorTitleBg = QColor(37, 75, 111).name();
App::ColorTitleText = QColor(103, 221, 251).name();
App::ColorChartBg = QColor(24, 29, 59).name();
App::ColorChartText = QColor(252, 253, 254).name();
App::ColorChartGrid = QColor(98, 192, 238).name();
App::ColorOk = QColor(41, 165, 243).name();
App::ColorLow = QColor(255, 192, 0).name();
App::ColorAlarm = QColor(214, 77, 84).name();
App::ColorDisable = QColor(210, 210, 210).name();
App::ColorPercent = QColor(0, 254, 254).name();
} else if (App::Theme == "black") {
App::ColorMainBg = QColor(25, 25, 44).name();
App::ColorPanelBg = QColor(36, 39, 62).name();
App::ColorLine = QColor(214, 77, 84).name();
App::ColorLine1 = QColor(0, 188, 212).name();
App::ColorLine2 = QColor(3, 169, 244).name();
App::ColorLine3 = QColor(255, 235, 59).name();
App::ColorTitleBg = QColor(50, 50, 72).name();
App::ColorTitleText = QColor(225, 226, 229).name();
App::ColorChartBg = QColor(30, 30, 49).name();
App::ColorChartText = QColor(252, 253, 254).name();
App::ColorChartGrid = QColor(206, 207, 212).name();
App::ColorOk = QColor(41, 165, 243).name();
App::ColorLow = QColor(255, 192, 0).name();
App::ColorAlarm = QColor(214, 77, 84).name();
App::ColorDisable = QColor(210, 210, 210).name();
App::ColorPercent = QColor(0, 254, 254).name();
}
}
void AppInit::initFont()
{
//字体放大,如果想用自定义的字体大小则设置分辨率不为下面三种即可
if (App::Ratio == "1920*1080") {
App::MainFont = 12;
App::NameFont = 22;
App::LabFont = 14;
App::DeviceFont = 14;
App::SubTitleFont = 15;
App::TitleFont = 20;
App::TitleHeight = 30;
App::HeadHeight = 30;
App::RowHeight = 27;
} else if (App::Ratio == "2560*1440") {
App::MainFont = 13;
App::NameFont = 30;
App::LabFont = 16;
App::DeviceFont = 16;
App::SubTitleFont = 18;
App::TitleFont = 23;
App::TitleHeight = 35;
App::HeadHeight = 32;
App::RowHeight = 28;
} else if (App::Ratio == "4096*2160") {
App::MainFont = 15;
App::NameFont = 75;
App::LabFont = 20;
App::DeviceFont = 20;
App::SubTitleFont = 22;
App::TitleFont = 28;
App::TitleHeight = 40;
App::HeadHeight = 35;
App::RowHeight = 30;
}
QFont font;
//微软雅黑 思源黑体 CN Medium 文泉驿微米黑
font.setFamily(QString::fromUtf8("微软雅黑"));
font.setPixelSize(App::MainFont);
qApp->setFont(font);
}
void AppInit::initDb()
{
}
void AppInit::initStyle()
{
QStringList list;
//去掉焦点虚边框
list.append(QString("*{outline:0px;color:%1;}").arg(App::ColorTitleText));
//按钮
list.append(QString("QPushButton{background-color:%1;color:%2;}").arg(App::ColorTitleBg).arg(App::ColorTitleText));
//提示信息
list.append(QString("QToolTip{border:0px solid #F0F0F0;background:%1;color:%2;}").arg(App::ColorTitleBg).arg(App::ColorTitleText));
//标题栏
list.append(QString("#widgetTitle,QLabel[flag=\"title\"]{background-color:%1;color:%2;}").arg(App::ColorTitleBg).arg(App::ColorTitleText));
list.append(QString("#widgetTitle>QPushButton{border:none;}"));
//二级窗口标题栏字体放大
list.append(QString("#labTitle{font:%1px;min-height:%2px;}QLabel{border:none;padding:5px;}").arg(App::TitleFont).arg(App::TitleHeight));
//显示特殊标签
list.append(QString("QWidget[flag=\"lab\"]{background-color:%1;}").arg(App::ColorChartBg));
list.append(QString("QWidget[flag=\"lab\"]>QLabel{font:%1px;}").arg(App::LabFont));
list.append(QString("QWidget[flag=\"sub\"]{background-color:%1;}").arg(App::ColorChartBg));
list.append(QString("QWidget[flag=\"sub\"]>QLabel{font:%1px;}").arg(App::SubTitleFont));
list.append(QString("QWidget[flag=\"device\"]>QLabel{font:%1px;}").arg(App::DeviceFont));
//二级窗口背景
list.append(QString("#widgetMain{background-color:%1;}").arg(App::ColorPanelBg));
//中间窗口背景
list.append(QString("#widgetCenter{border-image:url(%1);}").arg(":/image/bg_center.png"));
list.append(QString("#labMap{border-image:url(%1);}").arg(":/image/bg_china.png"));
//中间标题
list.append(QString("#labName{font-size:%1px;font-weight:bold;color:%2;}").arg(App::NameFont).arg("#05B6FA"));
//设备监控背景
list.append(QString("#widgetDevice{background-color:%1;}").arg(App::ColorChartBg));
//数码管
list.append(QString("QLCDNumber{background-color:%1;border:none;}").arg(App::ColorChartBg));
//表格样式
list.append(QString("QTableView{background-color:%1;gridline-color:%2;border:1px solid %2;}").arg(App::ColorChartBg).arg(App::ColorTitleBg));
list.append(QString("QTableView::item:selected{color:#FFFFFF;background:%1;}").arg("rgba(255,255,255,50)"));
list.append(QString("QTableView::item:hover{color:#FFFFFF;background:%1;}").arg("rgba(255,255,255,50)"));
//表格头部样式,所有子界面共用
list.append(QString("QHeaderView::section,QTableCornerButton:section{background-color:%1;color:%2;border:1px solid %3;font-weight:bold;font-size:%4px;}")
.arg(App::ColorChartBg).arg(App::ColorOk).arg(App::ColorTitleBg).arg(App::MainFont + 2));
//进度条颜色
list.append(QString("QProgressBar{background:%1;text-align:center;border:1px solid %2;}").arg(App::ColorChartBg).arg(App::ColorChartText));
list.append(QString("QProgressBar:chunk{background-color:%1;}").arg(App::ColorOk));
//自定义控件颜色
list.append(QString("ProgressRing{qproperty-bgColor:%1;qproperty-textColor:%2;qproperty-ringColor:%3;qproperty-circleColor:%4;qproperty-ringColor1:%5;qproperty-ringColor2:%6;qproperty-ringColor3:%7;}")
.arg(App::ColorChartText).arg(App::ColorChartText).arg(App::ColorOk).arg(App::ColorChartBg).arg(App::ColorAlarm).arg(App::ColorLow).arg(App::ColorOk));
list.append(QString("ProgressThree{qproperty-color1:%1;qproperty-color2:%2;qproperty-color3:%3;qproperty-bgColor:%4;qproperty-textColor:%5;qproperty-borderColor:%6;qproperty-borderWidth:%7;}")
.arg(App::ColorOk).arg(App::ColorLow).arg(App::ColorAlarm).arg(App::ColorPanelBg).arg(App::ColorChartText).arg(App::ColorChartText).arg(0));
list.append(QString("GaugePercent{qproperty-baseColor:%1;}").arg(App::ColorPercent));
list.append(QString("GaugeSpeed{qproperty-textColor:%1;}").arg(App::ColorChartText));
list.append(QString("CustomChart{qproperty-bgColor:%1;qproperty-textColor:%2;qproperty-gridColor:%3;qproperty-highColor:%4;}")
.arg(App::ColorChartBg).arg(App::ColorChartText).arg(App::ColorChartGrid).arg(App::ColorAlarm));
list.append(QString("CustomPlot{qproperty-bgColor:%1;qproperty-textColor:%2;qproperty-gridColor:%3;}")
.arg(App::ColorChartBg).arg(App::ColorChartText).arg(App::ColorChartGrid));
list.append(QString("CustomPlot{qproperty-lineColor:%1;qproperty-lineColor1:%2;qproperty-lineColor2:%3;qproperty-lineColor3:%4;}")
.arg(App::ColorLine).arg(App::ColorLine1).arg(App::ColorLine2).arg(App::ColorLine3));
qApp->setPalette(QPalette(App::ColorMainBg));
qApp->setStyleSheet(list.join(""));
}