Qt调用Echarts显示动态过程曲线

Qt调用Echarts显示动态过程曲线


效果

先来看看效果吧。

Qt生成随机数发送给Echarts,1000ms刷新一次

G3IF.gif

环境

具体配置见我的另外一篇最清晰Qt与JS通过qwebchannel交互例子

备注:
1.HTML端就是最基本的HTML、JS,没有更高层的
2.基础知识:Echarts相关基本知识

HTML端代码Echarts

在上一篇文章HTML目类下新建一个echarttest.html文件,修改Echarts例子给出的部分HTML代码,然后Qt调用这个页面

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8">
    <!-- 引入 ECharts 文件 -->
    <script src="D:/Code/JS/Echart/echarts.min.js"></script>
    <script src="qwebchannel.js"></script>

</head>
<p id="xlabel">x:</p>
<p id="ylabel">y:</p>

<body>
    <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
    <div id="main" class="chart" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
        //自适应宽高
        var resizeContainer = function () {
            var myChart = document.getElementById('main');
            myChart.style.width = window.innerWidth - 32 + 'px'; //
            myChart.style.height = window.innerHeight - 100 + 'px'; //适应Qt内嵌边框
        };

        resizeContainer();
        var myChart = echarts.init(document.getElementById('main'));
        // 指定图表的配置项和数据
        var option = {
            title: {
                text: 'Qt实时传输数据调用ECharts示例',
                left: '40%'
            },
            grid: {
                left: '5%',
                right: '3%',
                top: '10%',
                bottom: '8%'
            },
            tooltip: {
                trigger: 'axis'
            },
            legend: {
                data: ['值'],
                right: '10%',
                top: '5%'
            },
            xAxis: {

                data: []
            },
            yAxis: {},
            series: [{
                name: '值',
                type: 'line',
                data: []
            }]
        };
        myChart.setOption(option);
        //自适应窗口大小
        window.onresize = function () {
            resizeContainer();
            myChart.resize();
        };
        //接受从Qt来的数据
        var x = [];
        var y = [];
        new QWebChannel(qt.webChannelTransport, function (channel) {
            var webobj = channel.objects.webobj;
            //arg-QJsonObject类型
            webobj.dataChanged.connect(function (arg) {
                xlabel.innerHTML = "x:" + arg.x;
                ylabel.innerHTML = "y:" + arg.y.toFixed(4);
                x.push(arg.x);
                y.push(arg.y.toFixed(4));

                myChart.setOption({
                    xAxis: {
                        data: x
                    },
                    series: [{
                        name: '值',
                        data: y
                    }]
                });
            });

        });
    </script>

</body>

</html>

Qt端修改代码
.h文件

class WebClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QJsonObject jsonData MEMBER m_jsonData NOTIFY dataChanged)

public:
signals:

    void dataChanged(const QJsonObject &jsonData);
private:

    QJsonObject m_jsonData;
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    QWebEngineView *webView = nullptr;
    QWebChannel *webChannel = nullptr;
    WebClass *webobj = nullptr;
    QPushButton *btn = nullptr;
    QTimer *timer = nullptr;
    QJsonObject json;
};

.cpp文件

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    btn = new QPushButton("..");
    connect(btn, &QPushButton::clicked, this,
            [&]()
    {
        timer = new QTimer;
        connect(timer, &QTimer::timeout, this,
                [&]()
        {
            static int index = 0;
            json["x"] = index++;
            //生成随机数
            json["y"] = QRandomGenerator::global()->generateDouble() * 10;
            webobj->setProperty("jsonData", json);
        });
        timer->start(1000);
    });
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(btn, 1, Qt::AlignLeft);

    webView = new QWebEngineView(parent);
    webView->load(QUrl::fromLocalFile("D:\\Code\\JS\\test.html"));
    layout->addWidget(webView);
    QWidget *w = new QWidget;
    w->setLayout(layout);

    setCentralWidget(w);

    webChannel = new QWebChannel;
    webobj = new WebClass();
    webChannel->registerObject("webobj", webobj);
    webView->page()->setWebChannel(webChannel);

    setMinimumSize(800, 600);
}

x坐标是时间类型

上一个例子还是横坐标还是普通数据,如果是时间型的呢?这会涉及到QString和Json日期换算的问题,稍微花点时间完成了,顺便将几个类简单封装了下,另外Echarts里的一个重要特性加上了,仍然是Qt生成随机数实时发送给JS。效果如下
1.gif
具体代码如下:
HTML端

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8">
    <!-- 引入 ECharts 文件 -->
    <script src="echarts.min.js"></script>
    <script src="qwebchannel.js"></script>

</head>
<table width="300" border="0">
    <tr>
        <td id="xlabel">x:</td>
        <td id="ylabel">y:</td>
        <td id="zlabel">z:</td>
    </tr>
</table>

