关于Qt嵌入浏览器(一)

在学习qt的过程中发现需要运用到浏览器页面来引入ECharts图表,使自己的qt界面变得更好看,但是在嵌入浏览器的过程中出现了很多问题,首先qt自带的QWebEngineView需要在MSVC编译器才能使用,但是这个编译器我一般不用,因为会有字符错误,但是在MinGW编译器下又会报错,没有QWebEngineView这个库,于是上网查资料,终于有一个简单的方法,就是引入外部库miniblink,能在MinGw编译器下成功运行,接下来是具体的方法:

首先先去github上下载miniblink的sdk文件,具体可以看这篇文章添加链接描述

找到wek.h和node.dll,但是我看了一下最新的没找到这个文件,于是我又看了另一篇文章添加链接描述,我只要三个文件就好了,我就直接上传一下,注意注意,得把miniblink.dll、miniblink_64.dll 这两个文件放到可执行文件目录下,如图

在这里插入图片描述

不知道为什么我这里上传资源居然不是免费,如有需要,可私信,评论,免费提供!!!或者后面我上传网盘,直接取!

具体可以参考我前面提到的文章,它有一个封装的miniblink库,可以直接用,按照它的工程结构图
在这里插入图片描述
我这里就写一下我的事例
miniblink.pro文件

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

DEFINES += QT_DEPRECATED_WARNINGS



INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/miniblink


include ($$PWD/miniblink/miniblink.pri)




SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui



miniblink.pri文件


HEADERS += \
    $$PWD/miniblink.h \
    $$PWD/wke.h

SOURCES += \
    $$PWD/miniblink.cpp


miniblink.h文件

#ifndef MINIBLINK_H
#define MINIBLINK_H

#include <QWidget>
#include "wke.h"

class miniblink : public QWidget
{
    Q_OBJECT
public:
    explicit miniblink(QWidget *parent = 0);

    //初始化资源
    static void init();
    //释放资源
    static void release();

protected:
    //设置浏览器控件自动适应大小
    void resizeEvent(QResizeEvent *);

private:
    //浏览器控件对象
    wkeWebView webView;

signals:
    //网页载入完成
    void loadFinished(bool ok);
    //收到网页发出来的数据
    void receiveDataFromJs(const QString &type, const QVariant &data);

public:
    //给回调用的函数
    void loadFinish(bool ok);
    void receiveData(const QString &type, const QVariant &data);

public slots:
    //加载网址或者本地文件
    void load(const QString &url, bool file = false);
    //加载html内容
    void setHtml(const QString &html, const QString &baseUrl);
    //执行js函数
    void runJs(const QString &js);
};

#endif // MINIBLINK_H

wek.h在上传的资源包里

miniblink.cpp文件

#pragma execution_character_set("utf-8")
#include "miniblink.h"
#include "qapplication.h"
#include "qmessagebox.h"
#include "qdatetime.h"
#include "qfile.h"
#include "qvariant.h"
#include "qdebug.h"

#define TIMEMS QTime::currentTime().toString("hh:mm:ss zzz")
void onLoadingFinish(wkeWebView, void *param, const wkeString, wkeLoadingResult result, const wkeString)
{
    //qDebug() << "onLoadingFinish" << result;
    //在注册函数的地方就已经传入了类指针
    miniblink *widget = (miniblink *)param;
    //0 = WKE_LOADING_SUCCEEDED, 1 = WKE_LOADING_FAILED, 2 = WKE_LOADING_CANCELED
    widget->loadFinish(result == 0);
}

jsValue WKE_CALL_TYPE objName_receiveData(jsExecState es, void *param)
{
    if (0 == jsArgCount(es)) {
        return jsUndefined();
    }

    //挨个取出参数,设定的通用方法,只有两个参数
    jsValue arg0 = jsArg(es, 0);
    jsValue arg1 = jsArg(es, 1);
    if (!jsIsString(arg0)) {
        return jsUndefined();
    }

    //在注册函数的地方就已经传入了类指针
    miniblink *widget = (miniblink *)param;
    QString type = QString::fromStdString(jsToString(es, arg0));
    QVariant data = QString::fromStdString(jsToString(es, arg1));
    widget->receiveData(type, data);
    return jsUndefined();
}

