<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CuteQt Blog</title>
	<atom:link href="http://www.cuteqt.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.cuteqt.com/blog</link>
	<description>Qt技术分享博客</description>
	<lastBuildDate>Mon, 23 Apr 2012 02:50:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>[不完全翻译]如何在meego harmattan上发布和链接动态库</title>
		<link>http://www.cuteqt.com/blog/?p=2195</link>
		<comments>http://www.cuteqt.com/blog/?p=2195#comments</comments>
		<pubDate>Mon, 23 Apr 2012 02:50:06 +0000</pubDate>
		<dc:creator>qpang</dc:creator>
				<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[harmattan]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[shared]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2195</guid>
		<description><![CDATA[介绍
在为meego harmattan（N9）开发过程中，我们经验需要用到第三方库，由于Nokia Store的对于系统的保护策略，虽然harmattan是纯正的linux操作系统，但是我们不可能將动态库放在系统级别的目录，比如/usr/lib，/usr/local/lib。所以如果app使用了其他的动态库，在发布时候，会有链接失败的现象出现，并且同时我们也无法使用设置，考虑到过多的静态库会增加app的体积，所以研究一种可用的发布方式是必要的。
发布动态库
Nokia商店的策略建议讲动态库发布到/opt位置，一般是内置在你的程序目录内，我们假设程序目录目录为/opt/myapp/lib，同时名字为libcool.so。
那为了发布该库，你需要在你的.pro文件中加入如下行：
coollib.files = /local/path/to/libcool.so
coollib.path = /opt/myapp/lib
INSTALLS += coollib
假如你是在windows环境中，你的本地路径需要doc斜线符号来取代反斜线，比如c:/local/path/to/libcool.so。
你也可以考虑使用$$PWD变量来指定动态相对你的.pro文件的相对路径，比如
coollib.files = $$PWD/../coollib/libcool.so
链接到动态库
There are two stages needed for linking against a shared library: compile-time and runtime. At compile-time the shared library is being searched for the functions it exports to build dependencies inside your application&#8217;s binary. At runtime these dependencies are followed and the code of the [...]]]></description>
			<content:encoded><![CDATA[<h1>介绍</h1>
<p>在为meego harmattan（N9）开发过程中，我们经验需要用到第三方库，由于Nokia Store的对于系统的保护策略，虽然harmattan是纯正的linux操作系统，但是我们不可能將动态库放在系统级别的目录，比如/usr/lib，/usr/local/lib。所以如果app使用了其他的动态库，在发布时候，会有链接失败的现象出现，并且同时我们也无法使用设置，考虑到过多的静态库会增加app的体积，所以研究一种可用的发布方式是必要的。</p>
<h1>发布动态库</h1>
<p>Nokia商店的策略建议讲动态库发布到/opt位置，一般是内置在你的程序目录内，我们假设程序目录目录为/opt/myapp/lib，同时名字为libcool.so。<br />
那为了发布该库，你需要在你的.pro文件中加入如下行：</p>
<p>coollib.files = /local/path/to/libcool.so<br />
coollib.path = /opt/myapp/lib<br />
INSTALLS += coollib</p>
<p>假如你是在windows环境中，你的本地路径需要doc斜线符号来取代反斜线，比如c:/local/path/to/libcool.so。<br />
你也可以考虑使用$$PWD变量来指定动态相对你的.pro文件的相对路径，比如</p>
<p>coollib.files = $$PWD/../coollib/libcool.so</p>
<h1>链接到动态库</h1>
<p>There are two stages needed for linking against a shared library: compile-time and runtime. At compile-time the shared library is being searched for the functions it exports to build dependencies inside your application&#8217;s binary. At runtime these dependencies are followed and the code of the shared library is actually executed.<br />
这里有两种情况需要你链接到动态库，编译阶段和运行阶段。编译阶段，动态库用来和你的程序编译至二进制文件，运行阶段，程序依赖动态库代码而运行。</p>
<p>编译阶段需要在你的.pro文件中添加：</p>
<p>LIBS += -L/local/path/to -lcool<br />
INCLUDEPATH = /local/headers-path</p>
<p>cool是库的名字去除后缀面的前缀lib，同时/local/headers-path是库头文件目录所在，你也可以使用$$PWD来使用。<br />
为了成功编译，防止意外出来，你应该需要修改器的rules文件，將行</p>
<p># dh_shlibdeps # Uncomment this line for use without Qt Creator<br />
注释二次为<br />
## dh_shlibdeps # Uncomment this line for use without Qt Creator<br />
或者删除它。<br />
这样做的理由主要出于未知理由（在Qt4.8.0） dh_shlibdeps命令如果只注释一次，那么仍将执行，这样会阻止你的工程编译链接动态库</p>
<p>在运行阶段，你需要告诉你的二进制程序文件，你的动态库文件位置那里，对于普通linux，我们可以使用 LD_LIBRARY_PATH环境变量，但是这里并不适用。<br />
为了解决这个问题，你可以使用&#8211;rpath选项链接你的程序，添加下列一行在你的.pro文件中<br />
QMAKE_LFLAGS += -Wl,&#8211;rpath=/opt/myapp/lib<br />
然后，就完成了</p>
<h1>总结</h1>
<p>以上过程笔者已经在harmattan1.2测试通过，基本包含了绝大多数情况，偶然有特殊情况的话，可以考虑修改环境变量或者將库安装在系统级别的范围。</p>
<h1>参考</h1>
<p>http://www.developer.nokia.com/Community/Wiki/How_to_deploy_and_link_a_shared_library_on_Harmattan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2195</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用无线连接模式开发N9 App</title>
		<link>http://www.cuteqt.com/blog/?p=2193</link>
		<comments>http://www.cuteqt.com/blog/?p=2193#comments</comments>
		<pubDate>Sat, 14 Apr 2012 04:43:33 +0000</pubDate>
		<dc:creator>qpang</dc:creator>
				<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[harmattan]]></category>
		<category><![CDATA[n9]]></category>
		<category><![CDATA[QML]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2193</guid>
		<description><![CDATA[最近入入手N9，对于一个Qt兼linux兼移动开发人员来说，的确是神器了。
既然买来了，就好好开发玩玩。开发移动App，插着USB连着设备是必须得事，但是对于N9来说，不用这样麻烦，有无线连接，同样可以真机测试。
首先原来的USB模式，这部分可以参考BUG神牛的文章：
http://www.cuteqt.com/blog/?p=2169
无线部署开发模式和USB部署开发模式基本相同，最主要的就是要和开发主机连接到同一个无线ap内
，进入到SDK Connectivity可以选择

可以看到，IP地址是192.168.1.104,那么在开发主机的QtSDK内设置设备时候，地址也应该是这个。
接下来呢？接下来就就没了，就是这么简单。其他按照bug神牛的做就可以了，哈，N9开发，就是这么简单。
]]></description>
			<content:encoded><![CDATA[<p>最近入入手N9，对于一个Qt兼linux兼移动开发人员来说，的确是神器了。<br />
既然买来了，就好好开发玩玩。开发移动App，插着USB连着设备是必须得事，但是对于N9来说，不用这样麻烦，有无线连接，同样可以真机测试。<br />
首先原来的USB模式，这部分可以参考BUG神牛的文章：</p>
<p>http://www.cuteqt.com/blog/?p=2169</p>
<p>无线部署开发模式和USB部署开发模式基本相同，最主要的就是要和开发主机连接到同一个无线ap内</p>
<p>，进入到SDK Connectivity可以选择<br />
<a href="http://blog.cnnbboy.net/wp-content/uploads/2012/04/2012-04-15_00-30-55.png"><img class="alignnone size-full wp-image-783" src="http://blog.cnnbboy.net/wp-content/uploads/2012/04/2012-04-15_00-30-55.png" alt="" width="480" height="854" /></a></p>
<p>可以看到，IP地址是192.168.1.104,那么在开发主机的QtSDK内设置设备时候，地址也应该是这个。</p>
<p>接下来呢？接下来就就没了，就是这么简单。其他按照bug神牛的做就可以了，哈，N9开发，就是这么简单。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2193</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>你的N9你做主(诺基亚N9开发者模式详解)</title>
		<link>http://www.cuteqt.com/blog/?p=2169</link>
		<comments>http://www.cuteqt.com/blog/?p=2169#comments</comments>
		<pubDate>Mon, 05 Dec 2011 14:35:28 +0000</pubDate>
		<dc:creator>臭虫</dc:creator>
				<category><![CDATA[Linux技术]]></category>
		<category><![CDATA[MeeGo]]></category>
		<category><![CDATA[n9]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2169</guid>
		<description><![CDATA[N9绝对是一款诺基亚献给Linux开发人员的神器,他为你提供了无穷无尽的可能。在开始释放神器的能量前，你需要做一个小小的动作，那就是激活开发者模式.
激活开发者模式
激活开发者模式很简单，你只需通过菜单 设置-&#62;安全性-&#62;开发人员模式，即可打开如下界面

将开关按钮拨到右边，系统自动会提示你安装必要的软件，最重要的是Terminal和SDK Connectivity,可以在主菜单页找到它们。Terminal可以进行liux命令行的操作，而SDK Connectivity则让你可以在手机和开发主机之间进行网络连接。
root权限
root帐号的密码是rootme 。
有些文章提到可以在Terminal中执行 $ ssh root@localhost 命令可以登录root帐号，可能只是在开发机上的情况。在行货手机上真正起作用的命令应该是

$ devel-su

这也是官方SDK开发文档中介绍的方法。
和Linux主机连接
如果觉得在手机上通过软键盘来执行命令显得自己太像2B青年的话，建议还是通过PC主机和N9进行连接。这里只介绍Linux机器的连接方法。
 打开SDK Connectivity软件 
 利用USB线或WLAN将Linux主机和N9连接起来
 你可以看到如下界面


在这里你可有得到如下信息
 N9的IP为192.168.2.15,通常Linux PC端的IP为192.168.2.14 
 一个密码，这个密码的用户是developer

PC端的Qt SDK如果要安装和调试时会用到上面两个信息。本文不会涉及SDK，不过会介绍怎么远程登录到N9上。
ssh登录到N9
SDK Connectivity连接成功的话，就可以在PC端通过ssh连接N9了，命令是

$ ssh developer@192.168.2.15   #密码就是在SDK Connecity自动生成的，每次都会变

如果你不想每次登录都要输入密码，则可以将本机公钥拷贝到N9上。

$ ssh-copy-id developer@192.168.2.15   #若提示本地公钥文件不存在，可先执行$ ssh-keygen

这样的话，以后再执行$ ssh developer@192.168.2.15就无需输入密码了。
在你通过通过ssh登录到N9后，$ devel-su 命令进入root权限。
N9上的文件系统
进入N9后你可以大概了解一下里面的文件系统，用户生成的文件都会在MyDocs下
~/MyDocs $ pwd
/home/developer/MyDocs
~/MyDocs $ ls Pictures/    #系统自带的图片和截图生成的图片在这
~/MyDocs $ ls DCIM/       [...]]]></description>
			<content:encoded><![CDATA[<p>N9绝对是一款诺基亚献给Linux开发人员的神器,他为你提供了无穷无尽的可能。在开始释放神器的能量前，你需要做一个小小的动作，那就是激活开发者模式.</p>
<h3>激活开发者模式</h3>
<p>激活开发者模式很简单，你只需通过菜单 设置-&gt;安全性-&gt;开发人员模式，即可打开如下界面<br />
<a href="http://www.cuteqt.com/blog/wp-content/uploads/2011/12/2011-12-05_21-34-11.png"><img class="alignnone size-medium wp-image-2172" title="2011-12-05_21-34-11" src="http://www.cuteqt.com/blog/wp-content/uploads/2011/12/2011-12-05_21-34-11-168x300.png" alt="" width="168" height="300" /></a><br />
将开关按钮拨到右边，系统自动会提示你安装必要的软件，最重要的是Terminal和SDK Connectivity,可以在主菜单页找到它们。Terminal可以进行liux命令行的操作，而SDK Connectivity则让你可以在手机和开发主机之间进行网络连接。</p>
<h3>root权限</h3>
<p>root帐号的密码是<font color=red><strong>rootme</strong></font> 。<br />
有些文章提到可以在Terminal中执行 <strong>$ ssh root@localhost</strong> 命令可以登录root帐号，可能只是在开发机上的情况。在行货手机上真正起作用的命令应该是<br />
<code><br />
$ devel-su<br />
</code><br />
这也是官方SDK开发文档中介绍的方法。</p>
<h3>和Linux主机连接</h3>
<p>如果觉得在手机上通过软键盘来执行命令显得自己太像2B青年的话，建议还是通过PC主机和N9进行连接。这里只介绍Linux机器的连接方法。</p>
<blockquote><li> 打开SDK Connectivity软件 </li>
<li> 利用USB线或WLAN将Linux主机和N9连接起来</li>
<li> 你可以看到如下界面</li>
</blockquote>
<p><a href="http://www.cuteqt.com/blog/wp-content/uploads/2011/12/2011-12-05_21-10-56.png"><img src="http://www.cuteqt.com/blog/wp-content/uploads/2011/12/2011-12-05_21-10-56-168x300.png" alt="" title="2011-12-05_21-10-56" width="168" height="300" class="alignnone size-medium wp-image-2181" /></a><br />
在这里你可有得到如下信息</p>
<blockquote><li> N9的IP为192.168.2.15,通常Linux PC端的IP为192.168.2.14 </li>
<li> 一个密码，这个密码的用户是developer</li>
</blockquote>
<p>PC端的Qt SDK如果要安装和调试时会用到上面两个信息。本文不会涉及SDK，不过会介绍怎么远程登录到N9上。</p>
<h4>ssh登录到N9</h4>
<p>SDK Connectivity连接成功的话，就可以在PC端通过ssh连接N9了，命令是<br />
<code><br />
$ ssh developer@192.168.2.15   #密码就是在SDK Connecity自动生成的，每次都会变<br />
</code><br />
如果你不想每次登录都要输入密码，则可以将本机公钥拷贝到N9上。<br />
<code><br />
$ ssh-copy-id developer@192.168.2.15   #若提示本地公钥文件不存在，可先执行<strong>$ ssh-keygen</strong><br />
</code><br />
这样的话，以后再执行<strong>$ ssh developer@192.168.2.15</strong>就无需输入密码了。<br />
在你通过通过ssh登录到N9后，<strong>$ devel-su</strong> 命令进入root权限。</p>
<h3>N9上的文件系统</h3>
<p>进入N9后你可以大概了解一下里面的文件系统，用户生成的文件都会在MyDocs下</p>
<blockquote><p>~/MyDocs $ pwd<br />
/home/developer/MyDocs<br />
~/MyDocs $ ls Pictures/    #系统自带的图片和截图生成的图片在这<br />
~/MyDocs $ ls DCIM/        #照片在这</p></blockquote>
<p>通过诺基亚软件商店安装的程序主体都在 /opt/目录下，如果你想学习学习别人的QML都怎么学习的，可以去这里参考:)</p>
<h3>安装未验证软件</h3>
<p>如果你想安装未经验证的软件，比如网上下载到的QQ，那么你需要通过 设置->应用程序->安装，打开如下界面<br />
<a href="http://www.cuteqt.com/blog/wp-content/uploads/2011/12/2011-12-05_21-14-01.png"><img src="http://www.cuteqt.com/blog/wp-content/uploads/2011/12/2011-12-05_21-14-01-168x300.png" alt="" title="2011-12-05_21-14-01" width="168" height="300" class="alignnone size-medium wp-image-2188" /></a><br />
然后使能允许来自非商店来源的安装。<br />
<code>$ dpkg -i filename.deb </code><br />
可以让你在命令行下安装一个软件。</p>
<h3>截图软件</h3>
<p>软件商店里带的ScreenshotMe就很好用，本文的截图都是通过它完成的。截图方法很简单，在ScreenshotMee运行后，放到后台。在你想截图的时候将手机屏幕右上角轻轻盖住一会就可以了。<br />
将N9里的图片和照相拷贝到Linux主机的方法也很简单，只需在Linux上执行<br />
<code>scp -r developer@192.168.2.15:~/MyDocs/Pictures .<br />
scp -r developer@192.168.2.15:~/MyDocs/DCIM .</code><br />
就可以把图片都拷贝出来了。</p>
<h3>更多帮助</h3>
<p>请访问 <a href="http://harmattan-dev.nokia.com/docs/library/html/guide/html/main.html">http://harmattan-dev.nokia.com/docs/library/html/guide/html/main.html</a><br />
感谢诺基亚MeeGo团队不仅提供了一个完美的手机给我们，还提供了这么优秀的文档。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2169</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Qt全局热键（Linux/X11篇）</title>
		<link>http://www.cuteqt.com/blog/?p=2164</link>
		<comments>http://www.cuteqt.com/blog/?p=2164#comments</comments>
		<pubDate>Mon, 01 Aug 2011 13:48:38 +0000</pubDate>
		<dc:creator>shiroki</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Linux技术]]></category>
		<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[global]]></category>
		<category><![CDATA[hotkey]]></category>
		<category><![CDATA[lib]]></category>
		<category><![CDATA[Qt4]]></category>
		<category><![CDATA[X11]]></category>
		<category><![CDATA[全局热键]]></category>
		<category><![CDATA[热键]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2164</guid>
		<description><![CDATA[原作者liuyanghejerry 发表于本站论坛
很久以前许诺RED要写这个来着，后来各种事情冒出导致没能完成，今天履行一下诺言= =
代码大部分参考的都是libqxt的全局热键的内容，对于新手希望有所帮助。
Linux很多发行版都使用的是X11系统作为窗口系统的，比如Ubuntu 10。所以注册全局热键实际上是在X11窗口系统当中注册一个热键，作为全局热键来使用。
和Windows当中相仿，需要用到的几个API是：
XGrabKey，参考http://tronche.com/gui/x/xlib/input/XGrabKey.html
XStringToKeysym，参考http://tronche.com/gui/x/xlib/ut &#8230; StringToKeysym.html
XKeysymToKeycode，参考http://tronche.com/gui/x/xlib/ut &#8230; eysymToKeycode.html
XSync，参考http://tronche.com/gui/x/xlib/event-handling/XSync.html
XUngrabKey，参考http://tronche.com/gui/x/xlib/input/XUngrabKey.html
XSetErrorHandler，参考http://tronche.com/gui/x/xlib/ev &#8230; etErrorHandler.html
其过程是这样的：
首先，将需要注册的键值通过XStringToKeysym和XKeysymToKeycode两个函数计算得出（注意，像Ctrl这样的功能键需要自己进行枚举）；
其次，使用XSetErrorHandler注册一个错误处理函数；
之后使用XGrabKey注册热键；
然后使用XSync通知X11系统更新缓存
最后恢复X11原来的错误处理函数。
XUngrabKey的过程与之类似，只不过是换了一个函数罢了。
核心代码：

static int (*original_x_errhandler)(Display* display, XErrorEvent* event);
static int my_x_errhandler(Display* display, XErrorEvent *event)
{
    Q_UNUSED(display);
    switch (event->error_code)
    {
        case BadAccess:
        case BadValue:
     [...]]]></description>
			<content:encoded><![CDATA[<p>原作者liuyanghejerry 发表于本站论坛<br />
很久以前许诺RED要写这个来着，后来各种事情冒出导致没能完成，今天履行一下诺言= =</p>
<p>代码大部分参考的都是libqxt的全局热键的内容，对于新手希望有所帮助。</p>
<p>Linux很多发行版都使用的是X11系统作为窗口系统的，比如Ubuntu 10。所以注册全局热键实际上是在X11窗口系统当中注册一个热键，作为全局热键来使用。</p>
<p>和Windows当中相仿，需要用到的几个API是：</p>
<p>XGrabKey，参考http://tronche.com/gui/x/xlib/input/XGrabKey.html<br />
XStringToKeysym，参考http://tronche.com/gui/x/xlib/ut &#8230; StringToKeysym.html<br />
XKeysymToKeycode，参考http://tronche.com/gui/x/xlib/ut &#8230; eysymToKeycode.html<br />
XSync，参考http://tronche.com/gui/x/xlib/event-handling/XSync.html<br />
XUngrabKey，参考http://tronche.com/gui/x/xlib/input/XUngrabKey.html<br />
XSetErrorHandler，参考http://tronche.com/gui/x/xlib/ev &#8230; etErrorHandler.html</p>
<p>其过程是这样的：</p>
<p>首先，将需要注册的键值通过XStringToKeysym和XKeysymToKeycode两个函数计算得出（注意，像Ctrl这样的功能键需要自己进行枚举）；</p>
<p>其次，使用XSetErrorHandler注册一个错误处理函数；</p>
<p>之后使用XGrabKey注册热键；</p>
<p>然后使用XSync通知X11系统更新缓存</p>
<p>最后恢复X11原来的错误处理函数。</p>
<p>XUngrabKey的过程与之类似，只不过是换了一个函数罢了。</p>
<p>核心代码：<br />
<code><br />
static int (*original_x_errhandler)(Display* display, XErrorEvent* event);</p>
<p>static int my_x_errhandler(Display* display, XErrorEvent *event)<br />
{<br />
    Q_UNUSED(display);<br />
    switch (event->error_code)<br />
    {<br />
        case BadAccess:<br />
        case BadValue:<br />
        case BadWindow:<br />
            if (event->request_code == 33 /* X_GrabKey */ ||<br />
                event->request_code == 34 /* X_UngrabKey */)<br />
            {<br />
                qDebug()<<"error:"<<event->error_code<<"when "<<event->request_code;<br />
            }<br />
        default:<br />
            return 0;<br />
    }<br />
}</p>
<p>MyApplication::MyApplication ( int &#038; argc, char ** argv ):QApplication (argc,argv)<br />
{<br />
    Display* display = QX11Info::display();<br />
    Window window = QX11Info::appRootWindow();<br />
    Bool owner = True;<br />
    int pointer = GrabModeAsync;<br />
    int keyboard = GrabModeAsync;<br />
    quint32 keyCode = XKeysymToKeycode(display,XStringToKeysym("M"));<br />
    quint32 keyMod = 0;<br />
    keyMod |=ControlMask;<br />
    original_x_errhandler = XSetErrorHandler(my_x_errhandler);<br />
    XGrabKey(display, keyCode, keyMod, window, owner, pointer, keyboard);<br />
    XSync(display, false);<br />
    XSetErrorHandler(original_x_errhandler);<br />
}</p>
<p>bool MyApplication::x11EventFilter ( XEvent * event )<br />
{<br />
    XEvent* eventX = static_cast<XEvent*>(event);<br />
    if (eventX->type == KeyPress)<br />
    {<br />
        qDebug()<<"Got you, my baby.";</p>
<p>        Display* display = QX11Info::display();<br />
        Window window = QX11Info::appRootWindow();<br />
        quint32 keyCode = XKeysymToKeycode(display,XStringToKeysym("M"));<br />
        quint32 keyMod = 0;<br />
        keyMod |=ControlMask;<br />
        original_x_errhandler = XSetErrorHandler(my_x_errhandler);<br />
        XUngrabKey(display, keyCode, keyMod, window);<br />
        XSync(display, false);<br />
        XSetErrorHandler(original_x_errhandler);<br />
    }<br />
    return false;<br />
}<br />
</code></p>
<p>最后提供一个可以编译的实例：<a href='http://www.cuteqt.com/blog/wp-content/uploads/2011/08/hotkey.zip'>hotkey.zip</a></p>
<p>运行程序后，在全局按下Ctrl+M可以在debug处收到消息，收到一次后程序即注销热键。注意，不要和其他程序冲突。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2164</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac Cocoa实现事件过滤的方法</title>
		<link>http://www.cuteqt.com/blog/?p=2161</link>
		<comments>http://www.cuteqt.com/blog/?p=2161#comments</comments>
		<pubDate>Fri, 15 Jul 2011 10:09:29 +0000</pubDate>
		<dc:creator>shiroki</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[其他平台技术]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[macEventFilter]]></category>
		<category><![CDATA[NSApplication]]></category>
		<category><![CDATA[NSEvent]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2161</guid>
		<description><![CDATA[Qt为不同平台提供了平台相关的事件过滤函数， 如X11下为
bool QApplication::x11EventFilter ( XEvent * event ) [virtual]
一般情况下，开发者可以通过派生QApplication，然后重写该函数获得程序得到的所有X11事件。 在其他平台上也有类似的函数可以重写。 但笔者在做Mac相关的程序时在文档中发现了这样一段话：
“
bool QApplication::macEventFilter ( EventHandlerCallRef caller, EventRef event ) [virtual]
Warning: This virtual function is only implemented under Mac OS X when against Carbon.
”
这说明在用Cocoa时， 标准的Qt方法没有办法截获程序的事件。 文档后面还描述了在Cocoa下该如何做才能得到事件：“
Cocoa uses a different event system which means this function is NOT CALLED when building Qt against Cocoa. If you want similar [...]]]></description>
			<content:encoded><![CDATA[<p>Qt为不同平台提供了平台相关的事件过滤函数， 如X11下为</p>
<p><!-- p, li { white-space: pre-wrap; } --><a name="x11EventFilter"></a>bool QApplication::x11EventFilter ( XEvent * event ) [virtual]</p>
<p>一般情况下，开发者可以通过派生QApplication，然后重写该函数获得程序得到的所有X11事件。 在其他平台上也有类似的函数可以重写。 但笔者在做Mac相关的程序时在文档中发现了这样一段话：</p>
<p>“</p>
<p><!-- p, li { white-space: pre-wrap; } --><a name="macEventFilter"></a>bool QApplication::macEventFilter ( EventHandlerCallRef caller, EventRef event ) [virtual]</p>
<p>Warning: This virtual function is only implemented under Mac OS X when against Carbon.</p>
<p>”</p>
<p>这说明在用Cocoa时， 标准的Qt方法没有办法截获程序的事件。 文档后面还描述了在Cocoa下该如何做才能得到事件：“</p>
<p><!-- p, li { white-space: pre-wrap; } -->Cocoa uses a different event system which means this function is NOT CALLED when building Qt against Cocoa. If you want similar functionality subclass NSApplication and reimplement the sendEvent: message to handle all the NSEvents. You also will need to to instantiate your custom NSApplication before creating a <a href="qapplication.html">QApplication</a>. See <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html">Apple&#8217;s NSApplication Reference</a> for more information.</p>
<p>”</p>
<p>这段话说来算是很详细具体了， 但由于笔者对Mac编程所知甚少， 一时之间还是觉得有些无所适从， 相信很多朋友跟笔者有同样的疑虑。 通过在网上查找例子和文档， 笔者终于搞定了一个小例子， 特在此和广大qter分享， 希望对大家有所帮助。 闲话少说， 上代码：<br />
<code><br />
#include <QApplication><br />
#include <Cocoa/Cocoa.h><br />
#include "mainwin.h"</p>
<p>@interface KeyLoggerApplication : NSApplication<br />
{<br />
}<br />
@end</p>
<p>@implementation KeyLoggerApplication</p>
<p>- (BOOL)sendEvent:(NSEvent *)anEvent {</p>
<p>       NSEventType type = [anEvent type];<br />
       bool handled = NO;</p>
<p>       if (type == NSKeyUp)<br />
       {<br />
               switch( [anEvent keyCode] )<br />
               {<br />
                       default:<br />
                               NSLog(@"Keypressed: %d, **%@**", [anEvent keyCode], [anEvent characters]);<br />
                               break;<br />
               }<br />
       }</p>
<p>       //handle only the keys i need then let the other go through the regular channels<br />
       //this stops the annoying beep<br />
       if( !handled )<br />
               [super sendEvent:anEvent];<br />
}<br />
@end</p>
<p>int main(int argc, char* argv[])<br />
{<br />
        [KeyLoggerApplication sharedApplication];<br />
        QApplication a(argc, argv);<br />
        MainWin mw;<br />
        mw.show();<br />
        return a.exec();<br />
}<br />
</code></p>
<p>上面这段代码将接收到的键盘按下的事件打印到console上。除了语法是奇怪的Objective C的语法之外， 没有什么难点， 相信大家都是看得懂的。 还有一点值得提醒的地方， 就是这段代码保存的文件必须以.mm为后缀名， 也就是我们通常写的main.cpp要改成main.mm， 相应的pro文件也要修改。 pro里还要加上 &#8220;LIBS+= -framework AppKit&#8221;，因为用到了AppKit提供的NSApplication等API。<br />
个人觉得Mac编程的这些奇怪的条条框框有点太另类，俺是非常不喜欢的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2161</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在Qt程序中使用OpenCV的介绍</title>
		<link>http://www.cuteqt.com/blog/?p=2158</link>
		<comments>http://www.cuteqt.com/blog/?p=2158#comments</comments>
		<pubDate>Mon, 20 Jun 2011 10:23:56 +0000</pubDate>
		<dc:creator>shiroki</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Linux技术]]></category>
		<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[cmake]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[Qt4]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2158</guid>
		<description><![CDATA[OpenCV安装
关于OpenCV的安装，参考：
http://opencv.willowgarage.com/wiki/InstallGuide
安装文档写得无比详细， 这里就不赘述了。 简单来说就是安装CMake，然后用cmake命令去配置和编译。
最简单的命令是 &#8220;cmake .&#8221;。 这一步应该不算一帆风顺， 笔者遇到了gstreamer头文件找不到的问题。 在OpenCV的代码里搜索一番没找到gstreamer的头文件目录在哪里配置， 而笔者对cmake又非常不熟悉， 只好用了个土方法， 在/usr/include下给本机的gstreamer目录建了个link到OpenCV使用的gstreamer路径。 OpenCV使用的gstreamer路径在生成的Makefile里提到了， 是/usr/include/gstreamer-0.10， 这个路径是从哪儿得到的这一点很神奇&#8230;谁要是知道的请不吝赐教啊。 笔者电脑中的路径则为/usr/inlcude/gstreamer-0.10-a， 故建立链接如下：
ln -s /usr/include/gstreamer-0.10-a /usr/include/gstreamer-0.10
代码例子
OpenCV里带了很多的sample， 在samples目录下， 其中一个引起了笔者的注意， 那就是samples/cpp/Qt_sample。 简单看了看代码， OpenCV里已经实现了和Qt的集成， 里面用Qt的API写了widget，可以直接把摄像头取得的内容显示在Qt的widget里。
但这个例子工程似乎并没有做好， 编译过程实在是太曲折了， 到目前还没找到方法编译成功， 报的错误是undefined reference。 第一个遇到的问题是默认的编译选项不会去编译samples目录， 为了寻找合适的编译选项颇费了点脑筋（因为笔者对cmake基本上可以说是一窍不通的&#8230;汗）。 尝试单独编译samples目录， 失败了， 报了个莫名其妙的cmake版本的问题。 估计是有些依赖的东西是需要顶层目录里读取的。 继续查找相关的脚本和配置， 发现CMakeList.txt里提到了一个BUILD_EXAMPLES变量， 当此变量为真值时会编译samples目录。 但笔者绞尽脑汁也没想出来怎么才能从外部配置这个值， 是用环境变量？ cmake参数？ 都试了， 没一个管用的。 找来找去发现了OpenCV的文档里有个例子，说明了如何设置变量，是在cmake的命令行传入 -D BUILD_EXAMPLES=ON这样的方式。 如此一来build整个工程时就会自动为samples目录创建Makefile。所以configure的命令变成：
cmake -D BUILD_EXAMPLES=ON .
生成的例子都在OPENCV_DIR/bin下，大家可以运行看看。（不包括Qt_sample这个例子）
在Qt中使用OpenCV
Qt程序要想用OpenCV的函数需要将opencv的头文件和库在工程pro文件里配置一下，添加INCLUDEPATH和LIBS，具体的方法参考：
http://www.opencv.org.cn/index.php/%E5%9C%A8Qt%E4%B8%AD%E4%BD%BF%E7%94%A8OpenCV%E5%BA%93
另外有一篇更实用更详细的文章， 还提供几个很好的例子， 是绝佳的参考。 大家有问题就仔细看这篇文章， 一般都能得到解答：
http://code.google.com/p/qt-opencv-multithreaded/wiki/Documentation
]]></description>
			<content:encoded><![CDATA[<p><strong>OpenCV安装</strong><br />
关于OpenCV的安装，参考：</p>
<p>http://opencv.willowgarage.com/wiki/InstallGuide</p>
<p>安装文档写得无比详细， 这里就不赘述了。 简单来说就是安装CMake，然后用cmake命令去配置和编译。</p>
<p>最简单的命令是 &#8220;cmake .&#8221;。 这一步应该不算一帆风顺， 笔者遇到了gstreamer头文件找不到的问题。 在OpenCV的代码里搜索一番没找到gstreamer的头文件目录在哪里配置， 而笔者对cmake又非常不熟悉， 只好用了个土方法， 在/usr/include下给本机的gstreamer目录建了个link到OpenCV使用的gstreamer路径。 OpenCV使用的gstreamer路径在生成的Makefile里提到了， 是/usr/include/gstreamer-0.10， 这个路径是从哪儿得到的这一点很神奇&#8230;谁要是知道的请不吝赐教啊。 笔者电脑中的路径则为/usr/inlcude/gstreamer-0.10-a， 故建立链接如下：<br />
ln -s /usr/include/gstreamer-0.10-a /usr/include/gstreamer-0.10</p>
<p><strong>代码例子</strong><br />
OpenCV里带了很多的sample， 在samples目录下， 其中一个引起了笔者的注意， 那就是samples/cpp/Qt_sample。 简单看了看代码， OpenCV里已经实现了和Qt的集成， 里面用Qt的API写了widget，可以直接把摄像头取得的内容显示在Qt的widget里。<br />
但这个例子工程似乎并没有做好， 编译过程实在是太曲折了， 到目前还没找到方法编译成功， 报的错误是undefined reference。 第一个遇到的问题是默认的编译选项不会去编译samples目录， 为了寻找合适的编译选项颇费了点脑筋（因为笔者对cmake基本上可以说是一窍不通的&#8230;汗）。 尝试单独编译samples目录， 失败了， 报了个莫名其妙的cmake版本的问题。 估计是有些依赖的东西是需要顶层目录里读取的。 继续查找相关的脚本和配置， 发现CMakeList.txt里提到了一个BUILD_EXAMPLES变量， 当此变量为真值时会编译samples目录。 但笔者绞尽脑汁也没想出来怎么才能从外部配置这个值， 是用环境变量？ cmake参数？ 都试了， 没一个管用的。 找来找去发现了OpenCV的文档里有个例子，说明了如何设置变量，是在cmake的命令行传入 -D BUILD_EXAMPLES=ON这样的方式。 如此一来build整个工程时就会自动为samples目录创建Makefile。所以configure的命令变成：<br />
cmake -D BUILD_EXAMPLES=ON .</p>
<p>生成的例子都在OPENCV_DIR/bin下，大家可以运行看看。（不包括Qt_sample这个例子）</p>
<p><strong>在Qt中使用OpenCV</strong><br />
Qt程序要想用OpenCV的函数需要将opencv的头文件和库在工程pro文件里配置一下，添加INCLUDEPATH和LIBS，具体的方法参考：</p>
<p>http://www.opencv.org.cn/index.php/%E5%9C%A8Qt%E4%B8%AD%E4%BD%BF%E7%94%A8OpenCV%E5%BA%93</p>
<p>另外有一篇更实用更详细的文章， 还提供几个很好的例子， 是绝佳的参考。 大家有问题就仔细看这篇文章， 一般都能得到解答：</p>
<p>http://code.google.com/p/qt-opencv-multithreaded/wiki/Documentation</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2158</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>计算QTextEdit的行位置</title>
		<link>http://www.cuteqt.com/blog/?p=2150</link>
		<comments>http://www.cuteqt.com/blog/?p=2150#comments</comments>
		<pubDate>Thu, 16 Jun 2011 12:26:58 +0000</pubDate>
		<dc:creator>shiroki</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[Qt4]]></category>
		<category><![CDATA[QTextEdit]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2150</guid>
		<description><![CDATA[笔者以前撰写过一篇关于QPlainTextEdit计算和绘制行号的文章， 里面详细讲述了遍历QPlainTextEdit的每一行及其位置的方法。 最近遇到一个问题是要为QTextEdit实现相同的功能。 经过实践发现， 原理相同但使用的函数略有不同， 特此memo， 希望对广大qter有用。
如果没有阅读过笔者前文的， 请自行复习： 计算和绘制QPlainTextEdit的行号
针对QTextEdit的代码版本列举如下：

QPainter painter(w);
QTextBlock block = document()-&#62;begin();
int top = 0;
QTextCursor cursor(block);
cursor.setPosition(0);//move to the beginning of the document
int linenum = 0;
while(linenum &#60; document()-&#62;lineCount())
{
for( int i = 0 ; i &#60; block.lineCount(); i ++)         {         [...]]]></description>
			<content:encoded><![CDATA[<p>笔者以前撰写过一篇关于QPlainTextEdit计算和绘制行号的文章， 里面详细讲述了遍历QPlainTextEdit的每一行及其位置的方法。 最近遇到一个问题是要为QTextEdit实现相同的功能。 经过实践发现， 原理相同但使用的函数略有不同， 特此memo， 希望对广大qter有用。</p>
<p>如果没有阅读过笔者前文的， 请自行复习： <a href="http://www.cuteqt.com/blog/?p=1740">计算和绘制QPlainTextEdit的行号</a></p>
<p>针对QTextEdit的代码版本列举如下：<br />
<code><br />
QPainter painter(w);<br />
QTextBlock block = document()-&gt;begin();<br />
int top = 0;<br />
QTextCursor cursor(block);<br />
cursor.setPosition(0);//move to the beginning of the document<br />
int linenum = 0;<br />
while(linenum &lt; document()-&gt;lineCount())<br />
{<br />
for( int i = 0 ; i &lt; block.lineCount(); i ++)         {         color += 50;             color %= 255;             QColor pc(color,color,color);         QTextLine line = block.layout()-&gt;lineAt(i);<br />
painter.fillRect( block.layout()-&gt;position().x(), block.layout()-&gt;position().y(), line.width(), line.height(), pc);<br />
qWarning() &lt;&lt; linenum &lt;&lt; block.layout()-&gt;position() &lt;&lt; color;<br />
linenum ++;<br />
}<br />
block = block.next();<br />
if(!block.isValid())<br />
{<br />
break;<br />
}<br />
}</code></p>
<p>其实比较两者， 其相似程度达到95％以上。 只有一点需要提示注意， 那就是QTextLine的位置信息（x、y，rect等）是相对于当前QTextBlock而言， 所以需要按照block的位置信息相应位移才是正确的值。</p>
<p>这篇blog比较简单， 仅做memo用。 <img src='http://www.cuteqt.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2150</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>QML Untitled（四）：Review Native Quick Widgets</title>
		<link>http://www.cuteqt.com/blog/?p=2133</link>
		<comments>http://www.cuteqt.com/blog/?p=2133#comments</comments>
		<pubDate>Mon, 09 May 2011 15:09:30 +0000</pubDate>
		<dc:creator>qpang</dc:creator>
				<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[QML]]></category>
		<category><![CDATA[Qt4]]></category>
		<category><![CDATA[QtQuick]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2133</guid>
		<description><![CDATA[在前面到系列文章中，笔者只给了Native Quick Widget二星的评价，现在看来，这是一个非常肤浅的认识，在没有深入源码和具体功能到前提下，仅仅依靠界面来判断是非常愚蠢到行为。
这也提示了笔者，每个开源项目都有存在都有它到可取之处，由于开源者无私到分享，才能铸就出更好的软件，提供更好到代码逻辑。
这套Native Quick Widgets也是，它的存在价值并不是提供了美仑美焕的界面，而是提供了在目前到QtQuick中缺失的几个重要功能。
这几个功能作为触摸屏的移动设备开发来说，并没有非存在不可的的价值，但是一旦将QML应用于桌面开发，就显示出巨大的影响。
很显然，Native Quick Widgets的作者应该是使用QML进行了桌面软件开发或者在这方面的尝试，因此意识到了这方面的不足，才有这套组件的出现。
首先对这套QML组件进行最基本的分析，通过阅读源码发现，它提供了7个自定义QML元素：
1.Button元素
2.CheckBox元素
3.CursorArea元素
4.LineEdit元素
5.MenuAction元素
6.Menu元素
7.ProgressBar元素
8.ScrollBar元素
除了这些元素，还提供了7个QML组件：
1.Button.qml
2.ContextMenu.qml
3.ProgressBar.qml
4.ScrollBar.qml
5.CheckBox.qml
6.LineEdit.qml
7.ScrollArea.qml
逐一对这些进行分析，就可以发现这些组件提供的功能对于进行桌面开发的重要意义，从上面列出的QML组件和QML元素可以抽取出这些功能点：
1.最基本的按钮，用于用户的事件触发
2.输入编辑框，用于用户的输入
3.进度条，用户显示一个事件的处理进度
4.菜单和菜单动作，用于区域的用户事件触发
5.滚动条和滚动区域，用于查看可视范围外的界面
6.鼠标显示区域，用于改变鼠标显示的形状

前三个功能点，并不是特别需要或者重要，因为使用原生的QML也能完成这些功能点，并且能够编写出非常绚丽的效果，但是下面三点就不同了。
首先应该明白QML及QtQuick这门技术的适用范围，这是与传统UI不同的模式，并且设计之初更像是应用于触摸屏等移动设备，而不是桌面应用。针对这三个功能点来比较下移动设备和桌面开发的差异。
菜单功能在两者之间的差异：
1.桌面上菜单必不可少，右键菜单，或者是依附按钮的菜单，都是提供用户进行操作的捷径，并且，菜单往往是多级的，二三级，甚至四级菜单都会存在，而触摸屏设备内，由于屏幕尺寸的限制，往往多是一级菜单或者是没有菜单，基本多由按钮来完成必要的事件触发；
2.在桌面上，鼠标有右键可以触发菜单，在触摸屏上，操作就是点击或者放开，这是菜单非必需的重要理由，哪怕是多点触摸，既然可以多点触摸了，那为什么还需要菜单还进行事件触发呢，手势操作会显得更加便捷；
从这两点就已经可以看出两者的重大差异，更为重要的是，针对QML本身来说，由于采取的是以图元为基础的DirectUI，虽然可以实现自我绘制菜单，但是对于紧张的开发周期来说，这些实现的时间无疑是挥霍。
滚动功能在两者之间的差异：
这也是桌面上必备的功能，触摸屏设备也同样具有，但是同样受限于触摸屏设备的尺寸，用户不可能把手点在微小的滚动条上滚动，而是在滚动区域，这点在ipad上的操作就可以体现出来。可是同样的操作拿到桌面上，虽然有惯性滚动，但是这样的操作是现在的桌面用户无论如何都接受不了的；
QML的基本元素中提供了滚动，但是它不适用于传统的桌面表现形式，虽然有，但是直接应用的话，对于还在鼠标时代的桌面来说，反而提供了很差的用户体验。
最后是鼠标区域的差异：
在桌面上，由于操作的不同，鼠标会变换形状，提示用户当前操作的状态，可是在触摸屏设备上，就是画蛇添足了，这是非常细节的地方，但是越细节的地方才能更加体会出编写桌面软件和移动设备软件的不同。
通过这些简单的分析，就应该认识到Native Quick Widgets的意义，虽然只是简单地引用了Qt原生部件，但是这个实现帮助使用QML开发人员省去了自己实现这些功能点的过程，节省了宝贵的开发时间。
再次表达出对开源者的尊敬，正是接近无限的开源的代码，才铸就了ios，android，meego，如果没有开源，这些为人们生活提供巨大帮助和快乐的系统将不会出现。
同时也有由于Qt的存在，我们节省了造轮子的过程，才能快速地编写出软件，满足用户多变的需求。
]]></description>
			<content:encoded><![CDATA[<p>在前面到系列文章中，笔者只给了Native Quick Widget二星的评价，现在看来，这是一个非常肤浅的认识，在没有深入源码和具体功能到前提下，仅仅依靠界面来判断是非常愚蠢到行为。<br />
这也提示了笔者，每个开源项目都有存在都有它到可取之处，由于开源者无私到分享，才能铸就出更好的软件，提供更好到代码逻辑。<br />
这套Native Quick Widgets也是，它的存在价值并不是提供了美仑美焕的界面，而是提供了在目前到QtQuick中缺失的几个重要功能。<br />
这几个功能作为触摸屏的移动设备开发来说，并没有非存在不可的的价值，但是一旦将QML应用于桌面开发，就显示出巨大的影响。<br />
很显然，Native Quick Widgets的作者应该是使用QML进行了桌面软件开发或者在这方面的尝试，因此意识到了这方面的不足，才有这套组件的出现。<br />
首先对这套QML组件进行最基本的分析，通过阅读源码发现，它提供了7个自定义<strong>QML元素</strong>：<br />
1.Button元素<br />
2.CheckBox元素<br />
3.CursorArea元素<br />
4.LineEdit元素<br />
5.MenuAction元素<br />
6.Menu元素<br />
7.ProgressBar元素<br />
8.ScrollBar元素</p>
<p>除了这些元素，还提供了7个<strong>QML组件</strong>：<br />
1.Button.qml<br />
2.ContextMenu.qml<br />
3.ProgressBar.qml<br />
4.ScrollBar.qml<br />
5.CheckBox.qml<br />
6.LineEdit.qml<br />
7.ScrollArea.qml</p>
<p>逐一对这些进行分析，就可以发现这些组件提供的功能对于进行桌面开发的重要意义，从上面列出的QML组件和QML元素可以抽取出这些功能点：<br />
1.最基本的按钮，用于用户的事件触发<br />
2.输入编辑框，用于用户的输入<br />
3.进度条，用户显示一个事件的处理进度<br />
4.菜单和菜单动作，用于区域的用户事件触发<br />
5.滚动条和滚动区域，用于查看可视范围外的界面<br />
6.鼠标显示区域，用于改变鼠标显示的形状</p>
<p><span id="more-2133"></span><br />
前三个功能点，并不是特别需要或者重要，因为使用原生的QML也能完成这些功能点，并且能够编写出非常绚丽的效果，但是下面三点就不同了。<br />
首先应该明白QML及QtQuick这门技术的适用范围，这是与传统UI不同的模式，并且设计之初更像是应用于触摸屏等移动设备，而不是桌面应用。针对这三个功能点来比较下移动设备和桌面开发的差异。<br />
菜单功能在两者之间的差异：<br />
1.桌面上菜单必不可少，右键菜单，或者是依附按钮的菜单，都是提供用户进行操作的捷径，并且，菜单往往是多级的，二三级，甚至四级菜单都会存在，而触摸屏设备内，由于屏幕尺寸的限制，往往多是一级菜单或者是没有菜单，基本多由按钮来完成必要的事件触发；<br />
2.在桌面上，鼠标有右键可以触发菜单，在触摸屏上，操作就是点击或者放开，这是菜单非必需的重要理由，哪怕是多点触摸，既然可以多点触摸了，那为什么还需要菜单还进行事件触发呢，手势操作会显得更加便捷；<br />
从这两点就已经可以看出两者的重大差异，更为重要的是，针对QML本身来说，由于采取的是以图元为基础的DirectUI，虽然可以实现自我绘制菜单，但是对于紧张的开发周期来说，这些实现的时间无疑是挥霍。</p>
<p>滚动功能在两者之间的差异：<br />
这也是桌面上必备的功能，触摸屏设备也同样具有，但是同样受限于触摸屏设备的尺寸，用户不可能把手点在微小的滚动条上滚动，而是在滚动区域，这点在ipad上的操作就可以体现出来。可是同样的操作拿到桌面上，虽然有惯性滚动，但是这样的操作是现在的桌面用户无论如何都接受不了的；<br />
QML的基本元素中提供了滚动，但是它不适用于传统的桌面表现形式，虽然有，但是直接应用的话，对于还在鼠标时代的桌面来说，反而提供了很差的用户体验。</p>
<p>最后是鼠标区域的差异：<br />
在桌面上，由于操作的不同，鼠标会变换形状，提示用户当前操作的状态，可是在触摸屏设备上，就是画蛇添足了，这是非常细节的地方，但是越细节的地方才能更加体会出编写桌面软件和移动设备软件的不同。</p>
<p>通过这些简单的分析，就应该认识到Native Quick Widgets的意义，虽然只是简单地引用了Qt原生部件，但是这个实现帮助使用QML开发人员省去了自己实现这些功能点的过程，节省了宝贵的开发时间。<br />
再次表达出对开源者的尊敬，正是接近无限的开源的代码，才铸就了ios，android，meego，如果没有开源，这些为人们生活提供巨大帮助和快乐的系统将不会出现。<br />
同时也有由于Qt的存在，我们节省了造轮子的过程，才能快速地编写出软件，满足用户多变的需求。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2133</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>转载：Qt Lighthouse &amp; Wayland</title>
		<link>http://www.cuteqt.com/blog/?p=2125</link>
		<comments>http://www.cuteqt.com/blog/?p=2125#comments</comments>
		<pubDate>Fri, 01 Apr 2011 11:04:33 +0000</pubDate>
		<dc:creator>shiroki</dc:creator>
				<category><![CDATA[Linux技术]]></category>
		<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[embedded]]></category>
		<category><![CDATA[Lighthouse]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2125</guid>
		<description><![CDATA[原文: Qt Lighthouse &#38; Wayland Posted on 2011/03/23 by csslayer
Lighthouse是QtGui的一个Window System Agnostic移植（使得QtGui不了解它在什么窗口系统上运行，把处理逻辑交给了Lighthouse的插件）。
Lighthouse 直到前段时间还没有的一个特性是它没有提供在服务器和客户端同时运行Qt时的多进程的解决方案，这对于嵌入式设备是很重要的。虽然现在Qt当中有 QWS（开发嵌入式Qt程序时使用的一个窗口系统，类似X  Windows的C/S结构，从而保证Qt程序的的可移植性）。但是QWS并不是一个正式的协议，从而使得QWS的服务器和客户端是紧密耦合的。
因此如果有一个现成的协议可以利用的话，就会省下Qt开发者的不少功夫，然后他们最终发现Wayland（严格说来Wayland也是一个协议）正是他们所需要的。
在过去的几个月里Qt的几名开发者都在研究Wayland，然后他创建了一个新的实验室项目Qt-Compositor，这个项目的目标是作为一个基础层让其他人完成他们自己的Wayland compositor。Qt-Compositor抽象了所有Wayland Compositor所需要的通信。
其实我想很多人关心的重点其实就是Qt现在也有一个可以demo下的Wayland支持啦。虽然开发者们更多提到的是嵌入式系统，大概也就是想让Lighthouse替代以前的QWS，Wayland在Qt嵌入式的下一步也有着重要的作用。
Lighthouse在去年10月底的时候决定和Qt的master合并，评论里面不少人其实在催xcb支持（X的c语言绑定），后面也回复有xcb现在也正在开发中。lighthouse看来将成为Qt的移植性/跨平台的下一步。


来源：
http://labs.qt.nokia.com/2011/03/18/multi-process-lighthouse/
关于wayland的介绍，我就扔两篇tualatriX的blog了做参考了：
http://imtx.me/archives/1573.html
http://imtx.me/archives/1574.html
]]></description>
			<content:encoded><![CDATA[<p>原文:<a href="http://www.ikde.org/offtopic/qt-lighthouse-wayland/"> Qt Lighthouse &amp; Wayland</a> Posted on <a title="12:33 am" rel="bookmark" href="http://www.ikde.org/offtopic/qt-lighthouse-wayland/">2011/03/23</a> by <a title="View all posts by csslayer" href="http://www.ikde.org/author/csslayer/">csslayer</a></p>
<p><a title="View all posts by csslayer" href="http://www.ikde.org/author/csslayer/"></a>Lighthouse是QtGui的一个Window System Agnostic移植（使得QtGui不了解它在什么窗口系统上运行，把处理逻辑交给了Lighthouse的插件）。</p>
<p>Lighthouse 直到前段时间还没有的一个特性是它没有提供在服务器和客户端同时运行Qt时的多进程的解决方案，这对于嵌入式设备是很重要的。虽然现在Qt当中有 QWS（开发嵌入式Qt程序时使用的一个窗口系统，类似X  Windows的C/S结构，从而保证Qt程序的的可移植性）。但是QWS并不是一个正式的协议，从而使得QWS的服务器和客户端是紧密耦合的。</p>
<p>因此如果有一个现成的协议可以利用的话，就会省下Qt开发者的不少功夫，然后他们最终发现Wayland（严格说来Wayland也是一个协议）正是他们所需要的。</p>
<p>在过去的几个月里Qt的几名开发者都在研究Wayland，然后他创建了一个新的实验室项目<a href="http://qt.gitorious.org/qt-labs/qt-compositor">Qt-Compositor</a>，这个项目的目标是作为一个基础层让其他人完成他们自己的Wayland compositor。Qt-Compositor抽象了所有Wayland Compositor所需要的通信。</p>
<p>其实我想很多人关心的重点其实就是Qt现在也有一个可以demo下的Wayland支持啦。虽然开发者们更多提到的是嵌入式系统，大概也就是想让Lighthouse替代以前的QWS，Wayland在Qt嵌入式的下一步也有着重要的作用。</p>
<p>Lighthouse在<a href="http://labs.qt.nokia.com/2010/10/29/lighthouse-is-integrated/">去年10月底</a>的时候决定和Qt的master合并，评论里面不少人其实在催xcb支持（X的c语言绑定），后面也回复有xcb现在也正在开发中。lighthouse看来将成为Qt的移植性/跨平台的下一步。</p>
<p><img id="ncode_imageresizer_container_1" title="Click to enlarge it" src="http://nhsdbw.blu.livefilestore.com/y1przqt8dbezoisnzEQ-iIM3aRHcYO8MSkvbiDFunB-M89cvHAjarxtMZX32TkHyELlE0WAHRNktBFMjV_3XkAtNr4WFKFfoeFj/Qt-Compositor.png?psid=1" alt="" width="576" height="668" /></p>
<p><img id="ncode_imageresizer_container_2" title="Click to enlarge it" src="http://nhsdbw.blu.livefilestore.com/y1pS5_6sbD8QqAQ8UzI8KvYosS_yngnXd3bwlJGuwlR6haTz5NvI8EdpiqVlW3DE1rM4twj5Q8DMXx2lVYroVd7PVC3xCtd795I/waylandscreenshot.png?psid=1" alt="" width="563" height="441" /></p>
<p>来源：</p>
<p><a href="http://labs.qt.nokia.com/2011/03/18/multi-process-lighthouse/">http://labs.qt.nokia.com/2011/03/18/multi-process-lighthouse/</a></p>
<p>关于wayland的介绍，我就扔两篇tualatriX的blog了做参考了：</p>
<p><a href="http://imtx.me/archives/1573.html">http://imtx.me/archives/1573.html</a></p>
<p><a href="http://imtx.me/archives/1574.html">http://imtx.me/archives/1574.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2125</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qt全局热键(windows篇)</title>
		<link>http://www.cuteqt.com/blog/?p=2088</link>
		<comments>http://www.cuteqt.com/blog/?p=2088#comments</comments>
		<pubDate>Mon, 21 Mar 2011 12:36:10 +0000</pubDate>
		<dc:creator>red</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Qt技术]]></category>
		<category><![CDATA[Windows技术]]></category>
		<category><![CDATA[global hotkey]]></category>
		<category><![CDATA[hotkey]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[全局热键]]></category>
		<category><![CDATA[热键]]></category>

		<guid isPermaLink="false">http://www.cuteqt.com/blog/?p=2088</guid>
		<description><![CDATA[Qt对于系统底层，一直没有很好的支持，例如串口并口通信，还有我们经常都会用到的全局热键，等等。既然Qt可能出于某种原因，不对这些进行支持，我们就只能自己写代码，调用系统相关的API了。
注意，这个是Windows篇，就说明这些代码只支持windows系统。同时，也说明肯定还有其他平台的要写。不过要等O(∩_∩)O~
在Qt要调用Windows的API其实很简单，只要在需要用到的头文件中添加#include &#60;windows.h&#62;即可。不过要注意，Qt仅支持win32的API，像MFC之类的是不支持的。
想要在Qt里使用全局热键，最好的办法是重载QApplication里的winEventFilter函数。这个函数是用来响应Windows系统信息的。其函数原型为virtual bool winEventFilter(MSG *msg, long *result)。当msg指针中的message（MSG结构中的一个元素）为WM_HOTKEY类型时，就是用户激发了热键。整个过程和在VC的消息响应机制很类似，只不过换成了Qt而已。
而如果我们想要添加自己的全局热键，只需要使用RegisterHotKey函数即可。其函数原型为：
BOOL RegisterHotKey( HWND hWnd,     int id,     UINT fsModifiers,     UINT vk );
HWND类型是Windows中的窗口句柄类型，在Qt中，QWidget及其子类均可使用winId()函数得到。
第二个参数，是一个原子操作类型，用ATOM GlobalAddAtom(LPCTSTR lpString )函数得到。这也是一个Win32API，根据一个string参数可以得到一个唯一的值。使用完之后，必须使用GlobalDeleteAtom函数删除掉整个ATOM。其函数原型为ATOM GlobalDeleteAtom( ATOM nAtom )。
后面两个参数，一个是修饰键，一个是普通按键。例如，假设我们想注册Ctrl+F4这个热键组合，则fsModifiers就是MOD_CONTROL，而vk就是VK_F4。
如果注册成功,就返回true，否则,返回false。
注意，使用完之后，要使用UnregisterHotKey函数注销，否则你可能再也无法注册这个热键了！除非重启。其函数原型为：BOOL UnregisterHotKey(HWND hWnd,      int id )。
ok，热键注册就完成了。当按下热键后，我们就会在QApplication里的winEventFilter函数中收到一个msg。这个msg，前面也说过，我们需要知道它的一个元素message是不是WM_HOTKEY。如果是，就证明我们收到了Windows系统的热键信息。在MSG结构中，我们可能还需要理解的元素有两个，分别是wParam和lParam。wParam是注册热键时所用的id，也就是ATOM（原子)。而lParam就是我们的热键了。其实际上是一个32位的类型，前面16位代表普通按键，后16位代表的是修饰键。
至此，Qt在Windows下使用全局热键就完成了。如果有兴趣的朋友，还可以自己尝试一下，修改或直接自己写一份代码。
如有错误，敬请指正。
我把我写的测试代码放到CuteQt论坛，有兴趣的朋友可以去下载。
http://cuteqt.org/bbs/viewthread.php?tid=1641&#38;extra=page%3D1
]]></description>
			<content:encoded><![CDATA[<p>Qt对于系统底层，一直没有很好的支持，例如串口并口通信，还有我们经常都会用到的全局热键，等等。既然Qt可能出于某种原因，不对这些进行支持，我们就只能自己写代码，调用系统相关的API了。</p>
<p>注意，这个是Windows篇，就说明<span style="color: #0000ff;">这些代码只支持windows系统</span>。同时，也说明肯定还有其他平台的要写。不过要等O(∩_∩)O~</p>
<p>在Qt要调用Windows的API其实很简单，只要在需要用到的头文件中添加#include &lt;windows.h&gt;即可。不过要注意，Qt仅支持win32的API，像MFC之类的是不支持的。</p>
<p>想要在Qt里使用全局热键，最好的办法是重载QApplication里的winEventFilter函数。这个函数是用来响应Windows系统信息的。其函数原型为virtual bool winEventFilter(MSG *msg, long *result)。当msg指针中的message（MSG结构中的一个元素）为WM_HOTKEY类型时，就是用户激发了热键。整个过程和在VC的消息响应机制很类似，只不过换成了Qt而已。</p>
<p>而如果我们想要添加自己的全局热键，只需要使用RegisterHotKey函数即可。其函数原型为：</p>
<p><span style="color: #000000;">BOOL </span><span style="color: #000000;">RegisterHotKey</span><span style="color: #000000;">( HWND <em>hWnd</em>,     int <em>id</em>,     UINT <em>fsModifiers</em>,     UINT <em>vk</em> );</span></p>
<p><span style="color: #0000ff;">HWND类型是Windows中的窗口句柄类型，在Qt中，QWidget及其子类均可使用winId()函数得到。</span></p>
<p>第二个参数，是一个原子操作类型，用<span style="color: #000000;">ATOM </span><span style="color: #000000;">GlobalAddAtom</span><span style="color: #000000;">(LPCTSTR <em>lpString</em> )函数得到。这也是一个Win32API，根据一个string参数可以得到一个唯一的值。使用完之后，必须使用</span>GlobalDeleteAtom函数删除掉整个ATOM。其函数原型为<span style="color: #000000;">ATOM </span><span style="color: #000000;">GlobalDeleteAtom</span><span style="color: #000000;">( ATOM <em>nAtom</em> )。</span></p>
<p><span style="color: #000000;">后面两个参数，一个是修饰键，一个是普通按键。例如，假设我们想注册Ctrl+F4这个热键组合，则fsModifiers就是MOD_CONTROL，而vk就是VK_F4。</span></p>
<p><span style="color: #000000;">如果注册成功,就返回true，否则,返回false。</span></p>
<p><span style="color: #0000ff;">注意，使用完之后，要使用UnregisterHotKey函数注销，否则你可能再也无法注册这个热键了！除非重启。</span>其函数原型为：BOOL UnregisterHotKey(HWND <em>hWnd</em>,      int <em>id</em> )。</p>
<p>ok，热键注册就完成了。当按下热键后，我们就会在QApplication里的winEventFilter函数中收到一个msg。这个msg，前面也说过，我们需要知道它的一个元素message是不是WM_HOTKEY。如果是，就证明我们收到了Windows系统的热键信息。在MSG结构中，我们可能还需要理解的元素有两个，分别是wParam和lParam。wParam是注册热键时所用的id，也就是ATOM（原子)。而lParam就是我们的热键了。其实际上是一个32位的类型，前面16位代表普通按键，后16位代表的是修饰键。</p>
<p>至此，Qt在Windows下使用全局热键就完成了。如果有兴趣的朋友，还可以自己尝试一下，修改或直接自己写一份代码。</p>
<p><span style="color: #0000ff;"><strong>如有错误，敬请指正。</strong></span></p>
<p>我把我写的测试代码放到CuteQt论坛，有兴趣的朋友可以去下载。</p>
<p><a title="下载地址" href="http://cuteqt.org/bbs/viewthread.php?tid=1641&amp;extra=page%3D1" target="_blank">http://cuteqt.org/bbs/viewthread.php?tid=1641&amp;extra=page%3D1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cuteqt.com/blog/?feed=rss2&amp;p=2088</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

