QT-UE4三维可视化案例

QT-UE4三维可视化案例(建筑健康可视化监控)

标签(空格分隔): QT 、Socket 、UE4

//COPYRIGHT NOTICE
//Copyright (c) 2018, 四川xx科技有限公司  (版权声明)
//2018,xx科技 UE4组 Lp 修改
//All rights reserved.
//Copyright (c) 2018, 四川xx科技有限公司  (版权声明)
//2018,xx科技 UE4组 Lp 修改
//All rights reserved.

该项目为中铁客户端(QT部分),采用QT5.7X64编译,适用于windows server 2016及以上系统。该项目主要包括:数据可视化Socket通讯内嵌ue4可执行程序三大方面

一:数据可视化

数据可视化即采用图形图表等第三方库对采集的数据进行动态展示,可以非常直观的查看传感器采集到的数据。这部分主要采用了两大图形图标库:QT自带的库:QtCharts和第三方库:QCustomPlot。

1.1:QtCharts

QtCharts由于是qt自带的使用也是比较广泛的图形展示库,本项目中将它封装在statisticalwindow类中。我们在使用它时应该注意三点

①在.pro文件中添加:

QT       += charts;

②添加自己需要的头文件:

#include 
#include 
#include 
//根据需要自行添加
#include 
#include 
//根据需要自行添加

③在代码前声明命名空间:

using namespace QtCharts;

示例代码:

void StatisticalWindow::Creatpie_chart()
{
    //构建QPieSeries作为饼图为其添加3个切片QPieSlice数据源
    QPieSeries *pieSeries = new QPieSeries();
    //设置中心圆大小
    pieSeries->setHoleSize(0.35);
    //添加数据
    QPieSlice *slice1=pieSeries->append(QString::fromLocal8Bit("正常个数92个"), 40);
    slice1->setColor(QColor(0,226,255,150));//设置背景颜色
    slice1->setLabelColor(QColor(0,226,255,255));//标签颜色
    slice1->setBorderColor(QColor(255,58,93,90));//边框颜色
    slice1->setLabelVisible(true);//设置标签可见
    QPieSlice *slice2=pieSeries->append(QString::fromLocal8Bit("异常个数6个"), 6);
    slice2->setLabelColor(QColor(0,226,255,255));
    slice2->setColor(QColor(0,226,255,220));
    slice2->setBorderColor(QColor(255,58,93,90));//边框颜色
    slice2->setLabelVisible(true);
    QPieSlice *slice3 = pieSeries->append(QString::fromLocal8Bit("危险个数4个"), 4);
    //slice3->setExploded();//炸开
    slice3->setLabelVisible(true);
    slice3->setLabelColor(QColor(0,226,255,255));
    slice3->setBorderColor(QColor(255,58,93,90));//边框颜色
    slice3->setColor(QColor(255,58,93,230));
    QChart *pieChart = new QChart();
    pieChart->addSeries(pieSeries);  // 将 series 添加至图表
    pieChart->setTitle(QString::fromLocal8Bit("所有监测点数据统计"));
    pieChart->setTitleFont(QFont(QString::fromLocal8Bit("所有监测点数据统计"),11));//字体大小
    pieChart->setTitleBrush(QBrush(QColor(255,255,255,200)));
    //pieChart->setGeometry(0,400,400,400);
    pieChart->legend()->setAlignment(Qt::AlignBottom);
    //pieChart->setTheme(QChart::ChartThemeBrownSand);
    QString path1=QDir::currentPath()+"/imgs/1.png";//大表盘背景图
    QPixmap pixmap(path1);//设定图片
    ui->QchartviewPie_label->setPixmap(pixmap);
    pieChart->setBackgroundBrush(QBrush(QColor(255,255,255,0)));//设置背景透明
    //设置给控件显示(QchartviewPie是ui界面中拖入widget控件并将它提升为Qchartview类)
    ui->QchartviewPie->setRenderHint(QPainter::Antialiasing);
    pieChart->setSelected(true);
    ui->QchartviewPie->setChart(pieChart);
}
{
    //构建QPieSeries作为饼图为其添加3个切片QPieSlice数据源
    QPieSeries *pieSeries = new QPieSeries();
    //设置中心圆大小
    pieSeries->setHoleSize(0.35);
    //添加数据
    QPieSlice *slice1=pieSeries->append(QString::fromLocal8Bit("正常个数92个"), 40);
    slice1->setColor(QColor(0,226,255,150));//设置背景颜色
    slice1->setLabelColor(QColor(0,226,255,255));//标签颜色
    slice1->setBorderColor(QColor(255,58,93,90));//边框颜色
    slice1->setLabelVisible(true);//设置标签可见
    QPieSlice *slice2=pieSeries->append(QString::fromLocal8Bit("异常个数6个"), 6);
    slice2->setLabelColor(QColor(0,226,255,255));
    slice2->setColor(QColor(0,226,255,220));
    slice2->setBorderColor(QColor(255,58,93,90));//边框颜色
    slice2->setLabelVisible(true);
    QPieSlice *slice3 = pieSeries->append(QString::fromLocal8Bit("危险个数4个"), 4);
    //slice3->setExploded();//炸开
    slice3->setLabelVisible(true);
    slice3->setLabelColor(QColor(0,226,255,255));
    slice3->setBorderColor(QColor(255,58,93,90));//边框颜色
    slice3->setColor(QColor(255,58,93,230));
    QChart *pieChart = new QChart();
    pieChart->addSeries(pieSeries);  // 将 series 添加至图表
    pieChart->setTitle(QString::fromLocal8Bit("所有监测点数据统计"));
    pieChart->setTitleFont(QFont(QString::fromLocal8Bit("所有监测点数据统计"),11));//字体大小
    pieChart->setTitleBrush(QBrush(QColor(255,255,255,200)));
    //pieChart->setGeometry(0,400,400,400);
    pieChart->legend()->setAlignment(Qt::AlignBottom);
    //pieChart->setTheme(QChart::ChartThemeBrownSand);
    QString path1=QDir::currentPath()+"/imgs/1.png";//大表盘背景图
    QPixmap pixmap(path1);//设定图片
    ui->QchartviewPie_label->setPixmap(pixmap);
    pieChart->setBackgroundBrush(QBrush(QColor(255,255,255,0)));//设置背景透明
    //设置给控件显示(QchartviewPie是ui界面中拖入widget控件并将它提升为Qchartview类)
    ui->QchartviewPie->setRenderHint(QPainter::Antialiasing);
    pieChart->setSelected(true);
    ui->QchartviewPie->setChart(pieChart);
}

