在学习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,可以嵌入多个浏览器界面进行通信,后面如果有时间会出详细教程。