﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-清源游民的网络笔记本-随笔分类-Qt</title><link>http://www.cppblog.com/yuanyajie/category/3943.html</link><description>记录所思所想，收藏所见所闻�?
</description><language>zh-cn</language><lastBuildDate>Tue, 20 May 2008 02:51:40 GMT</lastBuildDate><pubDate>Tue, 20 May 2008 02:51:40 GMT</pubDate><ttl>60</ttl><item><title>还是关QSettings的，把我的问题重复一下</title><link>http://www.cppblog.com/yuanyajie/archive/2007/10/26/35276.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Fri, 26 Oct 2007 15:48:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/10/26/35276.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/35276.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/10/26/35276.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/35276.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/35276.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/10/26/35276.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/35276.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-10-26 23:48 <a href="http://www.cppblog.com/yuanyajie/archive/2007/10/26/35276.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Qt的进来帮忙解决下有关QSettings中写入中文的问题</title><link>http://www.cppblog.com/yuanyajie/archive/2007/10/26/35188.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Thu, 25 Oct 2007 19:16:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/10/26/35188.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/35188.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/10/26/35188.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/35188.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/35188.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/10/26/35188.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/35188.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-10-26 03:16 <a href="http://www.cppblog.com/yuanyajie/archive/2007/10/26/35188.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Connecting Signals to QtScript Functions(转)</title><link>http://www.cppblog.com/yuanyajie/archive/2007/10/07/33666.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Sat, 06 Oct 2007 16:20:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/10/07/33666.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/33666.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/10/07/33666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/33666.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/33666.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/10/07/33666.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/33666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-10-07 00:20 <a href="http://www.cppblog.com/yuanyajie/archive/2007/10/07/33666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Say hello to QtScript!(转)</title><link>http://www.cppblog.com/yuanyajie/archive/2007/10/07/33665.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Sat, 06 Oct 2007 16:17:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/10/07/33665.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/33665.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/10/07/33665.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/33665.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/33665.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/10/07/33665.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/33665.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-10-07 00:17 <a href="http://www.cppblog.com/yuanyajie/archive/2007/10/07/33665.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QT的Graphics View柜架(3/3) </title><link>http://www.cppblog.com/yuanyajie/archive/2007/09/27/32962.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Wed, 26 Sep 2007 16:09:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/09/27/32962.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/32962.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/09/27/32962.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/32962.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/32962.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/09/27/32962.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/32962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-09-27 00:09 <a href="http://www.cppblog.com/yuanyajie/archive/2007/09/27/32962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QT的Graphics View柜架(2/3) </title><link>http://www.cppblog.com/yuanyajie/archive/2007/09/26/32961.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Wed, 26 Sep 2007 15:57:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/09/26/32961.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/32961.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/09/26/32961.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/32961.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/32961.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/09/26/32961.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/32961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-09-26 23:57 <a href="http://www.cppblog.com/yuanyajie/archive/2007/09/26/32961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QT的Graphics View柜架(1/3)</title><link>http://www.cppblog.com/yuanyajie/archive/2007/09/26/32960.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Wed, 26 Sep 2007 15:49:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/09/26/32960.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/32960.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/09/26/32960.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/32960.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/32960.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/09/26/32960.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/32960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-09-26 23:49 <a href="http://www.cppblog.com/yuanyajie/archive/2007/09/26/32960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QT中的对象树与对象拥有权</title><link>http://www.cppblog.com/yuanyajie/archive/2007/09/25/32854.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Tue, 25 Sep 2007 12:36:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/09/25/32854.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/32854.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/09/25/32854.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/32854.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/32854.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/09/25/32854.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/32854.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-09-25 20:36 <a href="http://www.cppblog.com/yuanyajie/archive/2007/09/25/32854.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我的QT笔记打包下载</title><link>http://www.cppblog.com/yuanyajie/archive/2007/09/24/32795.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Mon, 24 Sep 2007 09:59:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/09/24/32795.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/32795.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/09/24/32795.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/32795.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/32795.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/09/24/32795.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/32795.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-09-24 17:59 <a href="http://www.cppblog.com/yuanyajie/archive/2007/09/24/32795.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt 中的多线程(二)</title><link>http://www.cppblog.com/yuanyajie/archive/2007/08/22/30610.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Wed, 22 Aug 2007 09:24:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/08/22/30610.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/30610.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/08/22/30610.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/30610.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/30610.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/08/22/30610.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/30610.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-08-22 17:24 <a href="http://www.cppblog.com/yuanyajie/archive/2007/08/22/30610.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt 中的多线程(一)</title><link>http://www.cppblog.com/yuanyajie/archive/2007/08/22/30599.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Wed, 22 Aug 2007 08:48:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/08/22/30599.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/30599.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/08/22/30599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/30599.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/30599.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/08/22/30599.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/30599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-08-22 16:48 <a href="http://www.cppblog.com/yuanyajie/archive/2007/08/22/30599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>试用QT中的多语言翻译</title><link>http://www.cppblog.com/yuanyajie/archive/2007/08/03/29258.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Fri, 03 Aug 2007 02:44:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/08/03/29258.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/29258.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/08/03/29258.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/29258.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/29258.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/08/03/29258.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/29258.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-08-03 10:44 <a href="http://www.cppblog.com/yuanyajie/archive/2007/08/03/29258.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Model/View 学习笔记 (七) </title><link>http://www.cppblog.com/yuanyajie/archive/2007/06/19/26641.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Tue, 19 Jun 2007 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/06/19/26641.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/26641.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/06/19/26641.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/26641.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/26641.html</trackback:ping><description><![CDATA[<p>清源游民 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#103;&#97;&#109;&#101;&#111;&#103;&#114;&#101;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">gameogre@gmail.com</a></p>
<p><span style="FONT-SIZE: 18pt"><em>Delegate&nbsp; 类<br></em></span><br><span style="COLOR: #0000ff"><strong>概念</strong></span></p>
<p>与MVC模式不同，model/view结构没有用于与用户交互的完全独立的组件。一般来讲， view负责把数据展示<br>给用户，也处理用户的输入。为了获得更多的灵性性，交互通过delegagte执行。它既提供输入功能又负责渲染view中的每个数据项。 控制delegates的标准接口在<span style="COLOR: #0000ff">QAbstractItemDelegate</span>类中定义。Delegates通过实现<span style="COLOR: #ff00ff">paint</span>()和<span style="COLOR: #ff00ff">sizeHint</span>()以达到渲染内容的目的。然而，简单的基于widget的delegates,可以从<span style="COLOR: #0000ff">QItemDelegate</span>子类化，而不是<span style="COLOR: #0000ff">QAbstractItemDelegate</span>,这样可以使用它提供的上述函数的缺省实现。delegate可以使用widget来处理编辑过程，也可以直接对事件进行处理。</p>
<p><strong style="COLOR: #0000ff">使用现成的delegate<br></strong>Qt提供的标准views都使用<span style="COLOR: #0000ff">QItemDelegate</span>的实例来提供编辑功能。它以普通的风格来为每个标准view渲染数据项。这些标准的views包括：<span style="COLOR: #0000ff">QListView</span>,<span style="COLOR: #0000ff">QTableView</span>,<span style="COLOR: #0000ff">QTreeView</span>。所有标准的角色都通过标准views包含的缺省delegate进行处理。一个view使用的delegate可以用<span style="COLOR: #ff00ff">itemDelegate</span>()函数取得,而<span style="COLOR: #ff00ff">setItemDelegate</span>()&nbsp;函数可以安装一个定制delegate。</p>
<p><br><strong style="COLOR: #0000ff">一个简单的delegate<br></strong>这个delegate使用<span style="COLOR: #0000ff">QSpinBox</span>来提供编辑功能。它主要想用于显示整数的models上。尽管我们已经建立了一个基于整数的table model,但我们也可以使用<span style="COLOR: #0000ff">QStandardItemModel</span>，因为delegate可以控制数据的录入。我们又建了一个table view来显示model的内容，用我们定制的delegate来编辑。<br><img height=182 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/o_spinboxdelegate-example.png" width=234 border=0><br>我们从<span style="COLOR: #0000ff">QItemDelegate</span>子类化，这样可以利用它缺省实现的显示功能。当然我们必需提供函数来管理用于编辑的widget:<br>class <span style="COLOR: #0000ff">SpinBoxDelegate</span> : public <span style="COLOR: #0000ff">QItemDelegate</span><br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; Q_OBJECT</p>
<p>&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp; SpinBoxDelegate(QObject *parent = 0);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QWidget</span> *<span style="COLOR: #ff00ff">createEditor</span>(<span style="COLOR: #0000ff">QWidget</span> *parent, const <span style="COLOR: #0000ff">QStyleOptionViewItem</span> &amp;option,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QModelIndex</span> &amp;index) const;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; void <span style="COLOR: #ff00ff">setEditorData</span>(<span style="COLOR: #0000ff">QWidget</span> *editor, const <span style="COLOR: #0000ff">QModelIndex</span> &amp;index) const;<br>&nbsp;&nbsp;&nbsp;&nbsp; void <span style="COLOR: #ff00ff">setModelData</span>(<span style="COLOR: #0000ff">QWidget</span> *editor, <span style="COLOR: #0000ff">QAbstractItemModel</span> *model,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QModelIndex</span> &amp;index) const;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; void <span style="COLOR: #ff00ff">updateEditorGeometry</span>(<span style="COLOR: #0000ff">QWidget</span> *editor,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QStyleOptionViewItem</span> &amp;option, const <span style="COLOR: #0000ff">QModelIndex</span> &amp;index) const;<br>&nbsp;};<br>需要注意的是,当一个delegate创建时，不需要安装一个widget，只有在真正需要时才创建这个用于编辑的widget。<br><br><span style="COLOR: #0000ff"><strong>提供编辑器</strong></span><br>在这个例子中，当table view需要提供一个编辑器时，它要求delegate提供一个可用于编辑的widget,它应该适用于当前正被修改的数据项。这正是<span style="COLOR: #ff00ff">createEditor</span>()函数应该实现的：<br>QWidget *SpinBoxDelegate::<span style="COLOR: #ff00ff">createEditor</span>(<span style="COLOR: #0000ff">QWidget</span> *parent,<br>&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QStyleOptionViewItem</span> &amp;/* option */,<br>&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QModelIndex</span> &amp;/* index */) const<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QSpinBox</span> *editor = new QSpinBox(parent);<br>&nbsp;&nbsp;&nbsp;&nbsp; editor-&gt;setMinimum(0);<br>&nbsp;&nbsp;&nbsp;&nbsp; editor-&gt;setMaximum(100);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">return</span> editor;<br>&nbsp;}<br>我们不需要跟踪这个widget的指针，因为view会在不需要时销毁这个widget。我们也给编辑安装了delegate缺省的事件过滤器，这提供了用户期望的标准编辑快捷键。view通过我们定义相应的函数来保证编辑器的数据与几何布局被正确的设置。我们也可以根据不同的model index来创建不同的编辑器，比如，我们有一列整数，一列字符串，我们可以根据哪种列被编辑来创建一个QSpinBox或是QLineEdit。delegate必需提供一个函数把model中的数据拷贝到编辑器中。<br>void SpinBoxDelegate::<span style="COLOR: #ff00ff">setEditorData</span>(<span style="COLOR: #0000ff">QWidget</span> *editor,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QModelIndex</span> &amp;index) const<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; int value = index.model()-&gt;<span style="COLOR: #ff00ff">data</span>(index, Qt::DisplayRole).toInt();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QSpinBox</span> *spinBox = static_cast&lt;QSpinBox*&gt;(editor);<br>&nbsp;&nbsp;&nbsp;&nbsp; spinBox-&gt;<span style="COLOR: #ff00ff">setValue</span>(value);<br>&nbsp;}<br><br><span style="COLOR: #0000ff"><strong>向model提交数据<br></strong></span>这需要我们实现另外一个函数<span style="COLOR: #ff00ff">setModelData</span>():</p>
<p>void SpinBoxDelegate::<span style="COLOR: #ff00ff">setModelData</span>(<span style="COLOR: #0000ff">QWidget</span> *editor, <span style="COLOR: #0000ff">QAbstractItemModel</span> *model,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QModelIndex</span> &amp;index) const<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QSpinBox</span> *spinBox = static_cast&lt;QSpinBox*&gt;(editor);<br>&nbsp;&nbsp;&nbsp;&nbsp; spinBox-&gt;<span style="COLOR: #ff00ff">interpretText</span>();<br>&nbsp;&nbsp;&nbsp;&nbsp; int value = spinBox-&gt;<span style="COLOR: #ff00ff">value</span>();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; model-&gt;<span style="COLOR: #ff00ff">setData</span>(index, value);<br>&nbsp;}</p>
<p>标准的QItemDelegate类当它完成编辑时会发射closeEditor()信号来通知view。view保证编辑器widget关闭与销毁。本例中我们只提供简单的编辑功能，因此不需要发送个信号。</p>
<p><strong style="COLOR: #0000ff">更新编辑器几何布局</strong></p>
<p>delegate负责管理编辑器的几何布局。这些几何布局信息在编辑创建时或view的尺寸位置发生改变时，<br>都应当被提供。幸运的是，view通过一个view option可以提供这些必要的信息。<br>&nbsp;void <span style="COLOR: #0000ff">SpinBoxDelegate</span>::<span style="COLOR: #ff00ff">updateEditorGeometry</span>(<span style="COLOR: #0000ff">QWidget</span> *editor,<br>&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QStyleOptionViewItem</span> &amp;option, const <span style="COLOR: #0000ff">QModelIndex</span> &amp;/* index */) const<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; editor-&gt;<span style="COLOR: #ff00ff">setGeometry</span>(option.rect);<br>&nbsp;}<br><br><strong style="COLOR: #0000ff">编辑提示</strong><br>编辑完成后，delegate会给别的组件提供有关于编辑处理结果的提示，也提供用于后续编辑操作的一些提示。<br>这可以通过发射带有某种hint的<span style="COLOR: #ff00ff">closeEditor</span>()信号完成。这些信号会被安装在spin box上的缺省的QItemDelegate事件过滤器捕获。对这个缺省的事件过滤来讲，当用户按下回车键，delegate会对model中的数据进行提交，并关闭spin box。<br>我们可以安装自己的事件过滤器以迎合我们的需要，例如，我们可以发射带有Edit<span style="COLOR: #ff00ff">NextItem hint</span>的<br>closeEditor()信号来实现自动开始编辑view中的下一项。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/26641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-06-19 17:37 <a href="http://www.cppblog.com/yuanyajie/archive/2007/06/19/26641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Model/View 学习笔记 (六) </title><link>http://www.cppblog.com/yuanyajie/archive/2007/06/19/26622.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Tue, 19 Jun 2007 06:29:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/06/19/26622.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/26622.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/06/19/26622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/26622.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/26622.html</trackback:ping><description><![CDATA[<p>清源游民 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#103;&#97;&#109;&#101;&#111;&#103;&#114;&#101;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">gameogre@gmail.com</a><br><br><span style="FONT-SIZE: 18pt"><em>在views中选择数据项</em></span></p>
<p><span style="COLOR: #0000ff"><strong>概念</strong></span></p>
<p>用于新的view类中的选择模型比Qt3中的模型有了很大的改进。它为基于model/view架构的选择提供了更为全面的描述。尽管对提供了的views来说，负责操纵选择的标准类已经足以应付，但是你也可以创建特定的选择模型来满足你特殊的需求。<br>关于在view被选择的数据项的信息保持在<span style="COLOR: #0000ff">QItemSelectionModel</span>类的实例中。它也为每个独立的model中的数据项维护model indexes信息，与任何views都关联关系。既然一个model可用于多个views,那么在多个views之间共享选择信息也是可以做到的，这使得多个views可以以一致的方式进行显示。<br>选择由多个选择范围组成。通过仅仅记录开始model indexes与结束model indexes，最大化地记录了可以选择的范围。非连续选择数据项由多个选择范围来描述。选择模型记录model indexes的集合来描述一个选择。最近选择的数据项被称为<span style="COLOR: #0000ff">current</span> <span style="COLOR: #0000ff">selection</span>。应用程序可以通过使用某种类型的选择命令来修改选择的效果。<br>在进行选择操作时，可以把<span style="COLOR: #0000ff">QItemSelectionModel</span>看成是model中所有数据项选择状态的一个记录。一旦建立一个选择模型，所有项的集合都可以选择，撤消选择，或者选择状态进行切换而不需要知道哪个数据项是否已经被选择过。所有被选择的项的indexes在任何时候都可以得到，通过信号槽机制可以通知别的组件发生的变化。<br><br><strong style="COLOR: #0000ff">使用选择模型<br></strong>标准view类提供了缺省的选择模型，它们可以在大次数程序中使用。一个view中的选择模型可以通过调用view的函数<span style="COLOR: #ff00ff">selectionModel</span>()取得，也可以通过<span style="COLOR: #ff00ff">setSelectionModel</span>()在多个views之间共享选择模型，因此总的来说构建一个新的模型一般情况不太必要。<br>通过给<span style="COLOR: #0000ff">QItemSelection</span>指定一个model,一对model indexes，可以创建一个选择。indexes的用法依赖于给定的model,这两个indexes被解释成选择的区块中的左上角项和右下角项。model中的项的选择服从于选择模型。<br><br><span style="COLOR: #0000ff">选择项</span><br>构建一个table model ，它有32个项，用一个table view进行显示：<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">TableModel</span> *model = new TableModel(8, 4, &amp;app);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QTableView</span> *table = new QTableView(0);<br>&nbsp;&nbsp;&nbsp;&nbsp; table-&gt;<span style="COLOR: #ff00ff">setModel</span>(model);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QItemSelectionModel</span> *selectionModel = table-&gt;<span style="COLOR: #ff00ff">selectionModel</span>();<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndex</span> topLeft;<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndex</span> bottomRight;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; topLeft = model-&gt;index(0, 0, QModelIndex());<br>&nbsp;&nbsp;&nbsp;&nbsp; bottomRight = model-&gt;index(5, 2, QModelIndex());<br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QItemSelection</span> selection(topLeft, bottomRight);<br>&nbsp;&nbsp;&nbsp;&nbsp; selectionModel-&gt;<span style="COLOR: #ff00ff">select</span>(selection, QItemSelectionModel::<span style="COLOR: #ff00ff">Select</span>);<br>结果如下：<br><img height=244 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/o_selected-items-i001.png" width=374 border=0><br><br><span style="COLOR: #0000ff">读取选择状态</span> <br>存储在选择模型中indexes可以用selectionIndexes()函数来读取。它返回一个未排序的model indexes列表，我们可以遍历它，如果我们知道他们关联于哪个model的话。<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndexList</span> indexes = selectionModel-&gt;<span style="COLOR: #ff00ff">selectedIndexes</span>();<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndex</span> index;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">foreach</span>(index, indexes) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; model-&gt;setData(index, text);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>选择模型在选择发生变化时会发出信号。这用于通知别的组件包括整体与当前焦点项所发生的变化。我们可以连接selectionChanged()信号到一个槽，检查当信号产生时哪些项被选择或被取消选择。这个槽被调用时带有两个参数，它们都是<span style="COLOR: #0000ff">QItemSelection</span>对象，一个包含新被选择的项，另一个包含新近被取消选择的项。下面的代码演示了给新选择的项添加数据内容，新近被取消选择的项的内容被清空。<br>void MainWindow::<span style="COLOR: #ff00ff">updateSelection</span>(const <span style="COLOR: #0000ff">QItemSelection</span> &amp;<span style="COLOR: #ff00ff">selected</span>,<br>&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QItemSelection</span> &amp;<span style="COLOR: #ff00ff">deselected</span>)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndex</span> index;<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndexList</span> items = selected.<span style="COLOR: #ff00ff">indexes</span>();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">foreach</span> (index, items) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; model-&gt;setData(index, text);<br>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; items = deselected.<span style="COLOR: #ff00ff">indexes</span>();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">foreach</span> (index, items)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; model-&gt;setData(index, "");<br>&nbsp;}<br>也可以通过响应currentChanged()信号来跟踪当前焦点项.对应的槽就有两个接收参数，一个表示之前的焦点，另一个表示当前的焦点。<br>void MainWindow::<span style="COLOR: #ff00ff">changeCurrent</span>(const <span style="COLOR: #0000ff">QModelIndex</span> &amp;current,<br>&nbsp;&nbsp;&nbsp;&nbsp; const <span style="COLOR: #0000ff">QModelIndex</span> &amp;previous)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; statusBar()-&gt;showMessage(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tr("Moved from (%1,%2) to (%3,%4)")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .arg(previous.row()).arg(previous.column())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .arg(current.row()).arg(current.column()));<br>&nbsp;}</p>
<p><span style="COLOR: #0000ff">更新选择<br></span>选择指令是通过选择标志提供的，它被定义在QItemSelectionModel::SelectionFlag中。常用的有Select标记，Toggle标记，Deselect标记,Current标记，Clear标记，其意义一目了然。沿上面例子的结果执行以下代码：<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QItemSelection</span> toggleSelection;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; topLeft = model-&gt;index(2, 1, QModelIndex());<br>&nbsp;&nbsp;&nbsp;&nbsp; bottomRight = model-&gt;index(7, 3, QModelIndex());<br>&nbsp;&nbsp;&nbsp;&nbsp; toggleSelection.<span style="COLOR: #ff00ff">select</span>(topLeft, bottomRight);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; selectionModel-&gt;<span style="COLOR: #ff00ff">select</span>(toggleSelection, QItemSelectionModel::<span style="COLOR: #ff00ff">Toggle</span>);<br>结果如下:<br><img height=244 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/o_selected-items2-i002.png" width=374 border=0><br><br>缺省情况下，选择指令只针对单个项(由model indexes指定)。然而，选择指令可以通过与另外标记的结合来改变整行和整列。举例来说，假如你只使用一个index来调用select(),但是用Select标记与Rows标记的组合，那么包括那个项的整行都将被选择。看以下示例：<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QItemSelection</span> columnSelection;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; topLeft = model-&gt;index(0, 1, QModelIndex());<br>&nbsp;&nbsp;&nbsp;&nbsp; bottomRight = model-&gt;index(0, 2, QModelIndex());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; columnSelection.<span style="COLOR: #ff00ff">select</span>(topLeft, bottomRight);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; selectionModel-&gt;select(columnSelection,<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QItemSelectionModel</span>::Select | <span style="COLOR: #0000ff">QItemSelectionModel</span>::<span style="COLOR: #ff00ff">Columns</span>);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QItemSelection</span> rowSelection;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; topLeft = model-&gt;index(0, 0, QModelIndex());<br>&nbsp;&nbsp;&nbsp;&nbsp; bottomRight = model-&gt;index(1, 0, QModelIndex());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; rowSelection.<span style="COLOR: #ff00ff">select</span>(topLeft, bottomRight);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; selectionModel-&gt;select(rowSelection,<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QItemSelectionModel</span>::Select | <span style="COLOR: #0000ff">QItemSelectionModel</span>::<span style="COLOR: #ff00ff">Rows</span>);<br>结果如下<br><img height=244 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/o_selected-items3-i003.png" width=374 border=0><br><br><span style="COLOR: #0000ff">选择模型中所有项<br></span>为了选择model中的所有项，必须先得创建一个选择，它包括当前层次上的所有项:<br>&nbsp;&nbsp;&nbsp; &nbsp;<span style="COLOR: #0000ff">QModelIndex</span> topLeft = model-&gt;index(0, 0, parent);<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndex</span> bottomRight = model-&gt;<span style="COLOR: #ff00ff">index</span>(model-&gt;<span style="COLOR: #ff00ff">rowCount</span>(parent)-1,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; model-&gt;<span style="COLOR: #ff00ff">columnCount</span>(parent)-1, parent);<br><br>&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QItemSelection</span> selection(topLeft, bottomRight);<br>&nbsp;&nbsp;&nbsp;&nbsp; selectionModel-&gt;<span style="COLOR: #ff00ff">select</span>(selection, QItemSelectionModel::Select);<br>顶级index可以这样：<br>QModelIndex parent = <span style="COLOR: #ff00ff">QModelIndex</span>();<br>对具有层次结构的model来说，可以使用<span style="COLOR: #ff00ff">hasChildren</span>()函数来决定给定项是否是其它项的父项。<br></p>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/26622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-06-19 14:29 <a href="http://www.cppblog.com/yuanyajie/archive/2007/06/19/26622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Model/View 学习笔记 (五) </title><link>http://www.cppblog.com/yuanyajie/archive/2007/06/18/26568.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Mon, 18 Jun 2007 08:15:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/06/18/26568.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/26568.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/06/18/26568.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/26568.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/26568.html</trackback:ping><description><![CDATA[<p>清源游民 gameogre@gmail.com<br><br><span style="FONT-SIZE: 18pt"><em>View 类<br></em></span><br><span style="COLOR: #0000ff"><strong>概念</strong></span></p>
<p>在model/view架构中，view从model中获得数据项然后显示给用户。数据显示的方式不必与model提供的表示方式相同，可以与底层存储数据项的数据结构完全不同。<br>内容与显式的分离是通过由<span style="COLOR: #0000ff">QAbstractItemModel</span>提供的标准模型接口，由<span style="COLOR: #0000ff">QAsbstractItemview</span>提供的标准视图接口共同实现的。普遍使用model index来表示数据项。view负责管理从model中读取的数据的外观布局。<br>它们自己可以去渲染每个数据项，也可以利用delegate来既处理渲染又进行编辑。<br>除了显示数据，views也处理数据项的导航，参与有关于数据项选择的部分功能。view也实现一些基本的用户接口特性，如上下文菜单与拖拽功能。view也为数据项提供了缺省的编程功能，也可搭配delegate实现更为特殊的定制编辑的需求。<br>一个view创建时必不需要model,但在它能显示一些真正有用的信息之前，必须提供一个model。view通过使用<br><strong style="COLOR: #993366">selections</strong>来跟踪用户选择的数据项。每个view可以维护单独使用的selections，也可以在多个views之间共享。有些views,如<span style="COLOR: #0000ff">QTableView</span>和<span style="COLOR: #0000ff">QTreeView</span>,除数据项之外也可显示标题(Headers)，标题部分通过一个view来实现，QHeaderView。标题与view一样总是从相同的model中获取数据。从 model中获取数据的函数是<span style="COLOR: #0000ff">QabstractItemModel</span>::<span style="COLOR: #800080"><strong>headerDate</strong></span>()，一般总是以表单的形式中显示标题信息。可以从<span style="COLOR: #0000ff">QHeaderView</span>子类化，以实现更为复杂的定制化需求。<br><br><span style="COLOR: #0000ff"><strong>使用现成的view<br></strong></span>Qt提供了三个现成的view 类，它们能够以用户熟悉的方式显示model中的数据。<span style="COLOR: #0000ff">QListView</span>把model中的数据项以一个简单的列表的形式显示，或是以经典的图标视图的形式显示。<span style="COLOR: #0000ff">QTreeView</span>把model中的数据项作为具有层次结构的列表的形式显示，它允许以紧凑的深度嵌套的结构进行显示。<span style="COLOR: #0000ff">QTableView</span>却是把model中的数据项以表格的形式展现，更像是一个电子表格应用程序的外观布局。<br><img style="WIDTH: 465px; HEIGHT: 212px" height=212 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/r_standard-views001.png" width=465 border=0><br>以上这些标准view的行为足以应付大多数的应用程序，它们也提供了一些基本的编辑功能，也可以定制特殊的需求。</p>
<p><span style="COLOR: #0000ff"><strong>使用model</strong></span><br>以前的例子中创建过一个string list model,可以给它设置一些数据，再创建一个view把model中的内容展示出来：<br>int main(int argc, char *argv[])<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">QApplication</span> app(argc, argv);</p>
<p>&nbsp;<span style="COLOR: #008000">// Unindented for quoting purposes:<br></span>&nbsp;<span style="COLOR: #0000ff">QStringList</span> numbers;<br>&nbsp;numbers &lt;&lt; "One" &lt;&lt; "Two" &lt;&lt; "Three" &lt;&lt; "Four" &lt;&lt; "Five";</p>
<p>&nbsp;<span style="COLOR: #0000ff">QAbstractItemModel</span> *model = new <span style="COLOR: #0000ff">StringListModel</span>(numbers);<br>&nbsp;<span style="COLOR: #008000">//要注意的是，这里把StringListModel作为一个QAbstractItemModel来使用。这样我们就可以<br>&nbsp;//使用model中的抽象接口，而且如果将来我们用别的model代替了当前这个model,这些代码也会照样工作。<br>&nbsp;//QListView提供的列表视图足以满足当前这个model的需要了。<br></span>&nbsp;<span style="COLOR: #0000ff">QListView</span> *view = new QListView;<br>&nbsp;view-&gt;<span style="COLOR: #800080"><strong>setModel</strong></span>(model);<br>&nbsp; view-&gt;<span style="COLOR: #800080"><strong>show</strong></span>();<br>&nbsp; return app.exec();<br>}<br><img height=218 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/r_stringlistmodel.png" width=264 border=0><br>view会渲染model中的内容，通过model的接口来访问它的数据。当用户试图编辑数据项时，view会使用缺省的delegate来提供一个编辑构件。<br><span style="COLOR: #0000ff"><strong>一个model,多个views</strong></span><br>为多个views提供相同的model是非常简单的事情，只要为每个view设置相同的model。<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QTableView</span> *firstTableView = new QTableView;<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QTableView</span> *secondTableView = new QTableView;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; firstTableView-&gt;<span style="COLOR: #800080"><strong>setModel</strong></span>(model);<br>&nbsp;&nbsp;&nbsp;&nbsp; secondTableView-&gt;<span style="COLOR: #800080"><strong>setModel</strong></span>(model);<br>在model/view架构中信号、槽机制的使用意味着model中发生的改变会传递中联结的所有view中，这保证了<br>不管我们使用哪个view，访问的都是同样的一份数据。<br><img height=232 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/r_sharedmodel-tableviews.png" width=573 border=0><br>上面的图展示了一个model上的两个不同的views,尽管在不同的view中显示的model中的数据是一致的，每个<br>view都维护它们自己的内部选择模型，但有时候在某些情况下，共享一个选择模型也是合理的。</p>
<p><strong style="COLOR: #0000ff">处理数据项的选择<br></strong>view中数据项选择机制由<span style="COLOR: #0000ff">QItemSelectionModel</span>类提供。所有标准的view缺省都构建它们自己的选择模型，<br>以标准的方式与它们交互。选择模型可以用<strong style="COLOR: #800080">selectionModel</strong>()函数取得，替代的选择模型也可以通过<br><span style="COLOR: #800080"><strong>setSelectionModel</strong></span>()来设置。当我们想在一个model上提供多个一致的views时，这种对选择模型的控制能力非常有用。通常来讲，除非你子类化一个model或view,你不必直接操纵selections的内容。<br><br><span style="COLOR: #0000ff"><strong>多个views之间共享选择</strong></span><br>接着上边的例子，我们可以这样：<br>secondTableView-&gt;<span style="COLOR: #800080"><strong>setSelectionModel</strong></span>(firstTableView-&gt;<span style="COLOR: #800080"><strong>selectionModel</strong></span>());<br>现在所有views都在同样的选择模型上操作，数据与选择项都保持同步。<br><img height=232 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/r_sharedselection-tableviews.png" width=572 border=0><br>上面的例子中，两个view的类型是相同的，假如这两个view类型不同，那么所选择的数据项在每个view<br>中的表现形式会有很大的不同。例如，在一个table view中一个连续的选择，在一个tree view中表现出<br>来的可能会是几个高亮的数据项片断的组合。</p>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/26568.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-06-18 16:15 <a href="http://www.cppblog.com/yuanyajie/archive/2007/06/18/26568.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Model/View 学习笔记 (四) </title><link>http://www.cppblog.com/yuanyajie/archive/2007/06/18/26555.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Mon, 18 Jun 2007 03:56:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/06/18/26555.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/26555.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/06/18/26555.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/26555.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/26555.html</trackback:ping><description><![CDATA[<p>清源游民 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#103;&#97;&#109;&#101;&#111;&#103;&#114;&#101;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">gameogre@gmail.com</a><br><br><span style="FONT-SIZE: 18pt">创建新的Models<br><br></span><strong><span style="COLOR: #0000ff">介绍</span><br></strong>model/view组件之间功能的分离，允许创建model利用现成的views。这也可以使用标准的功能 图形用户接口组件像QListView,QTableView和QTreeView来显示来自各种数据源的数据为。<br>QAbstractListModel类提供了非常灵活的接口，允许数据源以层次结构的形式来管理信息，也允许以某种<br>方式对数据进行插入、删除、修改和存储。它也提供了对拖拽操作的支持。<br><span style="COLOR: #0000ff">QAbstractListModel</span>与<span style="COLOR: #0000ff">QAbstractTableModel</span>为简单的非层次结构的数据提供了接口，对于比较简单的list和table models来说，这是不错的一个开始点。<br><br><span style="COLOR: #0000ff"><strong>设计一个Model<br></strong></span>当我们为存在的数据结构新建一个model时，首先要考虑的问题是应该选用哪种model来为这些数据提供接口。<br>假如数据结构可以用数据项的列表或表来表示，那么可以考虑子类化<span style="COLOR: #0000ff">QAbstractListModel</span>或<span style="COLOR: #0000ff">QAbstractTableModel</span><br>,既然这些类已经合理地对许多功能提供缺省实现。<br>然而，假如底层的数据结构只能表示成具有层次结构的树型结构，那么必须得子类化<span style="COLOR: #0000ff">QAbstractItemModel</span>。<br>无论底层的数据结构采取何种形式，在特定的model中实现标准的<span style="COLOR: #0000ff">QAbstractItemModel</span> API总是一个不错的主意，这使得可以使用更自然的方式对底层的数据结构进行访问。这也使得用数据构建model 更为容易，其他<br>的model/view组件也可以使用标准的API与之进行交互。<br><br><span style="COLOR: #0000ff"><strong>一个只读model示例</strong><br></span>这个示例实现了一个简单的，非层次结构的，只读的数据model,它基于<span style="COLOR: #0000ff">QStringistModel</span>类。它有一个<span style="COLOR: #0000ff">QStringList</span>作为它内部的数据源，只实现了一些必要的接口。为了简单化，它子类化了<span style="COLOR: #0000ff">QAbstractListModel</span>,这个基类提供了合理的缺省行为，对外提供了比<span style="COLOR: #0000ff">QAbstractItemModel</span>更为简单的接口。当我们实现一个model时，不要忘了<span style="COLOR: #0000ff">QAbstractItemModel</span>本身不存储任何数据，它仅仅提供了给views访问<br>数据的接口。<br>class <span style="COLOR: #0000ff">StringListModel</span> : public <span style="COLOR: #0000ff">QAbstractListModel</span><br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; Q_OBJECT</p>
<p>&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">StringListModel</span>(const QStringList &amp;strings, QObject *parent = 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : <span style="COLOR: #0000ff">QAbstractListModel</span>(parent), stringList(strings) {}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; int <span style="COLOR: #ff00ff">rowCount</span>(const QModelIndex &amp;parent = QModelIndex()) const;<br>&nbsp;&nbsp;&nbsp;&nbsp; QVariant <span style="COLOR: #ff00ff">data</span>(const QModelIndex &amp;index, int role) const;<br>&nbsp;&nbsp;&nbsp;&nbsp; QVariant <span style="COLOR: #ff00ff">headerData</span>(int section, Qt::Orientation orientation,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int role = Qt::DisplayRole) const;</p>
<p>&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QStringList</span> stringList;<br>&nbsp;};<br>除了构造函数，我们仅需要实现两个函数：<span style="COLOR: #ff00ff">rowCount</span>()返回model中的行数，<span style="COLOR: #ff00ff">data</span>()返回与特定model index对应的数据项。具有良好行为的model也会实现<span style="COLOR: #ff00ff">headerData</span>()，它返回tree和table views需要的，在标题中显示的数据。<br>因为这是一个非层次结构的model,我们不必考虑父子关系。假如model具有层次结构，我们也应该实现<span style="COLOR: #ff00ff">index</span>()与<span style="COLOR: #ff00ff">parent</span>()函数。<br><br><strong style="COLOR: #0000ff">Model的尺寸</strong><br>我们认为model中的行数与string list中的string数目一致：<br>int <span style="COLOR: #3366ff">StringListModel</span>::<span style="COLOR: #ff00ff">rowCount</span>(const QModelIndex &amp;parent) const<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; return stringList.count();<br>&nbsp;}<br>在缺省情况下，从<span style="COLOR: #0000ff">QAbstractListModel</span>派生的model只具有一列，因此不需要实现columnCount()。<br><br><span style="COLOR: #0000ff"><strong>Model 标题与数据</strong></span><br>&nbsp;QVariant <span style="COLOR: #0000ff">StringListModel</span>::<span style="COLOR: #ff00ff">data</span>(const QModelIndex &amp;index, int role) const<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; if (!index.isValid())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return QVariant();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if (index.row() &gt;= stringList.size())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return QVariant();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if (role == Qt::DisplayRole)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return stringList.at(index.row());<br>&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return QVariant();<br>&nbsp;}<br>QVariant <span style="COLOR: #0000ff">StringListModel</span>::<span style="COLOR: #ff00ff">headerData</span>(int section, Qt::Orientation orientation,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int role) const<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; if (role != Qt::DisplayRole)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return QVariant();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if (orientation == Qt::Horizontal)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return QString("Column %1").arg(section);<br>&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return QString("Row %1").arg(section);<br>&nbsp;}<br>一个数据项可能有多个角色，根据角色的不同输出不同的数据。上例中，model中的数据项只有一个角色 ，<br>DisplayRole,然而我们也可以重用提供给DisplayRole的数据，作为别的角色使用，如我们可以作为ToolTipRole来用。<br><br><span style="COLOR: #0000ff"><strong>可编辑的model<br></strong></span>上面我们演示了一个只读的model,它只用于向用户显示，对于许多程序来说，可编辑的list model可能更有用。我们只需要给只读的model提供另外两个函数flags()与setData()的实现。下列函数声明被添加到类定义中：<br>&nbsp;&nbsp;&nbsp;&nbsp; Qt::<span style="COLOR: #0000ff">ItemFlags</span> <span style="COLOR: #ff00ff">flags</span>(const QModelIndex &amp;index) const;<br>&nbsp;&nbsp;&nbsp;&nbsp; bool <span style="COLOR: #ff00ff">setData</span>(const QModelIndex &amp;index, const QVariant &amp;value,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int role = Qt::EditRole);<br><br><span style="COLOR: #0000ff">让model可编辑<br></span>delegate会在创建编辑器之前检查数据项是否是可编辑的。model必须得让delegate知道它的数据项是可<br>编辑的。这可以通过为每一个数据项返回一个正确的标记得到，在本例中，我们假设所有的数据项都是<br>可编辑可选择的：<br>Qt::<span style="COLOR: #0000ff">ItemFlags</span> <span style="COLOR: #0000ff">StringListModel</span>::<span style="COLOR: #ff00ff">flags</span>(const QModelIndex &amp;index) const<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; if (!index.isValid())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Qt::ItemIsEnabled;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; return <span style="COLOR: #0000ff">QAbstractItemModel</span>::flags(index) | Qt::ItemIsEditable;<br>&nbsp;}<br>我们不必知道delegate执行怎样实际的编辑处理过程，我们只需提供给delegate一个方法，delegate会使用它对model中的数据进行设置。这个特殊的函数就是setData():<br>bool <span style="COLOR: #0000ff">StringListModel</span>::<span style="COLOR: #ff00ff">setData</span>(const QModelIndex &amp;index,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const QVariant &amp;value, int role)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; if (index.isValid() &amp;&amp; role == Qt::EditRole) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stringList.replace(index.row(), value.toString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">emit</span> <span style="COLOR: #ff00ff">dataChanged</span>(index, index);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; return false;<br>&nbsp;}<br>当数据被设置后，model必须得让views知道一些数据发生了变化，这可通过发射一个dataChanged() 信号实现。<br>因为只有一个数据项发生了变化，因此在信号中说明的变化范围只限于一个model index。<br><span style="COLOR: #0000ff">插入，删除行<br></span>在model中改变行数与列数是可能的。当然在本列中，只考虑行的情况，我们只需要重新实现插入、删除<br>的函数就可以了，下面应在类定义中声明：<br>&nbsp;&nbsp;&nbsp;&nbsp; bool <span style="COLOR: #ff00ff">insertRows</span>(int position, int rows, const QModelIndex &amp;index = QModelIndex());<br>&nbsp;&nbsp;&nbsp;&nbsp; bool <span style="COLOR: #ff00ff">removeRows</span>(int position, int rows, const QModelIndex &amp;index = QModelIndex());<br>既然model中的每行对应于列表中的一个string,因此，insertRows()函数在string list&nbsp; 中指定位置插入一个空string,<br>父index通常用于决定model中行列的位置，本例中只有一个单独的顶级项，困此只需要在list中插入空string。<br>bool <span style="COLOR: #0000ff">StringListModel</span>::insertRows(int position, int rows, const QModelIndex &amp;parent)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">beginInsertRows</span>(QModelIndex(), position, position+rows-1);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; for (int row = 0; row &lt; rows; ++row) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stringList.insert(position, "");<br>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">endInsertRows</span>();<br>&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>&nbsp;}<br>beginInsertRows()通知其他组件行数将会改变。endInsertRows()对操作进行确认与通知。<br>返回true表示成功。<br>删除操作与插入操作类似：<br>bool <span style="COLOR: #0000ff">StringListModel</span>::removeRows(int position, int rows, const QModelIndex &amp;parent)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">beginRemoveRows</span>(QModelIndex(), position, position+rows-1);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; for (int row = 0; row &lt; rows; ++row) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stringList.removeAt(position);<br>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #ff00ff">endRemoveRows</span>();<br>&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>&nbsp;}</p>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/26555.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-06-18 11:56 <a href="http://www.cppblog.com/yuanyajie/archive/2007/06/18/26555.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Model/View 学习笔记 (三) </title><link>http://www.cppblog.com/yuanyajie/archive/2007/06/17/26488.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Sun, 17 Jun 2007 06:31:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/06/17/26488.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/26488.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/06/17/26488.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/26488.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/26488.html</trackback:ping><description><![CDATA[<p>清源游民 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#103;&#97;&#109;&#101;&#111;&#103;&#114;&#101;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;"><u><font color=#000000>gameogre@gmail.com</font></u></a><br><br><span style="FONT-SIZE: 24pt"><em>Model类<br></em></span><br><span style="COLOR: #0000ff"><strong>基本概念</strong><br></span>在model/view构架中，model为view和delegates使用数据提供了标准接口。在Qt中，标准接口<span style="COLOR: #0000ff">QAbstractItemModel</span>类中被定义。不管数据在底层以何种数据结构存储，<span style="COLOR: #0000ff">QAabstractItemModel</span>的子类会以层次结构的形式来表示数据，结构中包含了数据项表。我们按这种约定来访问model中的数据项，但这个约定不会对如何显示这些数据有任何限制。数据发生改变时，model通过信号槽机制来通知关联的views。<br><img height=332 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/o_modelview-models1.png" width=618 border=0></p>
<p><span style="COLOR: #0000ff"><strong>Model Indexes</strong></span></p>
<p>为了使数据存储与数据访问分开，引入了model index的概念。通过model index，可以引用model中的数据项，Views和delegates都使用indexes来访问数据项，然后再显示出来。因此，只有model需要了解如何获取数据，被model管理的数据类型可以非常广泛地被定义。Model indexes包含一个指向创建它们的model的指针，这会在配合多个model工作时避免混乱。<br><span style="COLOR: #0000ff">QAbstractItemModel</span> *model = index.<span style="COLOR: #ff00ff">model</span>();</p>
<p>model indexes提供了对一项数据信息的临时引用，通过它可以访问或是修改model中的数据。既然model有时会重新组织内部的数据结构，这时model indexes便会失效，因此不应该保存临时的model indexes。假如需要一个对数据信息的长期的引用，那么应该创建一个<span style="COLOR: #0000ff">persistent</span> model index。这个引用会保持更新。临时的model indexes由<span style="COLOR: #0000ff">QModelIndex</span>提供，而具有持久能力的model indexes则由<span style="COLOR: #0000ff">QPersistentModelIndex</span>提供。在获取对应一个数据项的model index时，需要考虑有关于model的三个属性：行数，列数，父项的model index。</p>
<p><br><span style="COLOR: #0000ff"><strong>行与列</strong></span><br>在最基本的形式中，一个model可作为一个简单的表来访问，每个数据项由行，列数来定位。这必不意味着<br>底层的数据用数组结构来存储。行和列的使用仅仅是一种约定，它允许组件之间相互通讯。可以通过指定<br>model中的行列数来获取任一项数据，可以得到与数据项一一对应的那个index。<br><span style="COLOR: #0000ff">QModelIndex</span> index = model-&gt;<span style="COLOR: #ff00ff">index</span>(row, column, ...);<br>Model为简单的，单级的数据结构如list与tables提供了接口，它们如上面代码所显示的那样，不再需要别的信息被提供。当我们在获取一个model index时，我们需要提供另外的信息。<br><img height=303 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/r_modelview-tablemodel.png" width=245 border=0></p>
<p>上图代表一个基本的table model，它的每一项用一对行列数来定位。通过行列数，可以获取代表一个数据项的model index . <br><span style="COLOR: #0000ff">QModelIndex</span> indexA = model-&gt;<span style="COLOR: #ff00ff">index</span>(0, 0, <span style="COLOR: #ff00ff">QModelIndex</span>());<br>&nbsp;<span style="COLOR: #0000ff">QModelIndex</span> indexB = model-&gt;<span style="COLOR: #ff00ff">index</span>(1, 1, <span style="COLOR: #ff00ff">QModelIndex</span>());<br>&nbsp;<span style="COLOR: #0000ff">QModelIndex</span> indexC = model-&gt;<span style="COLOR: #ff00ff">index</span>(2, 1, <span style="COLOR: #ff00ff">QModelIndex</span>());<br>一个model的顶级项,由QModelIndex()取得，它们上式被用作父项。</p>
<p><span style="COLOR: #0000ff"><strong>父项</strong></span><br>类似于表的接口在搭配使用table或list view时理想的，这种行列系统与view显示的方式是确切匹配的。<br>然则，像tree views这种结构需要model提供更为灵活的接口来访问数据项。每个数据项可能是别的项的<br>父项，上级的项可以获取下级项的列表。<br>当获取model中数据项的index时，我们必须指定关于数据项的父项的信息。在model外部，引用一个数据<br>项的唯一方法就是通过model index,因此需要在求取model index时指定父项的信息。<br><span style="COLOR: #0000ff">QModelIndex</span> index = model-&gt;<span style="COLOR: #ff00ff">index</span>(row, column, parent);<br><img height=332 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/o_modelview-treemodel.png" width=251 border=0><br>上图中，A项和C项作为model中顶层的兄弟项：<br>&nbsp;<span style="COLOR: #0000ff">QModelIndex</span> indexA = model-&gt;<span style="COLOR: #ff00ff">index</span>(0, 0, QModelIndex());<br>&nbsp;<span style="COLOR: #0000ff">QModelIndex</span> indexC = model-&gt;<span style="COLOR: #ff00ff">index</span>(2, 1, QModelIndex());<br>A有许多孩子，它的一个孩子B用以下代码获取：<br><span style="COLOR: #0000ff">QModelIndex</span> indexB = model-&gt;<span style="COLOR: #ff00ff">index</span>(1, 0, indexA);<br><br><strong><span style="COLOR: #0000ff">项角色</span><br></strong>model中的项可以作为各种角色来使用，这允许为不同的环境提供不同的数据。举例来说，Qt::DisplayRole被用于访问一个字符串，它作为文本会在view中显示。典型地，每个数据项都可以为许多不同的角色提供数据，标准的角色在Qt::ItemDataRole中定义。我们可以通过指定model index与角色来获取我们需要的数据：<br><span style="COLOR: #0000ff">QVariant</span> value = model-&gt;<span style="COLOR: #ff00ff">data</span>(index, role);<br><img height=265 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/o_modelview-roles.png" width=379 border=0></p>
<p>角色指出了从model中引用哪种类型的数据。views可以用不同的形式显示角色，因此为每个角色提供正确<br>的信息是非常重要的。通过为每个角色提供适当数据，model也为views和delegates提供了暗示，如何正确地<br>把这些数据项显给用户。不同的views可以自由地解析或忽略这些数据信息，对于特殊的场合，也可以定义<br>一些附加的角色。<br><span style="COLOR: #0000ff"><strong>概念总结：</strong></span><br>1，Model indexes为views与delegages提供model中数据项定位的信息，它与底层的数据结构无关。<br>2，通过指定行，列数，父项的model index来引用数据项。<br>3,依照别的组件的要求，model indexes被model构建。<br>4，使用index()时，如果指定了有效的父项的model index,那么返回得到的model index对应于父项的某个孩子。<br>5，使用index()时，如果指定了无效的父项的model index,那么返回得到的model index对应于顶层项的某个孩子。<br>6, 角色对一个数据项包含的不同类型的数据给出了区分。</p>
<p><span style="COLOR: #0000ff"><strong>使用Model Indexes</strong></span><br><span style="COLOR: #0000ff">QDirModel</span> *model = new <span style="COLOR: #0000ff">QDirModel</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndex</span> parentIndex = model-&gt;<span style="COLOR: #ff00ff">index</span>(QDir::currentPath());<br>&nbsp;&nbsp;&nbsp;&nbsp; int numRows = model-&gt;<span style="COLOR: #ff00ff">rowCount</span>(parentIndex);<br>&nbsp;for (int row = 0; row &lt; numRows; ++row)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QModelIndex</span> index = model-&gt;<span style="COLOR: #ff00ff">index</span>(row, 0, parentIndex);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tring text = model-&gt;<span style="COLOR: #ff00ff">data</span>(index, Qt::DisplayRole).toString();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #993366">&nbsp;&nbsp; // Display the text in a widget.</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; }<br>以上的例子说明了从model中获取数据的基本原则：<br>1，model的尺寸可以从<span style="COLOR: #ff00ff">rowCount</span>()与<span style="COLOR: #ff00ff">columnCount</span>()中得出。这些函数通常都需要一个表示父项的model index。<br>2，model indexes用来从model中访问数据项，数据项用行，列，父项model index定位。<br>3, 为了访问model顶层项，可以使用<span style="COLOR: #ff00ff">QModelIndex</span>()指定。<br>4, 数据项为不同的角色提供不同的数据。为了获取数据，除了model index之外，还要指定角色。<br></p>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/26488.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-06-17 14:31 <a href="http://www.cppblog.com/yuanyajie/archive/2007/06/17/26488.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Model/View 学习笔记 (二) </title><link>http://www.cppblog.com/yuanyajie/archive/2007/06/15/26390.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Fri, 15 Jun 2007 09:04:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/06/15/26390.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/26390.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/06/15/26390.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/26390.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/26390.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/06/15/26390.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/26390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-06-15 17:04 <a href="http://www.cppblog.com/yuanyajie/archive/2007/06/15/26390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Model/View 学习笔记  (一)</title><link>http://www.cppblog.com/yuanyajie/archive/2007/06/15/26387.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Fri, 15 Jun 2007 07:53:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/06/15/26387.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/26387.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/06/15/26387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/26387.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/26387.html</trackback:ping><description><![CDATA[<p>&nbsp;清源游民&nbsp;&nbsp; gameogre@gmail.com<br><br><span style="COLOR: #0000ff">介绍</span></p>
<p>Qt 4推出了一组新的item view类，它们使用model/view结构来管理数据与表示层的关系。这种结构带来的<br>功能上的分离给了开发人员更大的弹性来定制数据项的表示，它也提供一个标准的model接口，使得更多的<br>数据源可以被这些item view使用。这里对model/view的结构进行了描述，结构中的每个组件都进行了解释，<br>给出了一些例子说明了提供的这些类如何使用。</p>
<p><span style="COLOR: #0000ff">Model/View&nbsp; 结构</span></p>
<p>Model-View-Controller(MVC)， 是从Smalltalk发展而来的一种设计模式，常被用于构建用户界面。经典设计模式的著作中有这样的描述：</p>
<p style="COLOR: #ff00ff"><em>MVC 由三种对象组成。Model是应用程序对象，View是它的屏幕表示，Controller定义了用户界面如何对用户输入进行响应。在MVC之前，用户界面设计倾向于三者揉合在一起，MVC对它们进行了解耦，提高了灵活性与重用性。</em></p>
<p>假如把view与controller结合在一起，结果就是model/view结构。这个结构依然是把数据存储与数据表示进行了分离，它与MVC都基于同样的思想，但它更简单一些。这种分离使得在几个不同的view上显示同一个数据成为可能，也可以重新实现新的view,而不必改变底层的数据结构。为了更灵活的对用户输入进行处理，引入了delegate这个概念。它的好处是，数据项的渲染与编程可以进行定制。<br><img height=257 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/o_modelview-overview.png" width=239 border=0><br>如上图所示，model与数据源通讯，并提供接口给结构中的别的组件使用。通讯的性质依赖于数据源的种类<br>与model实现的方式。view从model获取model indexes,后者是数据项的引用。通过把model indexes提供给model,view可以从数据源中获取数据。</p>
<p>在标准的views中，delegate会对数据项进行渲染，当某个数据项被选中时，delegate通过model indexes与model直接进行交流。总的来说，model/view 相关类可以被分成上面所提到的三组：models,views,delegates。这些组件通过抽象类来定义，它们提供了共同的接口，在某些情况下，还提供了缺省的实现。抽象类意味着需要子类化以提供完整的其他组件希望的功能。这也允许实现定制的组件。models,views,delegates之间通过信号，槽机制来进行通讯：</p>
<p>从model发出的信号通知view数据源中的数据发生了改变。<br>从view发出的信号提供了有关被显示的数据项与用户交互的信息。<br>从delegate发生的信号被用于在编辑时通知model和view关于当前编辑器的状态信息。</p>
<p><span style="COLOR: #0000ff">Models</span></p>
<p>所有的item models都基于<span style="COLOR: #0000ff">QAbstractItemModel</span>类，这个类定义了用于views和delegates访问数据的接口。<br>数据本身不必存储在model,数据可被置于一个数据结构或另外的类，文件，数据库，或别的程序组件中。<br>关于model的基本概念在Model Classes部分中描述。<br><span style="COLOR: #0000ff">QAbstractItemModel</span>提供给数据一个接口，它非常灵活，基本满足views的需要，无论数据用以下任何样的形式<br>表现，如tables,lists,trees。然而，当你重新实现一个model时，如果它基于table或list形式的数据结构，最好从<span style="COLOR: #0000ff">QAbstractListModel</span>,<span style="COLOR: #0000ff">QAbstractTableModel</span>开始做起，因为它们提供了适当的常规功能的缺省实现。这些类可以被子类化以支持特殊的定制需求。子类化model的过程在Create New Model部分讨论<br>QT提供了一些现成的models用于处理数据项：<br><span style="COLOR: #0000ff">QStringListModel</span> 用于存储简单的QString列表。<br><span style="COLOR: #0000ff">QStandardItemModel</span> 管理复杂的树型结构数据项，每项都可以包含任意数据。<br><span style="COLOR: #0000ff">QDirModel</span>&nbsp; 提供本地文件系统中的文件与目录信息。<br><span style="COLOR: #0000ff">QSqlQueryModel</span>, <span style="COLOR: #0000ff">QSqlTableModel</span>,<span style="COLOR: #0000ff">QSqlRelationTableModel</span>用来访问数据库。<br>假如这些标准Model不满足你的需要，你应该子类化<span style="COLOR: #0000ff">QAbstractItemModel</span>,<span style="COLOR: #0000ff">QAbstractListModel</span>或是<br><span style="COLOR: #0000ff">QAbstractTableModel</span>来定制。</p>
<p><span style="COLOR: #0000ff">Views</span></p>
<p>不同的view都完整实现了各自的功能：<span style="COLOR: #0000ff">QListView</span>把数据显示为一个列表，<span style="COLOR: #0000ff">QTableView</span>把Model 中的数据以table的形式表现，<span style="COLOR: #0000ff">QTreeView</span> 用具有层次结构的列表来显示model中的数据。这些类都基于<span style="COLOR: #0000ff">QAbstractItemView</span>抽象基类，尽管这些类都是现成的，完整的进行了实现，但它们都可以用于子类化以便满足定制需求。</p>
<p><span style="COLOR: #0000ff">Delegates</span><br><span style="COLOR: #0000ff">QAbstractItemDelegate</span> 是model/view架构中的用于delegate的抽象基类。缺省的delegate实现在<span style="COLOR: #0000ff">QItemDelegate</span>类中提供。它可以用于Qt标准views的缺省 delegate.</p>
<p><span style="COLOR: #0000ff">排序</span></p>
<p>在model/view架构中，有两种方法进行排序，选择哪种方法依赖于你的底层Model。<br>假如你的model是可排序的，也就是它重新实现了<span style="COLOR: #0000ff">QAbstractItemModel</span>::<span style="COLOR: #0000ff">sort</span>()函数，<span style="COLOR: #0000ff">QTableView</span>与<span style="COLOR: #0000ff">QTreeView</span>都提供了API,允许你以编程的方式对Model数据进行排序。另外，你也可以进行交互方式下的排序（例如，允许用户通过点击view表头的方式对数据进行排序），可以这样做：把<span style="COLOR: #0000ff">QHeaderView</span>::<span style="COLOR: #0000ff">sectionClicked</span>()信号与QTableView::<span style="COLOR: #0000ff">sortByColum</span>()槽或QTreeView::<span style="COLOR: #0000ff">sortByColumn</span>()槽进行联结就好了。<br>另一种方法是，假如你的model没有提供需要的接口或是你想用list view表示数据，可以用一个代理<br>model在用view表示数据之前对你的model数据结构进行转换。</p>
<p><span style="COLOR: #0000ff">便利类</span></p>
<p>许多便利类都源于标准的view类，它们方便了那些使用Qt中基于项的view与table类，它们不应该被子类化，<br>它们只是为Qt 3的等价类提供一个熟悉的接口。这些类有<span style="COLOR: #0000ff">QListWidget,QTreeWidget,QTableWidget</span>,它们提供了如Qt 3中的<span style="COLOR: #0000ff">QListBox, QlistView,QTable</span>相似的行为。这些类比View类缺少灵活性，不能用于任意的models,推介使用model/view的方法处理数据。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/26387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-06-15 15:53 <a href="http://www.cppblog.com/yuanyajie/archive/2007/06/15/26387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QT中的事件机制</title><link>http://www.cppblog.com/yuanyajie/archive/2007/06/13/26283.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Wed, 13 Jun 2007 14:42:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/06/13/26283.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/26283.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/06/13/26283.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/26283.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/26283.html</trackback:ping><description><![CDATA[<p>原文<a href="http://doc.trolltech.com/qq/qq11-events.html">Another Look at Events</a>&nbsp;<br>作者： Jasmin Blanchette&nbsp; 译：清源游民 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#103;&#97;&#109;&#101;&#111;&#103;&#114;&#101;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">gameogre@gmail.com</a><br><br>什么是自发事件？哪些类型的事件可以被propagated 或compressed? posting and sending 事件之间有何不同？什么时候应该调用 accept() 或是ignore() ? 如果这些问题你还不是很了解，那么继续看下去。</p>
<p><span style="COLOR: #0000ff">事件起源：</span></p>
<p>基于事件如何被产生与分发，可以把事件分为三类：<br>* Spontaneous 事件,由窗口系统产生，它们被放到系统队列中，通过事件循环逐个处理。<br>* Posted 事件，由Qt或是应用程序产生，它们被Qt组成队列，再通过事件循环处理。<br>* Sent&nbsp; 事件，由Qt或是应用程序产生，但它们被直接发送到目标对象。<br>当我们在main()函数的末尾调用<span style="COLOR: #0000ff">QApplication</span>::exec()时,程序进入了Qt的事件循环，大概来讲，事件循环如下面所示：<br>while (!exit_was_called)<br>{<br>&nbsp; while(!posted_event_queue_is_empty)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; process_next_posted_event();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp; while(!spontaneous_event_queue_is_empty)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; process_next_spontaneous_event();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp; while(!posted_event_queue_is_empty)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; process_next_posted_event();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>}<br>首先，事件循环处理所有的posted事件，直到队列空。然后再处理所有的spontaneous事件，最后它处理所有的因为处理spontaneous事件而产生的posted事件。send 事件并不在事件循环内处理，它们都直接被发送到了目标对象。现在看一下实践中的paint 事件是如何工作的。当一个widget第一次可见，或是被遮挡后再次变为可见，<br>窗口系统产生一个(spontaneous) paint事件，要求程序重画widget,事件循环最终从事件队列中捡选这个事件并把它分发到那个需要重画的widget。<br>并不是所有的paint事件都是由窗口系统产生的。当你调用<span style="COLOR: #0000ff">QWidget</span>::update()去强行重画widget,这个widget会post 一个paint 事件给自己。这个paint事件被放入队列，最终被事件循环分发之。<br>假如你很不耐烦，等不及事件循环去重画一个widget, 理论上，你应该直接调用paintEvent()强制进行立即的重画。但实际上这不总是可行的，因为paintEvent()函数是protected的（很可能访问不了）。它也绕开了任何存在的事件过滤器。因为这些原因，Qt提供了一个机制，直接sending事件而不是posting 。<br><span style="COLOR: #0000ff">QWidget</span>::repaint()就使用了这个机制来强制进行立即重画。<br>posting 相对于sending的一个优势是，它给了Qt一个压缩(compress)事件的机会。假如你在一个widget上连续地调用update() 十次，因update()而产生的这十个事件，将会自动地被合并为一个单独的事件，但是<span style="COLOR: #0000ff">QPaintEvents</span>事件附带的区域信息也合并了。可压缩的事件类型包括：paint,move,resize,layout hint,language change。<br>最后要注意，你可以在任何时候调用<span style="COLOR: #0000ff">QApplication</span>::sendPostedEvent()，强制Qt产生一个对象的posted事件。</p>
<p><span style="COLOR: #0000ff">人工合成的事件<br><br></span>QT应用程序可以产生他们自己的事件，或是预定义类型，或是自定义类型。 这可以通过创建QEvent类或它的<br>子类的实例，并且调用<span style="COLOR: #0000ff">QApplication</span>:postEvent()或<span style="COLOR: #0000ff">QApplication</span>::sendEvent()来实现。<br>这两个函数需要一个 QObject* 与一个QEvent * 作为参数，假如你调用postEvent(),你必须用 new 操作符来创建事件对象，Qt会它被处理后帮你删除它。假如你用sendEvent(), 你应该在栈上来创建事件。下面举两个例子：<br>一是posting 事件：<br>QApplication::postEvent(mainWin, new QKeyEvent(QEvent::KeyPress,Key_X,'X',0));<br>二是sending 事件：<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QKeyEvent</span> event(QEvent::KeyPress, Key_X, 'X', 0);<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QApplication</span>::sendEvent(mainWin, &amp;event);<br>Qt应用程序很少直接调用postEvent()或是sendEvnet()，因为大多数事件会在必要时被Qt或是窗口系统自动产生<br>。在大多数的情况下，当你想发送一个事件时，Qt已经为了准备好了一个更高级的函数来为你服务。（例如<br>update()与repaint())。</p>
<p><span style="COLOR: #0000ff">定制事件类型<br></span><br>qt允许你创建自己的事件类型，这在多线程的程序中尤其有用。在单线程的程序也相当有用，它可以作为<br>对象间的一种通讯机制。为什么你应该用事件而不是其他的标准函数调用，或信号、槽的主要原因是：事件既可用于同步也可用于异步（依赖于你是调用sendEvent()或是postEvents()),函数调用或是槽调用总是同步的。事件的另外一个好处是它可以被过滤。<br>演示如何post一个定制事件的代码片段：<br>const <span style="COLOR: #0000ff">QEvent</span>::Type MyEvent = (<span style="COLOR: #0000ff">QEvent</span>::Type)1234;<br>&nbsp; ...<br><span style="COLOR: #0000ff">QApplication</span>::postEvent(obj, new QCustomEvent(MyEvent));<br>事件必须是QCustomEvent类型(或子类）的。构造函数的参数是事件的类型，1024以下被Qt保留。其他可被程序使用。为处理定制事件类型，要重新实现customEvent()函数：<br>void MyLineEdit::customEvent(<span style="COLOR: #0000ff">QCustomEvent</span> *event)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (event-&gt;type() == MyEvent) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myEvent();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QLineEdit</span>::customEvent(event);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><span style="COLOR: #0000ff">QcustomEvent</span>类有一个void *的成员，可用于特定的目的。你也可以子类化QCustomEvent，加上别的成员，但是你也需要在customEvent()中转换<span style="COLOR: #0000ff">QCustomeEvent</span>到你特有的类型。</p>
<p><span style="COLOR: #0000ff">事件处理与过滤<br><br></span>Qt中的事件可以在五个不同的层次上被处理<br>1,重新实现一个特定的事件handler<br>&nbsp;<span style="COLOR: #0000ff">QObject</span>与<span style="COLOR: #0000ff">QWidget</span>提供了许多特定的事件handlers，分别对应于不同的事件类型。（如paintEvent()对应paint事件）<br>2,重新实现<span style="COLOR: #0000ff">QObject</span>::event()<br>&nbsp;event()函数是所有对象事件的入口，QObject和QWidget中缺省的实现是简单地把事件推入特定的事件handlers。<br>3,在<span style="COLOR: #0000ff">QObject</span>安装上事件过滤器<br>&nbsp; 事件过滤器是一个对象，它接收别的对象的事件，在这些事件到达指定目标之间。<br>4，在aApp上安装一个事件过滤器，它会监视程序中发送到所有对象的所有事件<br>5,重新实现<span style="COLOR: #0000ff">QApplication</span>:notify(),Qt的事件循环与sendEvent()调用这个函数来分发事件，通过重写它，你可以在别人之前看到事件。</p>
<p>一些事件类型可以被传递。这意味着假如目标对象不处理一个事件，Qt会试着寻找另外的事件接收者。用新的目标来调用<span style="COLOR: #0000ff">QApplication</span>::notify()。举例来讲，key事件是传递的，假如拥有焦点的Widget不处理特定键，Qt会分发相同的事件给父widget,然后是父亲的父亲，直到最顶层widget。</p>
<p><span style="COLOR: #0000ff">接受或是忽略？<br><br></span>可被传递的事件有一个accept()函数和一个ignore()函数，你可以用它们来告诉Qt，你&#8220;接收&#8221;或是<br>&#8220;忽略&#8221;这个事件。假如事件handler调用accept(),这个事件将不会再被传递。假如事件handler调用<br>ignore(),Qt会试着查找另外的事件接收者。<br>像大多数的开发者一样，你可能不会被调用accept()或是ignore()所烦恼。缺省情况下是&#8220;接收&#8221;，在<br>QWidget中的缺省实现是调用ignore(),假如你希望接收事件，你需要做的是重新实现事件handler，避免<br>调用QWidget的实现。假如你想&#8220;忽略&#8221;事件，只需简单地传递它到QWidget的实现。下面的代码演示了这一点：<br>void MyFancyWidget::keyPressEvent(QKeyEvent *event)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (event-&gt;key() == Key_Escape) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doEscape();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QWidget</span>::keyPressEvent(event);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>在上面的例子里，假如用户按了"ESC"键，我们会调用doEscape()并且事件被&#8220;接收&#8221;了（这是缺省的情况），<br>事件不会被传递到父widget,假如用户按了别的键，则调用QWidget的缺省实现。<br>void <span style="COLOR: #0000ff">QWidget</span>::keyPressEvent(QKeyEvent *event)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event-&gt;ignore();<br>&nbsp;&nbsp;&nbsp; }<br>应该感谢ignore()，事件会被传递到父widget中去。<br>讨论到目前为至，我们都假设基类是QWidget,然而，同样的规则也可以应用到别的层次中，只要用QWidget<br>代替基类即可。举例来说：<br>&nbsp;void MyFancyLineEdit::keyPressEvent(QKeyEvent *event)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (event-&gt;key() == Key_SysReq) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSystemRequest();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">QLineEdit</span>::keyPressEvent(event);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>由于某些原因，你会在event()中处理事件，而不是在特定的handler中，如keyPressEvent(),这个过程会有些不同。event()会返回一个布尔值，来告诉调用者是否事件被accept或ignore,(true表示accept),从event()中调用accept()或是ignore()是没有意义的。&#8220;Accept&#8221;标记是event()与特定事件handler之间的一种通讯机制。而从event()返回的布尔值却是用来与QApplication:notify()通讯的。在QWidgetk中缺省的event()实现是转换&#8220;Accept&#8221;标记为一个布尔值，如下所示：<br>bool <span style="COLOR: #0000ff">QWidget</span>::event(QEvent *event)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (e-&gt;type()) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case <span style="COLOR: #0000ff">QEvent</span>::KeyPress:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyPressEvent((QKeyEvent *)event);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!((QKeyEvent *)event)-&gt;isAccepted())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return <span style="COLOR: #0000ff">false</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case <span style="COLOR: #0000ff">QEvent</span>::KeyRelease:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyReleaseEvent((QKeyEvent *)event);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!((QKeyEvent *)event)-&gt;isAccepted())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return <span style="COLOR: #0000ff">false</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return <span style="COLOR: #0000ff">true</span>;<br>&nbsp;&nbsp;&nbsp; }</p>
<p>到现在为至，我们所说的内容不仅仅适用于key事件，也适用于mouse,wheel,tablet,context menu等事件<br>Close事件有点不同，调用<span style="COLOR: #0000ff">QCloseEvent</span>:ignore()取消了关闭操作，而accept()告诉Qt继续执行正常的关闭操作。为了避免混乱，最好是在closeEvent()的新实现中明确地进行accept()与ignore()的调用：<br>&nbsp;void MainWindow::closeEvent(QCloseEvent *event)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (userReallyWantsToQuit()) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event-&gt;accept();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event-&gt;ignore();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }</p>
<p><br>&nbsp;</p>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/26283.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-06-13 22:42 <a href="http://www.cppblog.com/yuanyajie/archive/2007/06/13/26283.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ogre3D嵌入Qt框架 之　小结</title><link>http://www.cppblog.com/yuanyajie/archive/2007/05/21/24528.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Mon, 21 May 2007 03:57:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/05/21/24528.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/24528.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/05/21/24528.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/24528.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/24528.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/yuanyajie/archive/2007/05/21/24528.html'>阅读全文</a><img src ="http://www.cppblog.com/yuanyajie/aggbug/24528.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-05-21 11:57 <a href="http://www.cppblog.com/yuanyajie/archive/2007/05/21/24528.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ogre3D嵌入Qt框架 之　秀图</title><link>http://www.cppblog.com/yuanyajie/archive/2007/05/21/24506.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Sun, 20 May 2007 17:26:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/05/21/24506.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/24506.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/05/21/24506.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/24506.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/24506.html</trackback:ping><description><![CDATA[<p>环境：WindowsXp Pro SP2, VS2003.NET, Ogre1.4.1(Eihort), Qt 4.2.2 开源版<br>参考：ShowMesh,MAGE,两款工具源码<br>先把图秀出来，有时间文字总结一下，难度虽然不高，但也折腾不少时间,也算近来学习Qt与Ogre的一个小结。<br><br><img height=480 alt="" src="http://www.cppblog.com/images/cppblog_com/yuanyajie/2865/r_ShowOgreEmbedInQt.jpg" width=612 border=0><br></p>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/24506.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-05-21 01:26 <a href="http://www.cppblog.com/yuanyajie/archive/2007/05/21/24506.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2003下安装QT4.2.2开源版</title><link>http://www.cppblog.com/yuanyajie/archive/2007/03/27/20716.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Tue, 27 Mar 2007 08:47:00 GMT</pubDate><guid>http://www.cppblog.com/yuanyajie/archive/2007/03/27/20716.html</guid><wfw:comment>http://www.cppblog.com/yuanyajie/comments/20716.html</wfw:comment><comments>http://www.cppblog.com/yuanyajie/archive/2007/03/27/20716.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/yuanyajie/comments/commentRss/20716.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yuanyajie/services/trackbacks/20716.html</trackback:ping><description><![CDATA[1, 取得开源版本<a title=qt href="http://www.qtnode.net/wiki/Download_Qt">download</a><br>2, 取得Win32下的补丁<a title=patch href="http://downloads.sourceforge.net/qtwin/acs-4.2.3-patch1.zip">download</a><br>3, 将两个文件解压到相同目录，如D:\Qt4<br>4, 打开VS2003命令行窗口,这自动对环境变量进行了设置。<br>5,从命令行窗口进入D:Qt4, 执行<font color=#0000ff>installpatch42.bat</font> ，这是从补丁解压得到的文件之一。<br>6, 执行 <font color=#0000ff>qconfigure.bat &nbsp;msvc.</font><font color=#0000ff>net</font><br>7,提示协议信息， 等待响应，键入'Y'<br>8,又提示，键入'y'<br>9可能又一个提示,键入'y'<br>10,出现类似以下提示:
<pre>====================================================
You are now ready to build Qt
If you specified -static, type 'nmake sub-src'
otherwise, type 'nmake'
To start over, type 'nmake distclean'
and then re-run qconfigure.bat
====================================================<br><font face="Times New Roman">11, 执行 <font color=#0000ff>nmake<br></font><font color=#000000>12,编译结束后，设置机器的环境变量 <font color=#0000ff>path</font> ： 添加路径 <font color=#ff1493>D:\Qt4\bin</font> ,   创建新的变量，</font><font face="Courier New" color=#0000ff>QMAKESPEC，<font color=#000000>值为</font><font color=#000000><font color=#ff1493>win32-msvc.net</font><br>13,新建一个文件hello.cpp,内容如下(开始测试是否安装好了)<br>#include &lt;QApplication&gt;<br>#include &lt;QLabel&gt;</font></font></font></pre>
<pre><font face="Times New Roman"><font face="Courier New" color=#0000ff><font color=#000000>int main(int argc, char **argv) {<br>&nbsp; QApplication app(argc, argv);<br>&nbsp; QLabel *label = new QLabel("Hello World!");<br>&nbsp; <br>&nbsp; label-&gt;show();</font></font></font></pre>
<pre><font face="Times New Roman"><font face="Courier New" color=#0000ff><font color=#000000>&nbsp; return app.exec();<br>}<br>14，在VS2003命令窗口下，进入cpp文件所在目录，如D:\test<br>15,<font color=#0000ff>qmake</font> -project -t vcapp -o projectname.pro<br>16,再来一次，不带参数 <font color=#0000ff>qmake<br></font>17,当前目录下生成了VS工程文件：<tt>projectname.vcproj</tt><br>18,用VS2003将 此工程打开，编译，运行。<br></font></font></font></pre>
<img src ="http://www.cppblog.com/yuanyajie/aggbug/20716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yuanyajie/" target="_blank">清源游民</a> 2007-03-27 16:47 <a href="http://www.cppblog.com/yuanyajie/archive/2007/03/27/20716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>