zoukankan      html  css  js  c++  java
  • Qt学习 之 QWebView

    WebKit 是一个开源的浏览器引擎,目前 Safari,Chrome 等浏览器均使用了 WebKit 作为核心。Qt 从 4.5 版本开始,集成了 WebKit 作为 Qt 的平台组件,用户可以像使用其他组件一样将 WebKit 引擎集成到自己的应用程序中,以提供 Web 的支持。

    Qt 中对 WebKit 做了封装,主要有以下几个类:

    QWebView 最常用的类,这是一个窗体控件,可以用来渲染网页 。
    QWebPage 被 QWebView 包含,表示一个 document。

    QWebFrame 被 QWebPage 包含,表示一个 frame。

    QWebSettings    Web 渲染的全局设置。

    QWebHistory 用于浏览的历史记录。

    图 1. QWebView 的结构图

    QWebView 使用 QWebPage 来实现页面,QWebPage 使用 QWebFrame 来实现页面元素。

    以下是参考文章

    之前在做CS架构的时候,显示图表总是做得不好。只有C#有相应的组件,QT需要手画或者加载一些插件。做了BS架构之后,知道了很多在前端方面表现极佳的图表制作工具,如Echarts。在上一次的大作业之中,也使用了这一方法。那么又知道QT里可以加载QtWebKit,因此便可以进行Web与本地应用的混合开发。

    这里写图片描述

    新建一个Qt Gui项目,记得选上QtWebKit和QNetwork。

    QWebView类

    使用QWebView类只要几行代码就可以做出一个最简单的浏览器。QWebView的主要功能是用于浏览网页,每个QWebView都包含着一个QWebPage,而QWebPage是用于存储和编辑网页的类。

    下面是一个最简单的浏览器了:main.cpp

    #include <QtGui/QApplication>
    #include <QWebView>
    #include <QMainWindow>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QMainWindow window;
        QWebView view(&window);
        view.setGeometry(0, 0, 600, 400);
        view.setUrl(QUrl("https://github.com/Mr-Phoebe"));
        window.show();
        return a.exec();
    }

    webpage.pro:

    TEMPLATE = app  
    TARGET =   
    DEPENDPATH += .  
    INCLUDEPATH += .  
    CONFIG += qt  
    QT += webkit  
    # Input  
    SOURCES += main.cpp  

    QWebView有两种方法可以用来设定要显示的内容,一个是setUrl方法,一个是setContent方法。 这个很简单,试一下就会,不多说了。

    不过对这两种方法会有两种不同的开发方式:

    setContent的话,需要手动将网页代码生成出来放到QWebView中,网页中的元素(如:图片,样式,脚本)就只能采用“file:///”的方式了。

    setUrl的话,更用技术含量一点,可能需要自己做一个简单的Http服务器,然后监听本地端口,掉用QWebView的setUrl(QUrl(http://127.0.0.1:XXXX))就可以了。

    可以使用一种更省事的方法:直接把要显示的html放到apache上去了。

    显示出来并不难,最主要的是如何同界面双向交互,又不是asp,总不能没点按钮就刷一次页面吧。

    最容量想到的是传统Web开发的中常用的Ajax,不过就有两个缺点:

    一个是要监听本地端口,第二个更致命,Ajax不是双向的,Server向Client发消息就不行了。

    下面说一种更好的方法,实现js与C++的双向调用。

    js调用c++方法

    首先要将一个C++的对象“送”到js中,js拿到这个对象以后就可以像其它对象一样,自由的调用它的方法了。

    这一步有两种实现方式:

    1. 在网页中插入控件

    JS端

    在网页中插入下面一段代码:

    <object type="application/x-qt-plugin" id="qt"></object>

    之后就可以通过document.getElementById(‘qt’);获取这个对象,并调用方法了。

    C++端

    首先要自定义一个类继承自QWebPage,在构造函数中加入如下一句话开起plugin的支持。

    settings()->setAttribute(QWebSettings::PluginsEnabled, true);

    然后重载QWebPage中的如下方法(protected的)

    virtual QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues);

    方法的返回值就是要传递绐js的对象。

    注意:返回值要是一个QWidget *类型的,所以可能还要自己自己写一个Widget,写好后,返回的QWidget中的所有public slots在js中都是可见的方法。

    例子如下,有点长,不过很简单:

    MyWidget.h

    #ifndef MYWIDGET_H
    #define MYWIDGET_H
    
    #include<QWidget>
    #include<QWebPage>
    #include<QWebFrame>
    
    class MyWidget :public QWidget {
        Q_OBJECT
    private:
        QWebPage *page;
    public:
        MyWidget(QWebPage *page) : page(page) { }
    public slots:
        void func(QString arg) {
            this->page->mainFrame()->evaluateJavaScript("document.body.innerHTML += '" + arg + "';");
        }
    };
    
    #endif // MYWIDGET_H

    MyPage.h

    #ifndef MYPAGE_H
    #define MYPAGE_H
    
    #include<QWebPage>
    #include<QWebFrame>
    #include"MyWidget.h"
    
    class MyPage : public QWebPage {
        Q_OBJECT
    public:
        MyPage(QObject *parent = 0) : QWebPage(parent) {
            settings()->setAttribute(QWebSettings::PluginsEnabled, true);
        }
    protected:
        QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues){
            return new MyWidget(this);
        }
    };
    
    #endif // MYPAGE_H

    main.cpp

    #include <QtGui/QApplication>
    #include <QMainWindow>
    #include <QWebView>
    #include <QWebPage>
    #include <QWebFrame>
    #include "MyPage.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QMainWindow window;
        QWebView view(&window);
        MyPage page;
        view.setPage(&page);
        view.setGeometry(0, 0, 600, 400);
        // Object
        QString content("<object type='application/x-qt-plugin' height='1' width='1' id='qt'></object>");
        // JS Function f() : Invoke the 'func' function
        content += "<script>document.getElementById('qt').func('https://github.com/Mr-Phoebe');</script>";
        view.setContent(content.toAscii());
        window.show();
        return a.exec();
    }

    2. 用QWebFrame的addToJavaScriptWindowObject方法

    相比上一个方法,个人推荐这种方法。因为上一个在Linux下遇到过很诡异的问题。

    例子是最好的说明方式,于是再绐出一下例子:

    注意:addToJavaScriptWindowObject的第一个参数是对象在js中的变量名,第二个参数的QObject不要求是QWidget。

    MyObject.h

    #ifndef MYOBJECT_H
    #define MYOBJECT_H
    
    #include<QObject>
    #include<QWebPage>
    #include<QWebFrame>
    
    // !! ATTENTION !! : The object do NOT need to inherit from QWidget anymore.
    class MyObject :public QObject {
        Q_OBJECT
    private:
        QWebPage *page;
    public:
        MyObject(QWebPage *page) : page(page) { }
    public slots:
        void func(QString arg) {
            this->page->mainFrame()->evaluateJavaScript("document.body.innerHTML += '" + arg + "';");
        }
    };
    
    #endif // MYOBJECT_H

    main.cpp

    #include <QtGui/QApplication>
    #include <QMainWindow>
    #include <QWebView>
    #include <QWebPage>
    #include <QWebFrame>
    #include "MyObject.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QMainWindow window;
        QWebView view(&window);
        QWebPage page;
        view.setPage(&page);
        view.setGeometry(0, 0, 600, 400);
        MyObject obj(&page);
        page.mainFrame()->addToJavaScriptWindowObject("qt", &obj);
        QString content("<script>function f() { qt.func('https://github.com/Mr-Phoebe'); }</script>");
        content += "<a href='javascript:f()'>Click Me</a>";
        view.setContent(content.toAscii());
        window.show();
    
        return a.exec();
    }

    C++调用js代码

    依旧是两种方法。

    1. evaluateJavaScript

    这个超简单了,上面的例子中就用到了。不多说了。

    2. connect

    这个更符合Qt的风格一点。首先用上一部分介绍的两种方法中的任意一种将一个C++对象“送”到js中去。然后调用这个对象的connect方法,将自己的signals和js方法进行bind。

    再放个例子吧,不过例子中竟然用evaluateJavaScript来bind。

    当QWebView加载好后,绑定MyObject的Miku Signal到js本地方法f,再触发Miku Signal。

    MyObject.h

    #ifndef MYOBJECT_H
    #define MYOBJECT_H
    
    #include<QObject>
    #include<QWebPage>
    #include<QWebFrame>
    
    class MyObject :public QObject {
        Q_OBJECT
    private:
        QWebPage *page;
    public:
        MyObject(QWebPage *page) : page(page) { }
    signals:
        void Miku();
    public slots:
        void viewLoad() {
            this->page->mainFrame()->evaluateJavaScript("qt.Miku.connect(f);");
            this->Miku();
        }
    };
    
    #endif // MYOBJECT_H

    main.cpp

    #include <QtGui/QApplication>
    #include <QMainWindow>
    #include <QWebView>
    #include <QWebPage>
    #include <QWebFrame>
    #include "MyObject.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QMainWindow window;
        QWebView view(&window);
        QWebPage page;
        view.setPage(&page);
        view.setGeometry(0, 0, 600, 400);
        MyObject obj(&page);
        QObject::connect(&view, SIGNAL(loadFinished(bool)), &obj, SLOT(viewLoad()));
        page.mainFrame()->addToJavaScriptWindowObject("qt", &obj);
        QString content("<script>function f() { document.body.innerHTML += 'http://pnuts.cc'; }</script>");
        view.setContent(content.toAscii());
        window.show();
        return a.exec();
    }

    转自:http://blog.csdn.net/u013007900/article/details/52159795
  • 相关阅读:
    HDU4366 Successor 线段树+预处理
    POJ2823 Sliding Window 单调队列
    HDU寻找最大值 递推求连续区间
    UVA846 Steps 二分查找
    HDU3415 Max Sum of MaxKsubsequence 单调队列
    HDU时间挑战 树状数组
    UVA10168 Summation of Four Primes 哥德巴赫猜想
    UESTC我要长高 DP优化
    HDUChess 递推
    HDU4362 Dragon Ball DP+优化
  • 原文地址:https://www.cnblogs.com/liushui-sky/p/7851792.html
Copyright © 2011-2022 走看看