miniblink::miniblink(QWidget *parent) : QWidget(parent)
{
    //第一步先初始化动态库
    init();
    //第二步初始化浏览器控件
    //创建一个浏览器控件,放入句柄
    webView = wkeCreateWebWindow(WKE_WINDOW_TYPE_CONTROL, (HWND)this->winId(), 0, 0, this->width(), this->height());
    //关联完成信号
    wkeOnLoadingFinish(webView, onLoadingFinish, this);
    //设置浏览器控件可见
    wkeShowWindow(webView, TRUE);
    //注册通用的接收数据的方法,一定要放在这里在网页加载前执行
    wkeJsBindFunction("objName_receiveData", objName_receiveData, this, 2);
}

void miniblink::init()
{
    //全局只需要初始化一次
    static bool isInit = false;
    if (!isInit) {
        isInit = true;
        //不同的构建套件位数加载不同的动态库
#ifdef Q_OS_WIN64
        QString flag = "64";
        QString file = qApp->applicationDirPath() + "/miniblink_64.dll";
#else
        QString flag = "32";
        QString file = qApp->applicationDirPath() + "/miniblink.dll";
#endif
        //如果文件不存在则提示
        if (!QFile(file).exists()) {
            QMessageBox::critical(0, "错误", file + "\n文件不存在请先拷贝!");
            return;
        }

        const wchar_t *path = reinterpret_cast<const wchar_t *>(file.utf16());
        wkeSetWkeDllPath(path);
        bool ok = wkeInitialize();
        qDebug() << TIMEMS << QString("init miniblink_%1 %2").arg(flag).arg(ok ? "ok" : "error");
    }
}

void miniblink::release()
{
    wkeFinalize();
}

void miniblink::resizeEvent(QResizeEvent *)
{
    wkeResize(webView, this->width(), this->height());
}

void miniblink::loadFinish(bool ok)
{
    emit loadFinished(ok);
}

void miniblink::receiveData(const QString &type, const QVariant &data)
{
    emit receiveDataFromJs(type, data);
}

void miniblink::load(const QString &url, bool file)
{
    QByteArray data = url.toUtf8();
    const char *temp = data.data();
    if (file) {
        wkeLoadFile(webView, temp);
    } else {
        wkeLoadURL(webView, temp);
    }
}

void miniblink::setHtml(const QString &html, const QString &baseUrl)
{
    QByteArray dataHtml = html.toUtf8();
    QByteArray dataUrl = baseUrl.toUtf8();
    wkeLoadHtmlWithBaseUrl(webView, dataHtml.data(), dataUrl.data());
}

void miniblink::runJs(const QString &js)
{
    QByteArray data = js.toUtf8();
    wkeRunJS(webView, data.data());
}

widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "miniblink.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
    miniblink *webView;

private slots:
    void initForm();
    //网页载入完成
    void loadFinished(bool ok);
    //收到网页发出来的数据
    void receiveDataFromJs(const QString &type, const QVariant &data);

private slots:
    void on_btnLoadUrl_clicked();
    void on_btnLoadFile_clicked();
    void on_btnLoadHtml_clicked();
    void on_btnRunJs_clicked();
    void on_horizontalSlider_valueChanged(int value);
};

#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include "qapplication.h"
#include "qdebug.h"

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

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

void Widget::initForm()
{
    webView = new miniblink;
    connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
    connect(webView, SIGNAL(receiveDataFromJs(QString, QVariant)),
            this, SLOT(receiveDataFromJs(QString, QVariant)));
    ui->gridLayout->addWidget(webView, 0, 0);
}

void Widget::loadFinished(bool ok)
{
    qDebug() << "加载完成" << ok;
}

void Widget::receiveDataFromJs(const QString &type, const QVariant &data)
{
    qDebug() << "收到数据" << type << data;
}