示例效果:

 

1.2:QCustomPlot

QCustomPlot是目前QT公认为比较好用的第三方图形展示库,库里就只有qcustomplot.h和qcustomplot.cpp两个主要文件。本项目主要封装于showonepoint类中,以及mainwindow类也有使用。使用各类需要注意:

①:将下载好的QCustomPlot压缩包解压后的qcustomplot.h和qcustomplot.cpp两个文件放到自己项目的.pro同级目录,然后打开项目-添加现有文件,分别将这两个文件添加进自己的项目中。

②:在.pro文件中添加:

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport

③:执行qmark

示例代码:

//该函数代码不完整,主要展示图表细节设置代码
void MainWindow::ShowAllType()
{
    //三大类的折线展示图
    ui->AllTypeshow->addGraph();//添加线条
    ......
    //设置线条
    ui->AllTypeshow->graph(0)->setName(QString::fromLocal8Bit("风速平均值"));
    ui->AllTypeshow->graph(0)->setPen(QPen(QColor(0,226,255,180)));//风速线颜色
    ui->AllTypeshow->setBackground(QBrush(QColor(27, 27, 27,255)));//背景色
    //设置坐标轴名称
    //ui->AllTypeshow->yAxis->setSelectedTickLabelColor(QColor(0,226, 255,255));//设置单击选中后的坐标颜色
    ui->AllTypeshow->xAxis->setLabel(QString::fromLocal8Bit("各类传感器实时数据"));//x标签
    ui->AllTypeshow->xAxis->setLabelColor(QColor(255,255, 255,200));//x标签颜色
    ui->AllTypeshow->xAxis->setTickLabelColor(QColor(0,226, 255,255));//x的数据颜色
    ui->AllTypeshow->xAxis->setBasePen(QPen(QColor(0,226, 255,255)));//x轴基础线颜色
    ui->AllTypeshow->xAxis->setSubTickPen(QPen(QColor(0,226, 255,255)));//x轴小刻度颜色
    ui->AllTypeshow->yAxis->setLabelColor(QColor(255,255, 255,200));//Y标签
    ui->AllTypeshow->yAxis->setTickLabelColor(QColor(0,226, 255,255));
    ui->AllTypeshow->yAxis->setLabel(QString::fromLocal8Bit("实时平均值"));//y标签
    ui->AllTypeshow->yAxis->setBasePen(QPen(QColor(0,226, 255,255)));
    ui->AllTypeshow->yAxis->setSubTickPen(QPen(QColor(0,226, 255,255)));
    ui->AllTypeshow->xAxis->grid()->setPen(QPen(QColor(0,226, 255,100)));//x栅格颜色
    QPen qcustomx_grid_pen;//x轴网格线风格
    qcustomx_grid_pen.setColor(QColor(0,226, 255,100));
    qcustomx_grid_pen.setStyle(Qt::DotLine);
    ui->AllTypeshow->xAxis->grid()->setPen(qcustomx_grid_pen);
    QPen qcustomy_grid_pen;//y轴网格线风格
    qcustomy_grid_pen.setColor(QColor(0,226, 255,100));
    qcustomy_grid_pen.setStyle(Qt::DotLine);
    ui->AllTypeshow->yAxis->grid()->setPen(qcustomy_grid_pen);
    ui->AllTypeshow->xAxis-> setTicks(true); //不显示坐标轴
    ui->AllTypeshow->xAxis->setRange(0, 30);
    ui->AllTypeshow->yAxis->setRange(1, 80);
    //启用拖拽事件等
    ui->AllTypeshow->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
                                     QCP::iSelectLegend | QCP::iSelectPlottables);
    ui->AllTypeshow->legend->setBrush(QBrush(QColor(0,226,255,100)));
    ui->AllTypeshow->legend->setVisible(true);//设置图表的标注可见
    //添加数据,这里演示y=30-35浮动数据
   for (int i = 0; i<30; i++)
   {
       X_WD.append(i);
      // Y_WD.append(qrand()%3+30);//温度数据取值在30-33浮动
       Y_FS.append(qrand()%8+3);//风速在3-11浮动(单位:m/s)
       Y_ZD.append(qrand()%10+50);//震动在50-60浮动(单位%)
       Y_YL.append(qrand()%10+15);//应力在15-25浮动单位用kgf/mm²
       Y_JS.append(qrand()%10+30);
   }
   //给三大类实时数据设置数据
   ui->AllTypeshow->graph(0)->setData(X_WD, Y_FS);
   ui->AllTypeshow->graph(1)->setData(X_WD, Y_ZD);//震动
   ui->AllTypeshow->graph(2)->setData(X_WD, Y_YL);
   ui->AllTypeshow->graph(3)->setData(X_WD, Y_JS);
}
void MainWindow::ShowAllType()
{
    //三大类的折线展示图
    ui->AllTypeshow->addGraph();//添加线条
    ......
    //设置线条
    ui->AllTypeshow->graph(0)->setName(QString::fromLocal8Bit("风速平均值"));
    ui->AllTypeshow->graph(0)->setPen(QPen(QColor(0,226,255,180)));//风速线颜色
    ui->AllTypeshow->setBackground(QBrush(QColor(27, 27, 27,255)));//背景色
    //设置坐标轴名称
    //ui->AllTypeshow->yAxis->setSelectedTickLabelColor(QColor(0,226, 255,255));//设置单击选中后的坐标颜色
    ui->AllTypeshow->xAxis->setLabel(QString::fromLocal8Bit("各类传感器实时数据"));//x标签
    ui->AllTypeshow->xAxis->setLabelColor(QColor(255,255, 255,200));//x标签颜色
    ui->AllTypeshow->xAxis->setTickLabelColor(QColor(0,226, 255,255));//x的数据颜色
    ui->AllTypeshow->xAxis->setBasePen(QPen(QColor(0,226, 255,255)));//x轴基础线颜色
    ui->AllTypeshow->xAxis->setSubTickPen(QPen(QColor(0,226, 255,255)));//x轴小刻度颜色
    ui->AllTypeshow->yAxis->setLabelColor(QColor(255,255, 255,200));//Y标签
    ui->AllTypeshow->yAxis->setTickLabelColor(QColor(0,226, 255,255));
    ui->AllTypeshow->yAxis->setLabel(QString::fromLocal8Bit("实时平均值"));//y标签
    ui->AllTypeshow->yAxis->setBasePen(QPen(QColor(0,226, 255,255)));
    ui->AllTypeshow->yAxis->setSubTickPen(QPen(QColor(0,226, 255,255)));
    ui->AllTypeshow->xAxis->grid()->setPen(QPen(QColor(0,226, 255,100)));//x栅格颜色
    QPen qcustomx_grid_pen;//x轴网格线风格
    qcustomx_grid_pen.setColor(QColor(0,226, 255,100));
    qcustomx_grid_pen.setStyle(Qt::DotLine);
    ui->AllTypeshow->xAxis->grid()->setPen(qcustomx_grid_pen);
    QPen qcustomy_grid_pen;//y轴网格线风格
    qcustomy_grid_pen.setColor(QColor(0,226, 255,100));
    qcustomy_grid_pen.setStyle(Qt::DotLine);
    ui->AllTypeshow->yAxis->grid()->setPen(qcustomy_grid_pen);
    ui->AllTypeshow->xAxis-> setTicks(true); //不显示坐标轴
    ui->AllTypeshow->xAxis->setRange(0, 30);
    ui->AllTypeshow->yAxis->setRange(1, 80);
    //启用拖拽事件等
    ui->AllTypeshow->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
                                     QCP::iSelectLegend | QCP::iSelectPlottables);
    ui->AllTypeshow->legend->setBrush(QBrush(QColor(0,226,255,100)));
    ui->AllTypeshow->legend->setVisible(true);//设置图表的标注可见
    //添加数据,这里演示y=30-35浮动数据
   for (int i = 0; i<30; i++)
   {
       X_WD.append(i);
      // Y_WD.append(qrand()%3+30);//温度数据取值在30-33浮动
       Y_FS.append(qrand()%8+3);//风速在3-11浮动(单位:m/s)
       Y_ZD.append(qrand()%10+50);//震动在50-60浮动(单位%)
       Y_YL.append(qrand()%10+15);//应力在15-25浮动单位用kgf/mm²
       Y_JS.append(qrand()%10+30);
   }
   //给三大类实时数据设置数据
   ui->AllTypeshow->graph(0)->setData(X_WD, Y_FS);
   ui->AllTypeshow->graph(1)->setData(X_WD, Y_ZD);//震动
   ui->AllTypeshow->graph(2)->setData(X_WD, Y_YL);
   ui->AllTypeshow->graph(3)->setData(X_WD, Y_JS);
}