<body>
    <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
    <div id="main" class="chart" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
        //自适应宽高
        var resizeContainer = function () {
            var myChart = document.getElementById('main');
            myChart.style.width = window.innerWidth - 20 + 'px'; //
            myChart.style.height = window.innerHeight - 50 + 'px'; //适应Qt内嵌边框
        };
        //字符串转日期 yyyy-MM-dd hh:mm:ss
        function str2Datetime(strDateTime) {
            var tempStrs = strDateTime.split(" ");
            var dateStrs = tempStrs[0].split("-");
            var year = parseInt(dateStrs[0], 10);
            var month = parseInt(dateStrs[1], 10) - 1;
            var day = parseInt(dateStrs[2], 10);
            var timeStrs = tempStrs[1].split(":");
            var hour = parseInt(timeStrs[0], 10);
            var minute = parseInt(timeStrs[1], 10);
            var second = parseInt(timeStrs[2], 10);
            var datetime = new Date(year, month, day, hour, minute, second);
            return datetime;
        }
        resizeContainer();
        var myChart = echarts.init(document.getElementById('main'), 'light');
        // 指定图表的配置项和数据
        var option = {
            title: {
                text: 'Qt实时传输数据调用ECharts示例',
                left: 'center'
            },
            grid: {
                left: '5%',
                right: '8%',
                top: '10%',
                bottom: '12%',
                show: false
            },
            toolbox: {
                right: '13%',
                feature: {
                    dataZoom: {
                        yAxisIndex: 'none'
                    },
                    restore: {}
                }
            },
            tooltip: {
                trigger: 'axis',
                axisPointer: {
                    type: 'cross'
                }
            },
            legend: {
                data: ['流量', '降雨量'],
                left: '10%',
                top: '5%'
            },
            xAxis: {
                axisTick: {
                    alignWithLabel: true
                },
                data: []
            },
            yAxis: [{
                    name: '流量(m^3/h)',
                    type: 'value',
                    axisLine: {
                        lineStyle: {
                            color: '#333',
                            width: 2
                        }
                    },
                    axisPointer: {
                        show: false
                    }
                },
                {
                    name: '降雨量(mm)',
                    nameLocation: 'start',
                    type: 'value',
                    axisLine: {
                        lineStyle: {
                            color: '#aaa',
                            width: 2
                        }
                    },
                    inverse: true,
                    axisPointer: {
                        show: false
                    }
                }
            ],
            dataZoom: [{
                    type: 'slider',
                    show: true,
                    xAxisIndex: [0],
                    start: 0,
                    end: 100,
                    bottom: 3
                },
                {
                    type: 'inside',
                    show: true,
                    xAxisIndex: [0],
                    start: 0,
                    end: 100
                }
            ],
            series: [{
                    name: '流量',
                    type: 'line',
                    data: []
                },
                {
                    name: '降雨量',
                    yAxisIndex: 1,
                    type: 'bar',
                    data: []
                }
            ]
        };
        myChart.setOption(option);
        //自适应窗口大小
        window.onresize = function () {
            resizeContainer();
            myChart.resize();
        };
        //接受从Qt来的数据
        var x = [];
        var y = [];
        var z = [];
        new QWebChannel(qt.webChannelTransport, function (channel) {
            var jsondata = channel.objects.eChartdata;
            //arg-QJsonObject类型
            jsondata.dataChanged.connect(function (arg) {
                xlabel.innerHTML = "time:" + arg.x;
                ylabel.innerHTML = "y:" + arg.y.toFixed(4);
                zlabel.innerHTML = "z:" + arg.z.toFixed(4);
                var date =  str2Datetime(arg.x);
                var hour = date.getHours();
                var min = date.getMinutes();
                var sec = date.getSeconds();
                x.push(hour + ':' + min + ':' + sec);
                y.push(arg.y.toFixed(4));
                z.push(arg.z.toFixed(4));
                myChart.setOption({
                    xAxis: {
                        data: x
                    },
                    series: [{
                            name: '流量',
                            data: y
                        },
                        {
                            name: '降雨量',
                            data: z
                        }
                    ]
                });
            });
        });
    </script>
</body>
</html>

Qt端

class EchartDataClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QJsonObject jsonData MEMBER m_jsonData NOTIFY dataChanged)

public:
signals:

    void dataChanged(const QJsonObject &jsonData);
private:
    QJsonObject m_jsonData;
};

class EchartWidget : public QWidget
{
    Q_OBJECT
public:
    EchartWidget(const QString &htmlPath, QWidget *parent = nullptr) : QWidget(parent)
    {
        QVBoxLayout *layout = new  QVBoxLayout;
        webView = new QWebEngineView(parent);
        webView->load(QUrl::fromLocalFile(htmlPath));
        layout->addWidget(webView);

        webChannel = new QWebChannel;
        eChartdata = new EchartDataClass;
        webChannel->registerObject("eChartdata", eChartdata);
        webView->page()->setWebChannel(webChannel);
        setLayout(layout);
        layout->setMargin(0);

        setMinimumSize(800, 600);
    }

    void setData(QDateTime dt, double y, double z)
    {
        QJsonObject json;
        json["x"] = dt.toString("yyyy-MM-dd hh:mm:ss");
        json["y"] = y;
        json["z"] = z;

        eChartdata->setProperty("jsonData", json);
    }

    virtual ~EchartWidget()
    {
    }

private:
    QWebEngineView *webView = nullptr;
    QWebChannel *webChannel = nullptr;
    EchartDataClass *eChartdata = nullptr;
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    QPushButton *btn = nullptr;
    QTimer *timer = nullptr;
    EchartWidget *echartWidget = nullptr;
};

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    btn = new QPushButton("start");
    connect(btn, &QPushButton::clicked, this,
            [&]()
    {
        if (btn->text() == "start")
        {
            btn->setText("stop");
            if (timer == nullptr)
            {
                timer = new QTimer;
                connect(timer, &QTimer::timeout, this,
                        [&]()
                {
                    echartWidget->setData(QDateTime::currentDateTime(),
                                          QRandomGenerator::global()->generateDouble() * 10,
                                          QRandomGenerator::global()->generateDouble());
                });
            }
            timer->start(1000);
        }
        else
        {
            btn->setText("start");
            timer->stop();
        }
    });
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->addWidget(btn, 1, Qt::AlignLeft);
    echartWidget
        = new EchartWidget("D:\\Code\\JS\\test.html");
    layout->addWidget(echartWidget);
    QWidget *w = new QWidget;
    w->setLayout(layout);
    setCentralWidget(w);
}

参考文献

最清晰Qt与JS通过qwebchannel交互例子
Qt WebChannel JavaScript API
echart官方例子

  • 10
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值