qtwebkit bridge是将qtwebkit 代表的web或者说js 环境和qt代表的c++ native环境关联的一种技术,正是有了它才使得在qt中js和c++的互操作变得如此便利。
而去年我参与的一个直接在raw c++中实现的js 和 webkit 互操作,花费了很多时间,也没有达到qt的效果,当时仅仅解决了js端呼叫c++ 的能力。
那么为什么qt为什么能够方便的提供这种能力?
qt 的qobject 本身就实现了c++ 标准所没有实现的 introspection ,即qt支持元对象模型。
qtwebkit bridge 的几种应用场合
1. 方便的内嵌webcontent,比如一个web的music store,它可以方便的访问本地的播放器
2. 通过qtwebkit 采用web技术后,为开发thin client提供了方便。
几种类似bridge技术的差异
1. NPAI. 类似的bridge技术比如NPAPI, 这儿大致区分为,如果你要为浏览器开发一个插件,那么建议使用NPAPI,如果你想开发一个完整的应用只不过rendering想采用html那么采用qtwebkit bridge。
2. qtscript , 这块我现在还有点不理解。。。? 只是知道qtwebkit bridge 是前者的一个子集。
qtwebkit bridge 同样提供了signal,slot能力,现在看看几种具体场合
1. c++/script
c++ function signal to connect function in js.
这种情况比较适合,你不想让c++ side的对象暴露给js.
2. script/c++
script function signal to connect predefined c++ object.
这儿slot端是预先编写好的c++ 对象。
3. script/script
Note that functions such as qScriptConnect are unavilable in the web environment.
下面是一个例子。。。
In this form of connection, the argument to connect() is the function to connect to the signal.
function myInterestingScriptFunction() { ... }
...
myQObject.somethingChanged.connect(myInterestingScriptFunction);
The argument can be a JavaScript function, as in the above example, or it can be a slot, as in the following example:
myQObject.somethingChanged.connect(myOtherQObject.doSomething);
默认来说,signal和slot 在script环境中式可调用的。
但是,也可以通过一些手段让一个普通方法可在脚本中被call.
simply add the macro before its definition:
class MyObject : public
{
Q_OBJECT
public:
void thisMethodIsInvokableInQtScript();
void thisMethodIsNotInvokableInQtScript();
...
};
属性可访问。。。
The properties of the are available as properties of the corresponding JavaScript object. When you manipulate a property in script code, the C++ get/set method for that property will automatically be invoked. For example, if your C++ class has a property declared as follows:
(bool enabled READ enabled WRITE setEnabled)
then script code can do things like the following:
myQObject.enabled = true;
...
myQObject.enabled = !myQObject.enabled;
子对象访问
Every named child of the (that is, for which () is not an empty string) is by default available as a property of the JavaScript wrapper object. For example, if you have a with a child widget whose objectName property is "okButton", you can access this object in script code through the expression
myDialog.okButton
Since objectName is itself a Q_PROPERTY, you can manipulate the name in script code to, for example, rename an object:
myDialog.okButton
myDialog.okButton.objectName = "cancelButton";
如果父对象可脚本访问,则其命名子对象也可访问。。
Since objectName is itself a Q_PROPERTY, you can manipulate the name in script code to, for example, rename an object:
myDialog.okButton
myDialog.okButton.objectName = "cancelButton";
数据类型自动转换(这个js和c++对象的类型互转,去年我花了很多时间通过一个复杂的模板来进行转换,呵呵,没想到qt的bridge机制已经实现)
1. long/float....,qchar 和js 的number转换
2. qstring 和js string 可互转
3. , and 和js date互转
4. re 和 js的RegEx
5. , , and 转化为js array,其中qvariantlist非常有用
6. 复杂js对象,json 将可以和 qvariantmap/qvariantlist 转换,按照我的理解,如果js端转过来的时候默认转化为qvariantmap; 如果c++端要求qvarinatlist 或者c++端以qvariantlist 传给js那么js会转换为json。
7. qvariant 是一个很灵活的类型,当他作为c++端参数时候,它的实际类型将可以依据上述5调规则演化。
8. qobject, 对象类型。 当c++端将qobject作为参数传递与用于signal,slot,property时候,
这些对象可以像它们已经直接被暴露般使用,比如signal or slot的触发和连接,但是这个功能有一个非常大的限制,类型必须是qobject*,qwidget*; 如果是一个non widget subclass 那么不行;
另外一点意见就是,这类指针js端不会参与lifetime管理;所以使用时候要小心,或者就是全局单件可以用。
qtwebkit 以qpixmaps 来表示html image, qpixmaps 来自于native环境将可以直接被qtwebkit使用 ; 反过来时候,将转化为js的如下形式:
{
width: ...,
height: ...,
toDataURL: function() { ... },
assignToHTMLImageElement: function(element) { ... }
}
这样js就可以使用qpixmaps来展示html image。
Example code:
C++:
class MyObject : {
Q_OBJECT
(QPixmap myPixmap READ getPixmap)
public:
getPixmap() const;
};
MyObject myObject;
myWebPage.mainFrame()->addToJavaScriptWindowObject("myObject", &myObject);
HTML:
"loadImage()"
>
"imageElement" width=
"300" height=
"200" />
When a Qt object expects a QImage or a as input, and the argument passed is an HTML image element, the bridge would convert the pixmap assigned to that image element into a or a QImage.
10. QWebElement 无缝的和js 的dom element 转换。
Example:
C++:
class MyObject : {
Q_OBJECT
public slots:
void doSomethingWithWebElement(const QWebElement&);
};
MyObject myObject;
myWebPage.mainFrame()->addToJavaScriptWindowObject("myObject", &myObject);
HTML:
"runExample()"
>
"someElement">Text
qwebelement 必须存活于ui线程。
最后是架构方面的建议
1. 千万不要将大量的c++ object ,function直接暴露给js,而是有选择暴露,尽量暴露哪些layer层的,比如servicemgr。
2. 当hybird layer参与了对象的创建和销毁,或者通过slot,signal,property介入了qobject*,qwidget*。那么必须非常小心的管理好生命周期。
3. 安全,你必须要知道你暴露在js环境中的c++ 对象,可以直接被js访问,那么你必须小心的确认这些webcontent是可信的。比如来自于https.
阅读(1678) | 评论(0) | 转发(0) |