QT之QWebEngineView

从webkit到webengine

自从Qt5.6后引入了QWebEngine,摒弃了原先的QWebkit,这是一款基于chrome浏览器内核引擎,Qt webenginewidgets模块中提供了QWebEngineView这个视图控件来很方便的加载和显示网页,仅需如下几行:

QWebEngineView* webview = new QWebEngineView;
webview->load(QUrl("https://www.baidu.com/"));
webview->show();

QWebEngineView跳转问题

这段代码很容易运行起来,但是别高兴早了,接下来你会发现点页面上的链接或者百度到其它页面时无法跳转,这是为什么呢?

因为我们只是一个浏览器引擎,不是像firefox、chrome那样的浏览器,浏览器已经提供了tab页去显示一个新的链接,所以这里我们需要自己决定如何去显示新打开的链接。

有两种方法可以实现
1、我们发现点击链接时时会收到urlChanged信号的,它附带的参数就是url地址,所以如果你想在本webview视图上显示这个页面就直接在绑定的槽函数里调用load(url)就ok了,如果你想实现向浏览器用另一tab来显示也是可以的,只需另外创建一个QWebEngineView,加载显示就好了,当然你也可以跳出一个对话框来显示,就想新打开一个浏览器窗口一样;

2、第二种方法就是重写createWindow方法,默认返回的是NULL,所以我们看到的效果是无法显示新的链接,因为你没有提供一个QWebEngineView给它嘛,在这个方法里有一个WebWindowType类型参数,

    enum WebWindowType {
        WebBrowserWindow,
        WebBrowserTab,
        WebDialog
    };

可以看到就是第一种方法中我们提到的三种显示,本浏览器窗口视图显示,另一tab页显示,跳出新的对话框显示,分别给你想实现的效果就好啦,简单而灵活。实际上js里面的window.open就会触发这个动作,调用到这个方法。

示例代码:

class HWebView : public QWebEngineView
{
     Q_OBJECT
public:
    HWebView::HWebView(QWidget *parent)
        : QWebEngineView(parent){
    }

protected:
    virtual QWebEngineView *createWindow(QWebEnginePage::WebWindowType type){
        HWebView* view = new HWebView;
        view->setAttribute(Qt::WA_DeleteOnClose);
        view->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
        return view;
    }
};

c++和JS交互

因为Qt自带的元对象模型Meta Object Model,信号与槽机制,使得c++和JS的交互异常简单而优雅,可以说比微软的com组件更加好用。
这里隆重登场的就是QWebChannel了,它使用了QWebSocket了,在C++端开了一个服务器端口,在JS客户端去连接这个端口,然后利用qt的元对象模式,信号与槽机制进行交换,说的很复杂,实际请看代码,很简单

class HWebContext : public QObject{
    Q_OBJECT
signals:
    void sigClicked();
public slots:
    void setAction(int action);
};
QWebChannel* webchannel = new QWebChannel(m_webview);
m_webview->page()->setWebChannel(webchannel);
m_webContext = new HWebContext;
webchannel->registerObject(QStringLiteral("content"), (QObject*)m_webContext);

首先我们定义一个c++和JS进行交互的对象类,这个类需要继承自QObject,加上Q_OBJECT宏,定义一些信号和槽,这样就可以使用qt的信号与槽机制了.

然后new一个QWebChannel,与QWebEngineView里面的QWebEnginePage绑定起来,用registerObject去注册我们定义的c++和JS进行交互的对象。

这样c++端的工作就完成了,c++端实际上开了一个端口去监听,提供了一个对象供js去使用。

在JS端需要做的工作如下:


                    
                    

你可能感兴趣的:(Qt,品读Qt5)