void Widget::on_btnLoadUrl_clicked()
{
    webView->load("https://www.baidu.com");
}

void Widget::on_btnLoadFile_clicked()
{
    webView->load(qApp->applicationDirPath() + "/demo01.html", true);
    qDebug() << "Loading file from:" << qApp->applicationDirPath() + "/demo01.html";

}

void Widget::on_btnLoadHtml_clicked()
{
    QStringList html;
    html << "<html><body>";
    html << "<h2>Hello World</h2>";
    html << "</body></html>";
    webView->setHtml(html.join(""), "");
}

void Widget::on_btnRunJs_clicked()
{
    webView->load(qApp->applicationDirPath() + "/gauge.html", true);
}

void Widget::on_horizontalSlider_valueChanged(int value)
{
    QString js = QString("setGaugeValue(%1)").arg(value);
    webView->runJs(js);
}

注意注意,这里的demo01.html文件需要自己创建,并把它放在前面的可执行文件目录下,我的demo01.html文件是这样的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- 这里要引入echarts的js -->
    <script src="echarts.min.js"></script> 
</head>
<body>

    <!--Step:1 为ECharts准备一个具备大小(宽高)的Dom-->

<div id="main" style="height:400px;width: 700px;padding:10px;">
</div>
<script type="text/javascript">
	
	
    
       //实例化
       var myChart = echarts.init(document.getElementById('main'));

       
       //指定配置,从echarts下载的代码放在这里就可以了

     var   option = {
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [150, 230, 224, 218, 135, 147, 260],
      type: 'line'
    }
  ]
};



       // 调用
       myChart.setOption(option);
   
   
   
   
      
   </script>
</body>
</html>

其中用到的echarts.min.js文件也要引入(这个文件我同样放在后面的资源包里,也可以自行去官网下载)添加链接描述,同样是放在可执行目录文件下,不然后面图表不会显示。

最后可执行目录文件是这样的
在这里插入图片描述

最后是widget.ui界面
在这里插入图片描述

最后在qt运行,就能嵌入echarts图表了
在这里插入图片描述

最后总结,echarts里面还有很多很好看的图,不只是图表,还有地图,后面会写怎么嵌入地图,但是minblink也有一个弊端,就是它只能嵌入一个浏览器界面,多个好像就不行了,不能通信,目前还没有解决,但是还有另外一个方法就是,在linux系统下运行,它就只有一个编译器,就可以不用miniblink库,直接用它自带的QWebEngineView,可以嵌入多个浏览器界面进行通信,后面如果有时间会出详细教程。

QCEFView是基于Qt和Chromium Embedded Framework(CEF)的浏览器控件。它可以在Qt应用程序中嵌入个完整的浏览器窗口,允许用户浏览网页、执行JavaScript代码等。 QCEFView的优势之是它能够提供高性能的网页渲染和JavaScript执行。由于基于CEF,它可以利用Chromium引擎的功能和优化,提供流畅的浏览体验。 另个优点是QCEFView的灵活性。它可以与Qt的图形界面框架完美集成,允许开发者根据自己的需求自定义浏览器窗口的外观和行为。开发者可以通过信号和槽机制与QCEFView进行交互,实现诸如加载URL、执行JavaScript代码、获取网页的标题和内容等操作。 同时,QCEFView还可以集成其他Qt组件和功能。例如,可以将QCEFView与Qt的网络模块结合使用,实现浏览器的网络功能;也可以与Qt的文件系统模块结合使用,实现浏览器的文件操作功能等。 当然,使用QCEFView也存在些注意事项。首先,QCEFView的集成可能会增加应用程序的大小和内存占用,因为Chromium引擎是个相对庞大的库。其次,由于CEF是基于多进程架构的,QCEFView在使用时需要注意处理进程间通信的问题。 总的来说,QCEFView是个强大且灵活的Qt嵌入浏览器控件,能够为开发者提供良好的浏览体验和自定义能力。无论是用于开发嵌入浏览器应用程序还是添加浏览器功能到现有Qt应用程序中,QCEFView都是个不错的选择。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值