示例效果:

QT-UE4三维可视化案例_第1张图片

 

二:Socket通讯

QT部分的通讯主要涉及到和服务端后台通讯以及ue4程序间的通讯,均采用socket通讯来完成:

2.1:服务端通讯

服务端通讯:主要 是获取传感器数据,通过不停地向服务端发送命令以获取各个传感器的状态以及数据等,解析或计算后用于实施呈现在图形图表之中。

示例代码:

暂无:

2.2:ue4程序通讯

内嵌ue4程序通讯:主要是将qt作为服务端,在启动qt时初始化QTcpServer进行监听,然后启动外部ue4程序等待其连接。一ue4发消息qt接消息,qt接收消息并解析后执行响应操作。②qt发ue4程序接:qt不停发送消息以便ue4不间断更新传感器状态等。关于QT中使用socket:

①在.pro中添加、在头文件添加

QT       += network
#include 
#include 
#include 
#include 

②初始化监听、新连接、接收消息

//初始化socket进行监听,等待连接
void MainWindow::SocketListen()
{
     server = new QTcpServer();
     server->listen(QHostAddress::Any, Port);//监听端口Port(#define Port 9537)
     connect(server, SIGNAL(newConnection()), this, SLOT(SocketConnect()));//当有一个新连接过来,  执行socketcontent
}
//新的Socket连接
void MainWindow::SocketConnect()
{
    //初始化thissocket,得到这个连接
    thissocket = server->nextPendingConnection();
    if(thissocket)
    {
        connect(thissocket, SIGNAL(readyRead()), this, SLOT(SocketRecv())); //当接受到消息
    }  
}
//接受解析socket消息
void MainWindow::SocketRecv()
{
    if(thissocket->isValid())
    {
        QByteArray arr=thissocket->readAll();//读取消息
        QString data = arr;//QString::fromLocal8Bit(arr);将接收得到的unicode字符转为自己的utf8字符集,如果发送的已经转了那就直接接收
        if(!data.isEmpty())
        {
            Execute_sockecommand(data);//根据命令执行操作响应
        }
    }  
}
void MainWindow::SocketListen()
{
     server = new QTcpServer();
     server->listen(QHostAddress::Any, Port);//监听端口Port(#define Port 9537)
     connect(server, SIGNAL(newConnection()), this, SLOT(SocketConnect()));//当有一个新连接过来,  执行socketcontent
}
//新的Socket连接
void MainWindow::SocketConnect()
{
    //初始化thissocket,得到这个连接
    thissocket = server->nextPendingConnection();
    if(thissocket)
    {
        connect(thissocket, SIGNAL(readyRead()), this, SLOT(SocketRecv())); //当接受到消息
    }  
}
//接受解析socket消息
void MainWindow::SocketRecv()
{
    if(thissocket->isValid())
    {
        QByteArray arr=thissocket->readAll();//读取消息
        QString data = arr;//QString::fromLocal8Bit(arr);将接收得到的unicode字符转为自己的utf8字符集,如果发送的已经转了那就直接接收
        if(!data.isEmpty())
        {
            Execute_sockecommand(data);//根据命令执行操作响应
        }
    }  
}

