Wt简介

Wt简介作者 Wim Dumon and Koen Deforche 关于作者 1 本文作者 Wim Dumon Sobicom nv 创立者 专注于嵌入式系统设计及生物信息方面的软件工程咨询服务 关于作者 2 Koen Deforche Wt 库作者

大家好,我是讯享网,很高兴认识大家。

作者:Wim Dumon and Koen Deforche
*  关于作者1:本文作者Wim Dumon,Sobicom nv创立者,专注于嵌入式系统设计及生物信息方面的软件工程咨询服务,
*  关于作者2:Koen Deforche,Wt库作者,医学博士,创立并运行Emweb公司(http://www.emweb.eu/),
翻译:zhmsong

注:本文译自《Wt: A Web Toolkit ---Writing web applications using a C++ GUI programming style》(Dr. Dobb's,2008年11期),全文内容取自http://www.ddj.com/cpp/;该文的翻译工作已经获得了Dr. Dobb's杂志主编Jon Erickson及文章主要作者Koen Deforche的授权。


讯享网

 

                                                              图 2 Wt widget继承关系图


    新构建的WCompositeWidget的样式和结构是通过组合现有widgets得到的,这些现有widgets可以是WWebWidget或WCompositeWidget;其行为则是通过将槽与现有widgets提供的各种信号相连定义的。新Widget不仅仅限于服务器端事件处理,还可以使用动态C++-to-JavaScript翻译机制绕过服务器往返直接渲染视图的更新。例如,WTreeNode即使用这一特点实现客户端的打开/叠起开关动作。
部署架构


<messages>
<message id="hello-world">Hello World!</message>
</messages>


<messages>
<message id="hello-world">Dag Wereld!</message>
</messages>


class MyWidget : public WCompositeWidget
{
public:
MyWidget(WContainerWidget *parent = 0)
: WcompositeWidget(parent),
...
{
...

fumbleButton_ = new WPushButton("Fumble");
fumbleButton_->clicked.connect(SLOT(this, MyWidget::doFumble));
...
}
private:
WpushButton *fumbleButton_;
void doFumble()
{
fumbleButton_->disable();

fumbleSome(...);
}
};
                              清单 1

    这个例子存在一个明显的缺陷,即按钮只能在客户端与服务器端发生至少一次往返之后才能禁用,也会发生在所有的fumbling动作都完成之后!而在Wt中,这个缺陷可以通过客户端事件处理轻松地解决。

客户端事件处理

    虽然服务器端能够依规则进行各种事件处理,但存在某些限制,因为客户端和服务器端往返会产生一定的时间延迟。不过幸运的是,当浏览器支持JavaScript,特别是当事件处理直接采用JavaScript时,这种往返延迟带来的影响将显得无足轻重。但是就算我们不去考虑用JavaScript完成事件处理功能的复杂性以及其本身和其实现的缺憾,JavaScript还是存在很多根本性的问题。首先,如果JavaScript不被支持,那么必须提供替代方案。第二,使用JavaScript后,应用程序的服务器端状态将再也不会与客户端保持同步。另外,如果使用自定义的JavaScript,Wt是不能保证程序的健壮性的,特别是在防止XSS攻击和浏览器兼容等方面。

    Wt提供了一种极具吸引力的解决方案,这就是针对所谓的无状态槽的动态C++-to-JavaScript翻译机制。无状态槽即不管应用状态如何都能引起相同页面变化的一种槽。例如,上例中只要点击按钮,按钮即无条件地被禁用,我们可以看到该操作完全包含在MyWidget::doFumble()中,可见该操作是不需要任何应用状态或事件的具体细节的,因此Wt中无状态槽实现了客户端代码中的事件处理。

    我们再看清单2中的代码,他们运行的效果是第一次调用MyWidget::disableFumbleButton()槽时Wt将其所实现的页面变化用相应的JavaScript代码表示出来并缓存于浏览器中,这样做的效果是第一次调用需要在页面更新被渲染前等待服务器往返延迟,但之后的调用则实际是简单地对JavaScript代码的再次执行。很明显,如果fumbling是我们希望用户重复执行的动作时,这种解决方案便捉襟见肘了。

class MyWidget : public WCompositeWidget
{
public:
MyWidget(WContainerWidget *parent = 0)
: WcompositeWidget(parent),
...
{
...
implementStateless(&MyWidget::disableFumbleButton);
fumbleButton_ = new WPushButton("Fumble");
fumbleButton_
->clicked.connect(SLOT(this, MyWidget::disableFumbleButton));
fumbleButton_->clicked.connect(SLOT(this, MyWidget::doFumble));
...
}
private:
WpushButton *fumbleButton_;
void disableFumbleButton()
{
fumbleButton_->disable();
}
void doFumble()
{
fumbleSome(...);
}
};
                                                    清单 2

    当然,通过进一步努力,我们也还是可以消除上述第一次调用时发生的服务器往返延迟的,其方法是让Wt库在客户端事件触发之前便在内部调用无状态槽,这样Wt库就可以提前获得其引起的页面变化。另外,如果需要去掉这种自发的内部调用,则应该进一步提供undo函数。

    使用同一个例子,我们做如下变动:

implementStateless
(&MyWidget::disableFumbleButton,
&MyWidget::undoDisableFumbleButton);
and implement this undo method:
  
void undoDisableFumbleButton()
{
fumbleButton_->enable();
}

Wt库已经为自身诸多内置widget方法提供了无状态实现,比如WWidget::hide() 和WWidget::show(),但偶尔也会包括WFormWidget::enable() 和WFormWidget::disable()。因为将这些规模不大的方法连接到信号非常方便,所以,可以在定义中直接给出自动实现客户端优化的方法,如清单3:

class MyWidget : public WCompositeWidget
{
public:
MyWidget(WcontainerWidget *parent = 0)
: WcompositeWidget(parent),

{

fumbleButton_ = new WpushButton(“Fumble”);
fumbleButton_
->clicked.connect(SLOT(fumbleButton_, WpushButton::disable));
fumbleButton_->clicked.connect(SLOT(this, MyWidget::doFumble));

}
private:
WpushButton *fumbleButton_;
void doFumble()
{
fumbleSome(…);
}
};

小讯
上一篇 2025-04-08 08:49
下一篇 2025-03-17 13:38

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/16522.html