三:内嵌ue4可执行程序

该部分主要是将外部程序嵌入qt程序中,作为其一个子窗口进行展示。只要是通过qt启动外部程序,然后利用windows函数FindWindow()获得ue4窗口句柄handle,然后就是对这个handle的操作。

目前这个嵌入ue4exe的地方有点问题:一般做法是利用一个QWindow 来作为这个handle的代理,再利用QWidget在显示这个QWindow 已达到QT嵌入外部exe。实际上这种方法对绝大多数应用程序来说都比较实用,但是对于ue4来说却存在焦点问题!尝试许久无果后,无奈之举只能直接对handle进行移动缩放让其跟随qt窗口进行运动。

①移动ue4exe窗口

MoveWindow(hwnWindow,startpoint.x(),startpoint.y(),1041,540,1);

②关闭时自身时结束ue4exe。(结束本应该写在~mainwindow()里面,这里直接截取QCloseEvent事件进行处理)

//关闭操作响应
void MainWindow::closeEvent(QCloseEvent *event)
{
    switch( QMessageBox::information(this,QString::fromLocal8Bit("提示"),QString::fromLocal8Bit("你确定退出该软件?"),QString::fromLocal8Bit("确定"),QString::fromLocal8Bit("取消"),0,1))
    {
    case 0:
        {
        QString exename="UE4Game.exe";
        exename="sensor.exe";
        terminateMyexe(exename);//查找并结束exe
        delete mypie;
        break;
        event->accept();//接受关闭消息
        }
    case 1:
    default:
        event->ignore();//忽略
        break;
    }
}
void MainWindow::closeEvent(QCloseEvent *event)
{
    switch( QMessageBox::information(this,QString::fromLocal8Bit("提示"),QString::fromLocal8Bit("你确定退出该软件?"),QString::fromLocal8Bit("确定"),QString::fromLocal8Bit("取消"),0,1))
    {
    case 0:
        {
        QString exename="UE4Game.exe";
        exename="sensor.exe";
        terminateMyexe(exename);//查找并结束exe
        delete mypie;
        break;
        event->accept();//接受关闭消息
        }
    case 1:
    default:
        event->ignore();//忽略
        break;
    }
}

整体效果:

该版本为为了解决ue4焦点问题而新写的第二版本,经测试比较稳定,没有出现其他问题。

 

你可能感兴趣的:(QT,ue4,c++,可视化,socket,QT,UE4,智慧建筑)