﻿<?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++博客-I smell magic in the air-随笔分类-Qt</title><link>http://www.cppblog.com/izualzhy/category/15717.html</link><description>坚持 相信自己</description><language>zh-cn</language><lastBuildDate>Wed, 30 Nov 2011 18:00:23 GMT</lastBuildDate><pubDate>Wed, 30 Nov 2011 18:00:23 GMT</pubDate><ttl>60</ttl><item><title>24点游戏(c++,Qt)</title><link>http://www.cppblog.com/izualzhy/archive/2011/11/29/161187.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Tue, 29 Nov 2011 12:31:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/11/29/161187.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/161187.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/11/29/161187.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/161187.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/161187.html</trackback:ping><description><![CDATA[<p>试着自己写了个24点游戏，如有改进或者不对的地方请指出。 
<p>基本知识： 
<p>游戏规则很简单，就是利用加减乘除将扑克牌的任一4张牌的组合，运算后得到结果24. 
<p>界面用Qt完成后 
<p><a href="http://www.cppblog.com/images/cppblog_com/izualzhy/WindowsLiveWriter/24cQt_120B6/clip_image002_2.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://www.cppblog.com/images/cppblog_com/izualzhy/WindowsLiveWriter/24cQt_120B6/clip_image002_thumb.jpg" width="462" height="103" /></a> 
<p><a href="http://www.cppblog.com/images/cppblog_com/izualzhy/WindowsLiveWriter/24cQt_120B6/clip_image004_2.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://www.cppblog.com/images/cppblog_com/izualzhy/WindowsLiveWriter/24cQt_120B6/clip_image004_thumb.jpg" width="464" height="102" /></a> 
<p>界面没有多下功夫，可以添加时间提醒，修改目标数值（24），增加牌数应该也是可以的，不过我没有去试一下。感觉花哨了没有简单来的好一些。 
<p>next会生成新的牌。answer查看答案。 
<p>牌的数值使用QlineEdit做的，可以自己设置值。 
<p>CardCalculation类会根据输入的牌数(vector&lt;double&gt;)计算出响应的表达式。 
<p>计算流程： 
<p>数据结构的书还没看完，算法完全是自己凭空去试。最后写出来后其实也不知道自己再考虑这方便问题时思路怎么展开。尽快抽时间看下算法的书才行。 
<p>我们拿&#8251;作为任意的操作符（+-*/）来说明。 
<p>根据vec元素个数: 
<p>1. a&#8251;b，直接计算即可。 
<p>2. a&#8251;b&#8251;c,可能操作为: 
<p>(a&#8251;b)&#8251;c 
<p>a&#8251;(b&#8251;c) 
<p>3. a&#8251;b&#8251;c &#8251;d,可能操作为： 
<p>(a&#8251;b)&#8251;c &#8251;d 
<p>a&#8251;(b&#8251;c) &#8251;d 
<p>a&#8251;b&#8251;(c &#8251;d) 
<p>因此采用递归求解，好处是如果增加牌的张数时应该容易修改一些，具体实现函数为calCards。 
<p>刚传进vec时，大小为4，属于第三种情况。遍历vec，将可能操作后形成的新的vector再次作为函数参数传入，直到遇到1情况返回，如果满足返回true，否则返回false。返回true时，修改第二个参数保存表达式。 
<p>关于如何返回表达式这里我弄了很长时间。计算出正确的表达式后，每次递归都会加一对括号，其实后面应该可以对表达式优化下可能减少括号的数量，不过我没有写。 
<p>程序里都写了注释~如果还是有问题请给我留言J <a href="/Files/izualzhy/TwentyFourGame.rar">/Files/izualzhy/TwentyFourGame.rar</a></p><img src ="http://www.cppblog.com/izualzhy/aggbug/161187.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-11-29 20:31 <a href="http://www.cppblog.com/izualzhy/archive/2011/11/29/161187.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] Qt经典出错信息之undefined reference to `vtable for classname</title><link>http://www.cppblog.com/izualzhy/archive/2011/10/28/159246.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Thu, 27 Oct 2011 16:16:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/10/28/159246.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/159246.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/10/28/159246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/159246.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/159246.html</trackback:ping><description><![CDATA[<p><span style="font-family:宋体; font-size:12pt"><strong>本站所有文章由本站和原作者保留一切权力，仅在保留本版权信息、原文链接、原文作者的情况下允许转载，转载请勿删改原文内容， 并不得用于商业用途。 谢谢合作。 
</strong></span></p><p><span style="font-family:宋体; font-size:12pt"><strong>原文链接:<a href="http://www.cuteqt.com/blog/?p=116"><span style="color:blue; text-decoration:underline">Qt经典出错信息之undefined reference to `vtable for classname</span></a>
			</strong></span></p><p>
 </p><p><span style="font-family:宋体; font-size:12pt">这个出错信息太常见了，用过Qt两个月以上的朋友基本上都能自己解决了，因为太经典了，可以给新手参考。
</span></p><p><span style="font-family:宋体; font-size:12pt">出错信息一般类似:undefined reference to `vtable for classname MyWidget`<br/>在执行make命令后出现。
</span></p><p><span style="font-family:宋体; font-size:12pt">出错原因是在定义类的时候为了能使用signals和slot,在类定义的后面加了Q_OBJECT引起。 因为Q_OBJECT是一个宏，在不同的类中展开是不同的代码，例如在mywidgeth.h中生成的
</span></p><p><span style="font-family:宋体; font-size:12pt">public:
</span></p><p><span style="font-family:宋体; font-size:12pt">template  inline void qt_check_for_QOBJECT_macro(const T &amp;_q_argument) const {
</span></p><p><span style="font-family:宋体; font-size:12pt">int i = qYouForgotTheQ_OBJECT_Macro(this, &amp;_q_argument); i = i;
</span></p><p><span style="font-family:宋体; font-size:12pt">}
</span></p><p>
 </p><p><span style="font-family:宋体; font-size:12pt">static const QMetaObject staticMetaObject;
</span></p><p><span style="font-family:宋体; font-size:12pt"><span style="color:red">virtual</span> const QMetaObject *metaObject() const;
</span></p><p><span style="font-family:宋体; font-size:12pt"><span style="color:red">virtual</span> void *qt_metacast(const char *);
</span></p><p><span style="font-family:宋体; font-size:12pt">static inline QString tr(const char *s, const char *c = 0) {
</span></p><p><span style="font-family:宋体; font-size:12pt">    return staticMetaObject.tr(s, c);
</span></p><p><span style="font-family:宋体; font-size:12pt">}
</span></p><p><span style="font-family:宋体; font-size:12pt">static inline QString trUtf8(const char *s, const char *c = 0)
</span></p><p><span style="font-family:宋体; font-size:12pt">{
</span></p><p><span style="font-family:宋体; font-size:12pt">    return staticMetaObject.trUtf8(s, c);
</span></p><p><span style="font-family:宋体; font-size:12pt">}
</span></p><p><span style="font-family:宋体; font-size:12pt">static inline QString tr(const char *s, const char *c, int n) {
</span></p><p><span style="font-family:宋体; font-size:12pt"> return staticMetaObject.tr(s, c, n);
</span></p><p><span style="font-family:宋体; font-size:12pt">}
</span></p><p><span style="font-family:宋体; font-size:12pt">static inline QString trUtf8(const char *s, const char *c, int n) {
</span></p><p><span style="font-family:宋体; font-size:12pt">return staticMetaObject.trUtf8(s, c, n);
</span></p><p><span style="font-family:宋体; font-size:12pt">}
</span></p><p><span style="font-family:宋体; font-size:12pt"><span style="color:red">virtual</span> int qt_metacall(QMetaObject::Call, int, void **); private:
</span></p><p><span style="font-family:宋体; font-size:12pt">可以看到以上的代码声明了3个从父类继承的3个虚函数。本来这三个函数的实现应该是由moc_mywidget.cpp来完成。<br/>而当前的错误正是因为Makefile里没有将moc_mywidget.cpp加入编译引起。
</span></p><p><span style="font-family:宋体; font-size:12pt">Makefile背后的原因是qmake，因为Qt的编译系统是通过qmake将.pro文件转换成Makefile文件。当qmake扫描.h代码时发现有Q_OBJECT这样字眼的代码时，会将一个用moc生成moc_xxx.cpp代码的依赖关系写到Makefile里。如果扫描时没有找到Q_OBJECT就不会生成额外的moc_xxx.cpp这样的文件。
</span></p><p><span style="font-family:宋体; font-size:12pt">出现最初一幕的原因是在执行qmake的时候.h代码里并没有O_OBJECT这样的代码。而执行make的时候.h里已经有Q_OBJECT了，解决的方法就是重新执行qmake，然后执行make.
</span></p><p><span style="font-family:宋体; font-size:12pt">——
</span></p><p><span style="font-family:宋体; font-size:12pt">shiroki：另外我再加一句， 还有一种可能性是写代码的人把所有的代码都写在了.cpp文件中。要知道moc工具只读.h文件，如果把Q_OBJECT宏放在cpp里moc是看不到的……所以大家写代码还是要遵守声明放.h实现放cpp的规矩比较好。
</span></p><img src ="http://www.cppblog.com/izualzhy/aggbug/159246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-10-28 00:16 <a href="http://www.cppblog.com/izualzhy/archive/2011/10/28/159246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QtExample_QXmlStreamWriter Bookmarks</title><link>http://www.cppblog.com/izualzhy/archive/2011/06/19/148970.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Sun, 19 Jun 2011 09:13:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/06/19/148970.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/148970.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/06/19/148970.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/148970.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/148970.html</trackback:ping><description><![CDATA[<img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QTreeWidget__setItemExpanded.png" width="484" longdesc="" height="701" /><br /><br /><br />
<p>程序运行效果图<br /><br />负责处理xml文件的是XbelWriter，XbelReader，界面的实现是由MainWindow完成的</p>
<p>保存后的xbel文件前几行是这样的<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE xbel&gt;<br />&lt;xbel version="1.0"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;folder folded="yes"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Literate Programming&lt;/title&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bookmark href="<a href="http://www.vivtek.com/litprog.html">http://www.vivtek.com/litprog.html</a>"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Synopsis of Literate Programming&lt;/title&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bookmark&gt;<br />如果不断用readNext（），即以下几行代码读取文件的话<br />&nbsp;&nbsp;&nbsp; while (!xml.atEnd()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qDebug() &lt;&lt; "name " &lt;&lt; xml.name() &lt;&lt; "tokentype " &lt;&lt; xml.tokenType();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (xml.isCharacters()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qDebug() &lt;&lt; xml.text();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xml.readNext();<br />&nbsp;&nbsp;&nbsp; }<br />前几行输出：<br />name&nbsp; "" tokentype&nbsp; 0 <br />name&nbsp; "" tokentype&nbsp; 2 <br />name&nbsp; "" tokentype&nbsp; 8 <br />name&nbsp; "xbel" tokentype&nbsp; 4 <br />name&nbsp; "" tokentype&nbsp; 6 <br />"<br />&nbsp;&nbsp;&nbsp; " <br />name&nbsp; "folder" tokentype&nbsp; 4 <br />name&nbsp; "" tokentype&nbsp; 6 <br />"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " <br />name&nbsp; "title" tokentype&nbsp; 4 <br />name&nbsp; "" tokentype&nbsp; 6 <br />"Literate Programming" <br />name&nbsp; "title" tokentype&nbsp; 5 <br />name&nbsp; "" tokentype&nbsp; 6 <br />"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " <br />name&nbsp; "bookmark" tokentype&nbsp; 4 <br />name&nbsp; "" tokentype&nbsp; 6 <br />"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " <br />name&nbsp; "title" tokentype&nbsp; 4 <br />name&nbsp; "" tokentype&nbsp; 6 <br />"Synopsis of Literate Programming" <br />name&nbsp; "title" tokentype&nbsp; 5 <br />结合源代码里关于Tokentype的enum定义：<br />enum TokenType {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NoToken = 0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Invalid,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StartDocument,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EndDocument,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StartElement,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EndElement,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Characters,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Comment,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DTD,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EntityReference,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProcessingInstruction<br />&nbsp;&nbsp;&nbsp; };<br />可以看出：<br />1.readNext就是一个一个的来读，碰到&lt;xxx&gt;,&lt;/xxx&gt;,以及...&gt;xxx&lt;...的文字<br />&nbsp;理一下读取的流程：<br />&nbsp; 1.没有读取任何东西，NoToken<br />&nbsp; 2.读取&lt;?xml version="1.0" encoding="UTF-8"?&gt;，StartDocument<br />&nbsp; 3.读取&lt;!DOCTYPE xbel&gt;，DTD<br />&nbsp; 4.读取&lt;xbel version="1.0"&gt;，StartElement<br />&nbsp; 5.读取&lt;xbel version="1.0"&gt;与&lt;folder folded="yes"&gt;之间的characters，如果打印相应的unicode出来的话，是10 32 32 32 32<br />&nbsp;即1个换行+4个空格，直接打印就是<br />"<br />&nbsp;&nbsp;&nbsp; " <br />这个了，可见...&gt;xxx&lt;...的文字都会读取，即使是换行/空格之类的<br />&nbsp; 6.读取&lt;folder folded="yes"&gt;，StartElement<br />&nbsp; 。。。。。。<br />2.<br />遇到这种&lt;separator/&gt;则类似于&lt;separator&gt;&lt;/separator&gt;<br />name&nbsp; "separator" type&nbsp; 4 <br />name&nbsp; "separator" type&nbsp; 5 <br />利用void QXmlStreamWriter::writeEmptyElement("separator")可以写入成这样</p>
<p>1.XbelWriter Class<br />写入的过程其实是很简单的，具体看代码：<br />&nbsp;bool XbelWriter::writeFile(QIODevice *device)<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp; xml.setDevice(device);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; xml.writeStartDocument();//生成L1<br />&nbsp;&nbsp;&nbsp;&nbsp; xml.writeDTD("&lt;!DOCTYPE xbel&gt;");//生成L2<br />&nbsp;&nbsp;&nbsp;&nbsp; xml.writeStartElement("xbel");//与下一行共同生成L3<br />&nbsp;&nbsp;&nbsp;&nbsp; xml.writeAttribute("version", "1.0");<br />&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; treeWidget-&gt;topLevelItemCount(); ++i)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writeItem(treeWidget-&gt;topLevelItem(i));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; xml.writeEndDocument();<br />&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />&nbsp;}<br />2.XbelReader Class<br />首先读取到合适的Element<br />&nbsp;bool XbelReader::read(QIODevice *device)<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp; xml.setDevice(device);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if (xml.readNextStartElement()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (xml.name() == "xbel" &amp;&amp; xml.attributes().value("version") == "1.0")//即读到name为xbel，属性version为1.0的Element时<br />//The actual process of reading only takes place if the file is a valid XBEL 1.0 file.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readXBEL();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));<br />&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; return !xml.error();<br />&nbsp;}<br />由注释可以看到工作函数是readXBEL(),整个流程由这几行代码完成（里面函数用到递归）<br />void XbelReader::readXBEL()<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp; Q_ASSERT(xml.isStartElement() &amp;&amp; xml.name() == "xbel");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; while (xml.readNextStartElement()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (xml.name() == "folder")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readFolder(0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (xml.name() == "bookmark")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readBookmark(0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (xml.name() == "separator")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readSeparator(0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xml.skipCurrentElement();<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;}<br />看下skipCurrentElement()的源代码：<br />void QXmlStreamReader::skipCurrentElement()<br />{<br />&nbsp;&nbsp;&nbsp; int depth = 1;<br />&nbsp;&nbsp;&nbsp; while (depth &amp;&amp; readNext() != Invalid) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isEndElement())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --depth;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (isStartElement())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++depth;<br />&nbsp;&nbsp;&nbsp; }<br />}，可以看到变量depth在进入一个新的element则+1，出来则-1<br />因此直到现在的这个element结束（遇到相应的&lt;/xxx&gt;），函数才结束退出<br />Qt Assistant里的注释：<br />The readXBEL() function reads the name of a startElement and calls the appropriate function to read it, depending on whether if its a "folder", "bookmark" or "separator". Otherwise, it calls skipCurrentElement(). <br />即如果Element的name为folder,bookmark,separator时，读入内容，否则skip<br />具体会遇到的有这么几种：<br />&lt;folder folded="yes"&gt;<br />&lt;title&gt;Literate Programming&lt;/title&gt;<br />&lt;bookmark href="<a href="http://www.vivtek.com/litprog.html">http://www.vivtek.com/litprog.html</a>"&gt;<br />&lt;separator/&gt;<br />需要不同的函数来处理<br />例子里分别用了<br />readTitle(),readSeparator(),readFolder(),readBookmark()</p>
<p>我主要学习了下readFolder()<br />fold有两种情况<br />&lt;folder folded="yes"&gt;<br />&lt;folder folded="no"&gt;<br />读取时差别的处理代码<br />&nbsp;&nbsp;&nbsp; QTreeWidgetItem *folder = createChildItem(item);<br />&nbsp;&nbsp;&nbsp; bool folded = (xml.attributes().value("folded") != "no");<br />&nbsp;&nbsp;&nbsp; treeWidget-&gt;setItemExpanded(folder, !folded);<br />第三行注释掉后对比下图片<br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QXmlStreamBookmarks.png" width="481" height="352" /><br />可见默认是不expand的<br />Sets the item referred to by item to either closed or opened, depending on the value of expand.</p>
<p>This function is deprecated. Use QTreeWidgetItem::setExpanded() instead.<br />void QTreeWidgetItem::setExpanded ( bool expand )<br />Expands the item if expand is true, otherwise collapses the item<br />主要是展开还是摺叠项。<br />folder下面的element可能name为title，bookmark，separator，还可能再由folder，像Useful C++ Links下面还有STL Qt等，需要递归处理，因此还需要以下代码<br />&nbsp;&nbsp;&nbsp; while (xml.readNextStartElement()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (xml.name() == "title")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readTitle(folder);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (xml.name() == "folder")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readFolder(folder);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (xml.name() == "bookmark")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readBookmark(folder);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (xml.name() == "separator")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readSeparator(folder);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xml.skipCurrentElement();<br />&nbsp;&nbsp;&nbsp; }<br />只不过跟readXBEL里参数不同</p>
<p>再看下while-loop condition<br />bool QXmlStreamReader::readNextStartElement ()<br />Reads until the next start element within the current element. Returns true when a start element was reached. When the end element was reached, or when an error occurred, false is returned.</p>
<p>The current element is the element matching the most recently parsed start element of which a matching end element has not yet been reached. When the parser has reached the end element, the current element becomes the parent element.</p>
<p>This is a convenience function for when you're only concerned with parsing XML elements. <br />看下该函数源代码：<br />bool QXmlStreamReader::readNextStartElement()<br />{<br />&nbsp;&nbsp;&nbsp; while (readNext() != Invalid) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isEndElement())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (isStartElement())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return false;<br />}<br />可以看到是读取下一个记号，如果是endElement，则返回false，否则true<br />再对比下xml文件看下该函数是如何用来在这个大的element内部遍历的<br />&lt;folder folded="yes"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Literate Programming&lt;/title&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bookmark href="<a href="http://www.vivtek.com/litprog.html">http://www.vivtek.com/litprog.html</a>"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Synopsis of Literate Programming&lt;/title&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bookmark&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bookmark href="<a href="http://vasc.ri.cmu.edu/old_help/Programming/Literate/literate.html">http://vasc.ri.cmu.edu/old_help/Programming/Literate/literate.html</a>"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Literate Programming: Propaganda and Tools&lt;/title&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bookmark&gt;<br />1.读到记号为&lt;title&gt;，进入readTitle()<br />2.读取内容，记号移动到&lt;/title&gt;<br />3.进入while条件，即readNextStartElement()，此时虽然TokenType是EndElement，但是readNext后，变为startElement，即bookmark，进入readBookmark()<br />4.同folder，bookmark也一直要读到&lt;/bookmark&gt;</p>
<p>再看下<br />QTreeWidgetItem *XbelReader::createChildItem(QTreeWidgetItem *item)<br />{<br />&nbsp;&nbsp;&nbsp; QTreeWidgetItem *childItem;<br />&nbsp;&nbsp;&nbsp; if (item) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; childItem = new QTreeWidgetItem(item);<br />&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; childItem = new QTreeWidgetItem(treeWidget);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; childItem-&gt;setData(0, Qt::UserRole, xml.name().toString());<br />&nbsp;&nbsp;&nbsp; return childItem;<br />}<br />setData参数可以指定不同的role<br />Qt::UserRole&nbsp;32&nbsp;The first role that can be used for application-specific purposes.<br />通过相应的data函数可以取出该QString<br />通过给<br />QTreeWidgetItem的构造函数传入不同的参数，可以传入QTreeWidget，也可以是QTreeWidgetItem<br />QTreeWidget会根据各个item的关系而排列好缩进？关于QTreeWidget还没用过，有空要学习一下。<br /></p><img src ="http://www.cppblog.com/izualzhy/aggbug/148970.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-06-19 17:13 <a href="http://www.cppblog.com/izualzhy/archive/2011/06/19/148970.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QtExample______DomBookmarks</title><link>http://www.cppblog.com/izualzhy/archive/2011/06/19/148969.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Sun, 19 Jun 2011 09:09:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/06/19/148969.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/148969.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/06/19/148969.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/148969.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/148969.html</trackback:ping><description><![CDATA[<p>先看下程序运行的结果图<img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/DomBookmarks.png" width="478" height="349" /><br /></p>
<p>跟使用QXmlStreamReader QXmlStreamWriter是一样的，区别在于处理的过程。<br />前一个例子主要是传参的方式，将QTreeWidget传给xmlReader，xmlWriter<br />读取xml到QTreeWidget里，随着读入添加item到里面，写的时候则遍历这个QTreeWidget，把item写入到xml文件<br />这个例子则是由QTreeWidget派生一个XbelTree的类出来，私有成员里有一个QDomDocument的对象。<br />算是两种处理方式吧，但传参和组合的方式每个例子都是可以用的，可能只是QXmlStream和QDom更适合哪种方式里了。<br />这个例子主要是学习QDom Classes</p>
<p>先贴一个Qt Assistant里的一段代码<br />The QDom classes are typically used as follows:</p>
<p>&nbsp;QDomDocument doc("mydocument");<br />&nbsp;QFile file("mydocument.xml");<br />&nbsp;if (!file.open(QIODevice::ReadOnly))<br />&nbsp;&nbsp;&nbsp;&nbsp; return;<br />&nbsp;if (!doc.setContent(&amp;file)) {<br />&nbsp;&nbsp;&nbsp;&nbsp; file.close();<br />&nbsp;&nbsp;&nbsp;&nbsp; return;<br />&nbsp;}<br />&nbsp;file.close();</p>
<p>&nbsp;// print out the element names of all elements that are direct children<br />&nbsp;// of the outermost element.<br />&nbsp;QDomElement docElem = doc.documentElement();</p>
<p>&nbsp;QDomNode n = docElem.firstChild();<br />&nbsp;while(!n.isNull()) {<br />&nbsp;&nbsp;&nbsp;&nbsp; QDomElement e = n.toElement(); // try to convert the node to an element.<br />&nbsp;&nbsp;&nbsp;&nbsp; if(!e.isNull()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; qPrintable(e.tagName()) &lt;&lt; endl; // the node really is an element.<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp; n = n.nextSibling();<br />&nbsp;}</p>
<p>&nbsp;// Here we append a new element to the end of the document<br />&nbsp;QDomElement elem = doc.createElement("img");<br />&nbsp;elem.setAttribute("src", "myimage.png");<br />&nbsp;docElem.appendChild(elem);</p>
<p>Once doc and elem go out of scope, the whole internal tree representing the XML document is deleted.</p>
<p>To create a document using DOM use code like this:</p>
<p>&nbsp;QDomDocument doc("MyML");<br />&nbsp;QDomElement root = doc.createElement("MyML");<br />&nbsp;doc.appendChild(root);</p>
<p>&nbsp;QDomElement tag = doc.createElement("Greeting");<br />&nbsp;root.appendChild(tag);</p>
<p>&nbsp;QDomText t = doc.createTextNode("Hello World");<br />&nbsp;tag.appendChild(t);</p>
<p>&nbsp;QString xml = doc.toString();</p>
<p>加上这几句话产生xml文件查看内容<br />&nbsp;&nbsp;&nbsp; QFile file("mydocument.xml");<br />&nbsp;&nbsp;&nbsp; file.open(QIODevice::ReadWrite);</p>
<p>&nbsp;&nbsp;&nbsp; QTextStream m_out(&amp;file);</p>
<p>&nbsp;&nbsp;&nbsp; doc.save(m_out,4);<br />&nbsp;&nbsp;&nbsp; file.close();<br />产生的document内容：<br />&lt;!DOCTYPE MyML&gt;<br />&lt;MyML&gt;<br />&nbsp;&nbsp;&nbsp; &lt;Greeting&gt;Hello Wolrd!&lt;/Greeting&gt;<br />&lt;/MyML&gt;</p>
<p>1.<br />XbelTree继承自QTreeWidget<br />每一列的大小是否可以自由改变，由该函数决定<br />void QHeaderView::setResizeMode ( ResizeMode mode )<br />Sets the constraints on how the header can be resized to those described by the given mode.<br />The resize mode specifies the behavior of the header sections. It can be set on the entire header view or on individual sections using setResizeMode().</p>
<p><br />Constant&nbsp;Value&nbsp;Description<br />QHeaderView::Interactive&nbsp;0&nbsp;The user can resize the section. The section can also be resized programmatically using resizeSection(). The section size defaults to defaultSectionSize. (See also cascadingSectionResizes.)<br />QHeaderView::Fixed&nbsp;2&nbsp;The user cannot resize the section. The section can only be resized programmatically using resizeSection(). The section size defaults to defaultSectionSize.<br />QHeaderView::Stretch&nbsp;1&nbsp;QHeaderView will automatically resize the section to fill the available space. The size cannot be changed by the user or programmatically.<br />QHeaderView::ResizeToContents&nbsp;3&nbsp;QHeaderView will automatically resize the section to its optimal size based on the contents of the entire column or row. The size cannot be changed by the user or programmatically. (This value was introduced in 4.2)</p>
<p>最上一排的headview的指针通过该函数获得<br />QHeaderView * QTreeView::header () const<br />Returns the header for the tree view.<br />2.<br />&lt;img src="myimg.png"&gt;<br />tagName:img<br />name:src<br />value:"myimg.png"</p>
<p>QDom<br />A<br />QDomElement QDomDocument::documentElement () const<br />Returns the root element of the document.<br />该函数返回的即在DOCTYPE后最大的一个Element，即root<br />B<br />QDomElement QDomNode::firstChildElement ( const QString &amp; tagName = QString() ) const<br />Returns the first child element with tag name tagName if tagName is non-empty; otherwise returns the first child element. Returns a null element if no such child exists.<br />该函数返回指定tagName的QDomElement<br />相关的有<br />firstChildElement(),lastChildElement(), previousSiblingElement(), and nextSiblingElement().<br />都需要指定tagName<br />当子结点的不是一个Element时，使用函数获得第一个子节点<br />QDomNode QDomNode::firstChild () const<br />Returns the first child of the node. If there is no child node, a null node is returned. Changing the returned node will also change the node in the document tree.<br />获得最后一个子结点<br />QDomNode QDomNode::lastChild () const<br />Returns the last child of the node. If there is no child node, a null node is returned. Changing the returned node will also change the node in the document tree.</p>
<p>See also firstChild() and childNodes().<br />获得下一个子节点<br />QDomNode QDomNode::nextSibling () const<br />Returns the next sibling in the document tree. Changing the returned node will also change the node in the document tree.</p>
<p>If you have XML like this:</p>
<p>&nbsp;&lt;h1&gt;Heading&lt;/h1&gt;<br />&nbsp;&lt;p&gt;The text...&lt;/p&gt;<br />&nbsp;&lt;h2&gt;Next heading&lt;/h2&gt;<br />and this QDomNode represents the &lt;p&gt; tag, nextSibling() will return the node representing the &lt;h2&gt; tag.</p>
<p>获得上一个子节点<br />QDomNode QDomNode::previousSibling () const<br />Returns the previous sibling in the document tree. Changing the returned node will also change the node in the document tree.</p>
<p>For example, if you have XML like this:</p>
<p>&nbsp;&lt;h1&gt;Heading&lt;/h1&gt;<br />&nbsp;&lt;p&gt;The text...&lt;/p&gt;<br />&nbsp;&lt;h2&gt;Next heading&lt;/h2&gt;<br />and this QDomNode represents the &amp;lt;p&amp;gt; tag, previousSibling() will return the node representing the &amp;lt;h1&amp;gt; tag.<br />你也可以直接获得结点的列表<br />QDomNodeList QDomNode::childNodes () const<br />Returns a list of all direct child nodes.</p>
<p>Most often you will call this function on a QDomElement object.</p>
<p>For example, if the XML document looks like this:</p>
<p>&nbsp;&lt;body&gt;<br />&nbsp;&lt;h1&gt;Heading&lt;/h1&gt;<br />&nbsp;&lt;p&gt;Hello &lt;b&gt;you&lt;/b&gt;&lt;/p&gt;<br />&nbsp;&lt;/body&gt;<br />Then the list of child nodes for the "body"-element will contain the node created by the &amp;lt;h1&amp;gt; tag and the node created by the &amp;lt;p&amp;gt; tag.</p>
<p>The nodes in the list are not copied; so changing the nodes in the list will also change the children of this node.</p>
<p><br />&nbsp;</p><img src ="http://www.cppblog.com/izualzhy/aggbug/148969.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-06-19 17:09 <a href="http://www.cppblog.com/izualzhy/archive/2011/06/19/148969.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转 Qt通过dom方式修改xml </title><link>http://www.cppblog.com/izualzhy/archive/2011/06/09/148379.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Thu, 09 Jun 2011 15:21:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/06/09/148379.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/148379.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/06/09/148379.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/148379.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/148379.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body">
<p>DOM是一种解析由万维网协会(W3C)所开发的XML文档的标准应用程序编程接口。Qt提供一套用于读取、操作和编写XML文档的非验证型二级DOM实现。</p>
<p>DOM把XML文件表示成内存中的一棵树。我们可以按需要遍历这个DOM树，也可以修改这个树并把它作为XML文件保存到磁盘中。</p>
<p>让我们考虑如下这个XML文档：</p>
<blockquote>
<p>&lt;doc&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;quote&gt;Scio me nihil scire&lt;/quote&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;translation&gt;I know that I know nothing&gt;&lt;/translation&gt;</p>
<p>&lt;/doc&gt;</p></blockquote>
<p>它对于如下所示的DOM树：</p>
<blockquote>
<p>Document</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element(doc)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element(quote)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Text(&#8220;Scio me nihil scire&#8221;)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element(translation)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Text(&#8220;I know that I know nothing&#8221;)</p>
<p>这个DOM树包含不同类型的节点。例如，Element节点对应打开标签以及与它匹配的关闭标签。<font color="#0000ff">在这两个标签之间的内容则作为这个Element节点的子节点出现。</font><font color="#000000">（注意蓝色字体）</font></p>
<p><font color="#000000">上面的介绍主要是用来说明dom树的结构情况，下面则进入正题看如何通过qt来达到修改xml文件的目的。本文中主要说明如何修改xml属性值以及节点值，</font></p>
<p><font color="#000000">修改属性值的代码如下：</font></p><pre class="code"><span style="color: blue">bool </span><span style="color: #020002">QXmlEdit</span>::<span style="color: #020002">SetAValue</span>(<span style="color: blue">const </span><span style="color: #020002">QString </span>&amp;<span style="color: #020002">key</span>, <span style="color: blue">const </span><span style="color: #020002">QVariant </span>&amp;<span style="color: #020002">value</span>)
{
    <span style="color: blue">try
    </span>{
        <span style="color: #020002">QString tag</span>;
        <span style="color: #020002">QString attName</span>;
        <span style="color: #020002">QStringList sl</span>=<span style="color: #020002">key</span>.<span style="color: #020002">split</span>(<span style="color: #a31515">"/"</span>);
        <span style="color: #020002">tag </span>= <span style="color: #020002">sl</span>.<span style="color: #020002">at</span>(0);
        <span style="color: #020002">attName </span>= <span style="color: #020002">sl</span>.<span style="color: #020002">at</span>(1);

        <span style="color: #020002">QDomElement docElem </span>= <span style="color: #020002">doc</span>.<span style="color: #020002">documentElement</span>();
        <span style="color: #020002">QDomNodeList nodeList </span>= <span style="color: #020002">docElem</span>.<span style="color: #020002">elementsByTagName</span>(<span style="color: #020002">tag</span>);
        <span style="color: blue">if </span>(<span style="color: #020002">nodeList</span>.<span style="color: #020002">count</span>() &gt;0 )
        {
            <span style="color: #020002">QDomElement el </span>= <span style="color: #020002">nodeList</span>.<span style="color: #020002">at</span>(0).<span style="color: #020002">toElement</span>();
           <font color="#000000"> <span style="color: #020002">el</span>.<span style="color: #020002">setAttribute</span>(<span style="color: #020002">attName</span>,<span style="color: #020002">value</span>.<span style="color: #020002">toString</span>());</font>  <span style="color: green">//设置属性值</span></pre><pre class="code"><span style="color: green">            </span><span style="color: #020002">QFile file</span>(<span style="color: #020002">fileName</span>);
            <span style="color: blue">if </span>(!<span style="color: #020002">file</span>.<span style="color: #020002">open</span>(<span style="color: #020002">QIODevice</span>::<span style="color: #020002">WriteOnly </span>| <span style="color: #020002">QIODevice</span>::<span style="color: #020002">Text</span>))
            {
                <span style="color: blue">return false</span>;
            }
            <span style="color: #020002">QTextStream out</span>(&amp;<span style="color: #020002">file</span>);
            <span style="color: #020002">doc</span>.<span style="color: #020002">save</span>(<span style="color: #020002">out</span>,4);
        }
        <span style="color: blue">return true</span>;
    }
    <span style="color: blue">catch </span>(...)
    {
        <span style="color: blue">return false</span>;
    } 
}</pre><pre class="code"><font face="Verdana">修改节点值的代码如下：</font></pre><pre class="code"><span style="color: blue">bool </span><span style="color: #020002">QXmlEdit</span>::<span style="color: #020002">SetTValue</span>(<span style="color: blue">const </span><span style="color: #020002">QString </span>&amp;<span style="color: #020002">key</span>, <span style="color: blue">const </span><span style="color: #020002">QVariant </span>&amp;<span style="color: #020002">value</span>)
{
    <span style="color: blue">try
    </span>{
        <span style="color: #020002">QDomElement docElem </span>= <span style="color: #020002">doc</span>.<span style="color: #020002">documentElement</span>();
        <span style="color: #020002">QDomNodeList nodeList </span>= <span style="color: #020002">docElem</span>.<span style="color: #020002">elementsByTagName</span>(<span style="color: #020002">key</span>);
        <span style="color: blue">if </span>(<span style="color: #020002">nodeList</span>.<span style="color: #020002">count</span>() &gt;0 )
        {
            <span style="color: #020002">QDomElement el </span>= <span style="color: #020002">nodeList</span>.<span style="color: #020002">at</span>(0).<span style="color: #020002">toElement</span>();  <span style="color: green">//tag为key的节点
            </span><span style="color: #020002">QDomNode oldnode </span>= <span style="color: #020002">el</span>.<span style="color: #020002">firstChild</span>();           <span style="color: green">//标签之间的内容作为节点的子节点出现，得到原来的子节点
            </span><span style="color: #020002">el</span>.<span style="color: #020002">firstChild</span>().<span style="color: #020002">setNodeValue</span>(<span style="color: #020002">value</span>.<span style="color: #020002">toString</span>());   <span style="color: green">//用提供的value值来设置子节点的内容</span></pre><pre class="code"><span style="color: green">            </span><span style="color: #020002">QDomNode newnode </span>= <span style="color: #020002">el</span>.<span style="color: #020002">firstChild</span>();               <span style="color: green">//值修改过后的子节点</span></pre><pre class="code"><span style="color: green">            </span><span style="color: #020002">el</span>.<span style="color: #020002">replaceChild</span>(<span style="color: #020002">newnode</span>,<span style="color: #020002">oldnode</span>);                 <span style="color: green">//调用节点的replaceChild方法实现修改功能
        
            </span><span style="color: #020002">QFile file</span>(<span style="color: #020002">fileName</span>);
            <span style="color: blue">if </span>(!<span style="color: #020002">file</span>.<span style="color: #020002">open</span>(<span style="color: #020002">QIODevice</span>::<span style="color: #020002">WriteOnly </span>| <span style="color: #020002">QIODevice</span>::<span style="color: #020002">Text</span>))
            {
                <span style="color: blue">return false</span>;
            }
            <span style="color: #020002">QTextStream out</span>(&amp;<span style="color: #020002">file</span>);
            <span style="color: #020002">doc</span>.<span style="color: #020002">save</span>(<span style="color: #020002">out</span>,4);
        }
        <span style="color: blue">return true</span>;
    }
    <span style="color: blue">catch </span>(...)
    {
        <span style="color: blue">return false</span>;
    }
}</pre><a href="http://11011.net/software/vspaste" target="_blank"></a></blockquote>
<p>至此我们就实现了修改xml属性及text的功能。</p></div><script type="text/javascript">
if ($ != jQuery) {
	$ = jQuery.noConflict();
}
var isLogined = true;
var cb_blogId = 28010;
var cb_entryId = 1674067;
var cb_blogApp = "mxly";
var cb_blogUserGuid = "7f793d0b-63cf-dd11-9e4d-001cf0cd104b";
var cb_entryCreatedDate = '2010/2/26 10:52:00';
</script><img src ="http://www.cppblog.com/izualzhy/aggbug/148379.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-06-09 23:21 <a href="http://www.cppblog.com/izualzhy/archive/2011/06/09/148379.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QtExample___OrderForm</title><link>http://www.cppblog.com/izualzhy/archive/2011/05/22/146929.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Sun, 22 May 2011 07:19:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/05/22/146929.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/146929.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/05/22/146929.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/146929.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/146929.html</trackback:ping><description><![CDATA[<p><img height="528" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/OrderFormExample.png" width="1239" border="0" /><br />Enter Customer Details是Order Form窗口点击File-New后的结果<br />当Enter Customer Details的Name或者Address为空时，会弹出Incom<font>p</font>lete Form的MessageBox<br />学习该例子主要是想了解基于QTextCursor的操作方法，文档布局<br />1<br />QDialogButtonBox和QMessageBox<br />A<br />Enter Customer Details窗口的右下Cancel OkButton就是拿QDialogButtonBox生成的，之所以用这个Qt assitant给出的解释是<br />Also, a QCheckBox and a QDialogButtonBox are defined; the former to <font>p</font>rovide the user with the o<font>p</font>tion to receive information on <font>p</font>roducts and offers, and the latter to ensure that buttons used are arranged according to the user's native <font>p</font>latform。<br />除了这点外，用起来也比单独去定义Button方便，体现在这里<br />buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok<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; | QDialogButtonBox::Cancel);<br />connect(buttonBox, SIGNAL(acce<font>p</font>ted()), this, SLOT(verify()));<br />connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));</p>
<p>Ok Cancel Button可以直接使用，再看下acce<font>p</font>ted，rejected信号在什么情况下发送<br />void QDialogButtonBox::acce<font>p</font>ted ()&nbsp;&nbsp; [signal]<br />This signal is emitted when a button inside the button box is clicked, as long as it was defined with the Acce<font>p</font>tRole or YesRole.<br />void QDialogButtonBox::rejected ()&nbsp;&nbsp; [signal]<br />This signal is emitted when a button inside the button box is clicked, as long as it was defined with the RejectRole or NoRole.<br />，而Ok cancel Button的定义：<br />QDialogButtonBox::Ok&nbsp;0x00000400&nbsp;An "OK" button defined with the Acce<font>p</font>tRole.<br />。。。 <br />QDialogButtonBox::Cancel&nbsp;0x00400000&nbsp;A "Cancel" button defined with the RejectRole.<br />此外还有很多Button，如Save A<font>p</font><font>p</font>ly等，都定义在<br />enum QDialogButtonBox::StandardButton<br />flags QDialogButtonBox::StandardButtons里了。<br />用起来是不是很方便呢？<br />不过该类还有很多东西没看懂，如ActionRole等，感觉有空这个类可以单独学习一下。<br />B<br />Incom<font>p</font>lete Form Widget是一个QMEssgeBOx：：warning<br />之所以两个类归结为一个知识点，是因为QMessageBox与上面的类有一点还是很像的，那就是Button不用定义。。。<br />QMessageBox的Button都定义在这里了<br />enum QMessageBox::StandardButton<br />flags QMessageBox::StandardButtons<br />跟上面的很像<br />用起来也非常方便，看下Incom<font>p</font>lete Form Widget的相关代码<br />QMessageBox::StandardButton answer;<br />&nbsp;&nbsp;&nbsp;&nbsp; answer = QMessageBox::warning(this, tr("Incom<font>p</font>lete Form"),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tr("The form does not contain all the necessary information.\n"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Do you want to discard it?"),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QMessageBox::Yes | QMessageBox::No);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if (answer == QMessageBox::Yes)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reject();</p>
<p>关于warning的定义<br />Static <font>P</font>ublic Members<br />。。。<br />StandardButton&nbsp;warning ( QWidget * <font>p</font>arent, const QString &amp; title, const QString &amp; text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton )<br />注意是Static的<br />返回类型即为上面说的枚举类型<br />2.<br />QTableView的上边和左边1 2/1 2 3 4的窗口也可以进一步操作<br />通过<br />QHeaderView *&nbsp;horizontalHeader () const<br />拿到对应指针，例如<br />itemsTable-&gt;verticalHeader()-&gt;hide();就可以将左边的1 2 3 4隐藏了<br />3.<br />QAction * QMenu::addAction ( const QString &amp; text )<br />This convenience function creates a new action with text. The function adds the newly created action to the menu's list of actions, and returns it.<br />这个函数非常好用，因为可以自动创建一个action，返回值就是这个action的指针，同时另外几个重载函数有的更加方便<br />QAction * QMenu::addAction ( const QString &amp; text, const QObject * receiver, const char * member, const QKeySequence &amp; shortcut = 0 )<br />This is an overloaded function.</p>
<p>This convenience function creates a new action with the text text and an o<font>p</font>tional shortcut shortcut. The action's triggered() signal is connected to the receiver's member slot. The function adds the newly created action to the menu's list of actions and returns it.<br />在创建的时候，可以直接指定连接到的槽。<br />例子里这里分别用到了：<br />QAction *newAction = fileMenu-&gt;addAction(tr("&amp;New..."));<br />&nbsp;&nbsp;&nbsp;&nbsp; newAction-&gt;setShortcuts(QKeySequence::New);<br />&nbsp;&nbsp;&nbsp;&nbsp; <font>p</font>rintAction = fileMenu-&gt;addAction(tr("&amp;<font>P</font>rint..."), this, SLOT(<font>p</font>rintFile()));<br />&nbsp;&nbsp;&nbsp;&nbsp; <font>p</font>rintAction-&gt;setShortcuts(QKeySequence::<font>P</font>rint);<br />&nbsp;&nbsp;&nbsp;&nbsp; <font>p</font>rintAction-&gt;setEnabled(false);<br />4.<br />Order Form Widget里主窗口就是QTabWidget<br />其下显示窗口是一个QTextEdit，通过利用QTextCursor QTextFrame等做的非常好看<br />因为这个排版之前完全不知道怎么去作，代码涉及了很多的类（都很简单的接口），所以跟着代码做了一遍注释学习了下<br />&nbsp;&nbsp;&nbsp;&nbsp; QTextCursor cursor(editor-&gt;textCursor());<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.move<font style="background-color: #ffd700">Position</font>(QTextCursor::Start);//取得指针并放在最开始的位置<br />&nbsp;&nbsp;&nbsp;&nbsp; QTextFrame *to<font>p</font>Frame = cursor.currentFrame();//Note that to<font>p</font>Frame is the editor's to<font>p</font>-level frame and is not shown in the document structure.<br />&nbsp;&nbsp;&nbsp;&nbsp; QTextFrameFormat to<font>p</font>FrameFormat = to<font>p</font>Frame-&gt;frameFormat();<br />&nbsp;&nbsp;&nbsp;&nbsp; to<font>p</font>FrameFormat.set<font><font>P</font>adding</font>(16);//设置内容的边距，去掉后对比下<img height="1003" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/setPadding.png" width="639" border="0" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp; to<font>p</font>Frame-&gt;setFrameFormat(to<font>p</font>FrameFormat);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; QTextCharFormat textFormat;<br />&nbsp;&nbsp;&nbsp;&nbsp; QTextCharFormat boldFormat;<br />&nbsp;&nbsp;&nbsp;&nbsp; boldFormat.setFontWeight(QFont::Bold);//设置字体，一会会用到</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; QTextFrameFormat referenceFrameFormat;<br />&nbsp;&nbsp;&nbsp;&nbsp; referenceFrameFormat.setBorder(1);<br />&nbsp;&nbsp;&nbsp;&nbsp; referenceFrameFormat.set<font><font>P</font>adding</font>(8);<br />&nbsp;&nbsp;&nbsp;&nbsp; referenceFrameFormat.set<font style="background-color: #ffd700">Position</font>(QTextFrameFormat::FloatRight);//该句使得显示位置从右边开始，改成Left后对比下<img height="994" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QTextFramFormat__setPosition.png" width="645" border="0" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp; referenceFrameFormat.setWidth(QTextLength(QTextLength::<font>P</font>ercentageLength, 40));//QTextLength有三种类型，含义如下<br />&nbsp;Constant&nbsp;Value&nbsp;Descri<font>p</font>tion<br />&nbsp;QTextLength::VariableLength&nbsp;0&nbsp;The width of the object is variable<br />&nbsp;QTextLength::FixedLength&nbsp;1&nbsp;The width of the object is fixed<br />&nbsp;QTextLength::<font>P</font>ercentageLength&nbsp;2&nbsp;The width of the object is in <font>p</font>ercentage of the maximum width<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertFrame(referenceFrameFormat);//关于该句的介绍<br />&nbsp;QTextFrame * QTextCursor::insertFrame ( const QTextFrameFormat &amp; format )<br />&nbsp;Inserts a frame with the given format at the current cursor <font style="background-color: #ffd700">position</font>(), moves the cursor <font style="background-color: #ffd700">position</font>() inside the frame, and returns the frame.</p>
<p>&nbsp;If the cursor holds a selection, the whole selection is moved inside the frame.<br />&nbsp;注意给的参数是QTextFramFormat，返回值是QTextFrame，光标会移动到该Frame内</p>
<p><br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText("A com<font>p</font>any", boldFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();//换行<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText("321 City Street");<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText("Industry <font>P</font>ark");<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText("Another country");</p>
<p><br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.set<font style="background-color: #ffd700">Position</font>(to<font>p</font>Frame-&gt;last<font style="background-color: #ffd700">Position</font>());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(name, textFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp; QString line;<br />&nbsp;&nbsp;&nbsp;&nbsp; foreach (line, address.s<font>p</font>lit("\n")) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(line);<br />&nbsp;&nbsp;&nbsp;&nbsp; }//光标被重新移动回来并且写入name address</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();//twice，一次表示换行，两次才会产生一个空行</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; QDate date = QDate::currentDate();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(tr("Date: %1").arg(date.toString("d MMMM yyyy")),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; textFormat);//取日期，insert。。。<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; QTextFrameFormat bodyFrameFormat;<br />&nbsp;&nbsp;&nbsp;&nbsp; bodyFrameFormat.setWidth(QTextLength(QTextLength::<font>P</font>ercentageLength, 100));<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertFrame(bodyFrameFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(tr("I would like to <font>p</font>lace an order for the following "<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; "items:"), textFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();//nserts standard text into the order form.</p>
<p>//接下来是一个<br />//A QTextTableFormat object, orderTableFormat, is used to hold the ty<font>p</font>e of item and the quantity ordered.<br />//用来存储orderItems及其数量<br />&nbsp;&nbsp;&nbsp;&nbsp; QTextTableFormat orderTableFormat;<br />&nbsp;&nbsp;&nbsp;&nbsp; orderTableFormat.setAlignment(Qt::AlignHCenter);<br />&nbsp;&nbsp;&nbsp;&nbsp; QTextTable *orderTable = cursor.insertTable(1, 2, orderTableFormat);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; QTextFrameFormat orderFrameFormat = cursor.currentFrame()-&gt;frameFormat();<br />&nbsp;&nbsp;&nbsp;&nbsp; orderFrameFormat.setBorder(1);<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.currentFrame()-&gt;setFrameFormat(orderFrameFormat);<br />//题外：关于QTextTable的S<font>p</font>acing和<font><font>P</font>adding</font>在QTextTable类的介绍了有个图</p>
<p>//感觉<font><font>p</font>adding</font>即为外围的边距，s<font>p</font>acing即为内部边距<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor = orderTable-&gt;cellAt(0, 0).firstCursor<font style="background-color: #ffd700">Position</font>();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(tr("<font>P</font>roduct"), boldFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor = orderTable-&gt;cellAt(0, 1).firstCursor<font style="background-color: #ffd700">Position</font>();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(tr("Quantity"), boldFormat);<br />//添加每列的标题<font>P</font> Quantity<br />//不过这样添加出来的cell是可以在界面上修改的，如何防止这点？<br />//editor-&gt;setReadOnly(true);会使整个页面不可编辑，所以不可用</p>
<p>&nbsp;for (int i = 0; i &lt; orderItems.count(); ++i) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Q<font>P</font>air&lt;QString,int&gt; item = orderItems[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int row = orderTable-&gt;rows();//当前行数</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; orderTable-&gt;insertRows(row, 1);//在最后添加额外一行<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor = orderTable-&gt;cellAt(row, 0).firstCursor<font style="background-color: #ffd700">Position</font>();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(item.first, textFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor = orderTable-&gt;cellAt(row, 1).firstCursor<font style="background-color: #ffd700">Position</font>();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(QString("%1").arg(item.second), textFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />//在这段代码后我加了一段代码测试了下<br />&nbsp;&nbsp;&nbsp; cursor.insertText("This is a test");<br />&nbsp;&nbsp;&nbsp; cursor.set<font style="background-color: #ffd700">Position</font>(cursor.currentFrame()-&gt;first<font style="background-color: #ffd700">Position</font>());<br />&nbsp;&nbsp;&nbsp; cursor.insertText("another test");<br />//<img height="979" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QTextTablePosition.png" width="635" border="0" /><br /><br />//至于cellAt（0，0）处的背景颜色，是这么改变的<br />&nbsp;QTextTableCell cell = orderTable-&gt;cellAt(0,0);<br />&nbsp;&nbsp;&nbsp; QTextCharFormat format = cell.format();<br />&nbsp;&nbsp;&nbsp; format.setBackground(Qt::green);<br />&nbsp;&nbsp;&nbsp; cell.setFormat(format);<br />/<img height="987" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QTextCharFormat__backGroundColor.png" width="642" border="0" />/<br /><br />//继续程序里的源代码<br />//The cursor is then moved back to to<font>p</font>Frame's last<font style="background-color: #ffd700">Position</font>() and more standard text is inserted.<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.set<font style="background-color: #ffd700">Position</font>(to<font>p</font>Frame-&gt;last<font style="background-color: #ffd700">Position</font>());//返回到to<font>p</font>Frame的正确位置开始输入</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(tr("<font>P</font>lease u<font>p</font>date my records to take account of the "<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; "following <font>p</font>rivacy information:"));<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />//Another QTextTable is inserted, to dis<font>p</font>lay the customer's <font>p</font>reference regarding offers.<br />&nbsp;&nbsp;&nbsp;&nbsp; QTextTable *offersTable = cursor.insertTable(2, 2);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; cursor = offersTable-&gt;cellAt(0, 1).firstCursor<font style="background-color: #ffd700">Position</font>();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(tr("I want to receive more information about your "<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; "com<font>p</font>any's <font>p</font>roducts and s<font>p</font>ecial offers."), textFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor = offersTable-&gt;cellAt(1, 1).firstCursor<font style="background-color: #ffd700">Position</font>();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(tr("I do not want to receive any <font>p</font>romotional information "<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; "from your com<font>p</font>any."), textFormat);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if (sendOffers)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor = offersTable-&gt;cellAt(0, 0).firstCursor<font style="background-color: #ffd700">Position</font>();<br />&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor = offersTable-&gt;cellAt(1, 0).firstCursor<font style="background-color: #ffd700">Position</font>();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText("X", boldFormat);</p>
<p>//The cursor is moved to insert "Sincerely" along with the customer's name. More blocks are inserted for s<font>p</font>acing <font>p</font>ur<font>p</font>oses. The <font>p</font>rintAction is enabled to indicate that an order form can now be <font>p</font>rinted.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; cursor.set<font style="background-color: #ffd700">Position</font>(to<font>p</font>Frame-&gt;last<font style="background-color: #ffd700">Position</font>());<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(tr("Sincerely,"), textFormat);<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertBlock();<br />&nbsp;&nbsp;&nbsp;&nbsp; cursor.insertText(name);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <font>p</font>rintAction-&gt;setEnabled(true);<br />&nbsp;}</p>
<p>其实总结下的话，整个界面的形成主要依赖于cursor的移动和insert<br />移动比如这样<br />cursor = offersTable-&gt;cellAt(0, 1).firstCursor<font style="background-color: #ffd700">Position</font>();<br />或者<br />cursor.set<font style="background-color: #ffd700">Position</font>(to<font>p</font>Frame-&gt;last<font style="background-color: #ffd700">Position</font>());等等<br />输入主要依靠QTextCursor的四个函数来完成的<br />void&nbsp;insertText ( const QString &amp; text, const QTextCharFormat &amp; format )<br />QTextFrame *&nbsp;insertFrame ( const QTextFrameFormat &amp; format )<br />void&nbsp;insertBlock ( const QTextBlockFormat &amp; format, const QTextCharFormat &amp; charFormat )<br />QTextTable *&nbsp;insertTable ( int rows, int columns, const QTextTableFormat &amp; format )<br />5.<br />关于这一句分析一下流程<br />buttonBox 的 acce<font>p</font>ted（）信号会触发DetailsDialog的verify（）槽，该槽函数会执行Dialog的acce<font>p</font>t() or reject()</p>
<p>void QDialog::acce<font>p</font>t ()&nbsp;&nbsp; [virtual slot]<br />Hides the modal dialog and sets the result code to Acce<font>p</font>ted.<br />void QDialog::reject ()&nbsp;&nbsp; [virtual slot]<br />Hides the modal dialog and sets the result code to Rejected.<br />void QDialog::done ( int r )&nbsp;&nbsp; [virtual slot]<br />Closes the dialog and sets its result code to r. If this dialog is shown with exec(), done() causes the local event loo<font>p</font> to finish, and exec() to return r.</p>
<p>//TODO：<br />最后的<font>p</font>rint界面用的Q<font>P</font>rintDialog来实现，有空可以看下<br />QTextCursor以及相关还需要进一步学习<br />o<font>p</font>enDialog函数里，不执行dialog.exec()<br />用dialog.show(),窗口没有show出来<br /></p><img src ="http://www.cppblog.com/izualzhy/aggbug/146929.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-05-22 15:19 <a href="http://www.cppblog.com/izualzhy/archive/2011/05/22/146929.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QtExample__LineEdit学习笔记</title><link>http://www.cppblog.com/izualzhy/archive/2011/05/18/146696.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Wed, 18 May 2011 13:09:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/05/18/146696.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/146696.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/05/18/146696.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/146696.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/146696.html</trackback:ping><description><![CDATA[<p>整个窗口如图所示<img height="364" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/LineEditExample.png" width="467" border="0" /><br /><br />先看下界面：<br />总体上框架使用QGridLayout布局，共5个GroupBox，每个GroupBox内部依旧使用QGridLayout布局，一个QLabel，如Mode：，一个QComboBox，如PasswordEchoOnEdit，一个QLineEdit，显示粗点的那个Echo即为GroupBox的标题，这样整个界面就设置OK了，非常简单，也十分美观</p>
<p>再说下功能：<br />5各QGroupBox分别对应5各方面的功能，也同时对应着QLineEidt的5个函数<br />从第一个开始说起：<br />显示方面的，看下类里面自定义的枚举，正好对应Echo 的ComboxBox的4个选项</p>
<p>enum QLineEdit::EchoMode<br />This enum type describes how a line edit should display its contents.</p>
<p>Constant&nbsp;Value&nbsp;Description<br />QLineEdit::Normal&nbsp;0&nbsp;Display characters as they are entered. This is the default.<br />QLineEdit::NoEcho&nbsp;1&nbsp;Do not display anything. This may be appropriate for passwords where even the length of the password should be kept secret.<br />QLineEdit::Password&nbsp;2&nbsp;Display asterisks instead of the characters actually entered.<br />QLineEdit::PasswordEchoOnEdit&nbsp;3&nbsp;Display characters as they are entered while editing otherwise display asterisks.<br />使用的函数是：<br />void&nbsp;setEchoMode ( EchoMode )<br />相关的函数查了下还有这两个<br />1.displayText : const QString<br />This property holds the displayed text.</p>
<p>If echoMode is Normal this returns the same as text(); if EchoMode is Password or PasswordEchoOnEdit it returns a string of asterisks text().length() characters long, e.g. "******"; if EchoMode is NoEcho returns an empty string, "".</p>
<p>By default, this property contains an empty string.<br />2.text : QString<br />This property holds the line edit's text.</p>
<p>Setting this property clears the selection, clears the undo/redo history, moves the cursor to the end of the line and resets the modified property to false. The text is not validated when inserted with setText().</p>
<p>The text is truncated to maxLength() length.</p>
<p>By default, this property contains an empty string.<br />顾名思义，displayText返回的是显示内容，如果时密码模式，那么返回**************星号<br />第二个：<br />Validator使用的函数是<br />void QLineEdit::setValidator ( const QValidator * v )<br />Sets this line edit to only accept input that the validator, v, will accept. This allows you to place any arbitrary constraints on the text which may be entered.</p>
<p>If v == 0, setValidator() removes the current input validator. The initial setting is to have no input validator (i.e. any input is accepted up to maxLength()).</p>
<p>See also validator(), QIntValidator, QDoubleValidator, and QRegExpValidator.<br />看下程序里是怎么用的<br />&nbsp;&nbsp;&nbsp;&nbsp; case 0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validatorLineEdit-&gt;setValidator(0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;&nbsp; case 1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validatorLineEdit-&gt;setValidator(new QIntValidator(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validatorLineEdit));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;&nbsp; case 2:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validatorLineEdit-&gt;setValidator(new QDoubleValidator(-999.0,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 999.0, 2, validatorLineEdit));<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />是QLineEdit内只能输入整数，0.01精度浮点数。可以看到还可以利用正则控制输入的内容：<br />QRegExp rx("<a href="file://\\d{,6">\\d{,6</a>}");<br />validatorLineEdit-&gt;setValidator(new QRegExpValidator(rx,validatorLineEdit));<br />这样就只能输入最多6各数字了，再配合前面的密码模式输入就可以用来设置密码了：）<br />第三个：设置对齐方式<br />第三各用到的函数是<br />void&nbsp;setAlignment ( Qt::Alignment flag )<br />alignment : Qt::Alignment<br />This property holds the alignment of the line edit.</p>
<p>Both horizontal and vertical alignment is allowed here, Qt::AlignJustify will map to Qt::AlignLeft.</p>
<p>By default, this property contains a combination of Qt::AlignLeft and Qt::AlignVCenter.<br />非常简单，直接看枚举的类型<br />enum Qt::AlignmentFlag<br />flags Qt::Alignment</p>
<p>This enum type is used to describe alignment. It contains horizontal and vertical flags that can be combined to produce the required effect.</p>
<p>The TextElideMode enum can also be used in many situations to fine-tune the appearance of aligned text.</p>
<p>The horizontal flags are:</p>
<p>Constant&nbsp;Value&nbsp;Description<br />Qt::AlignLeft&nbsp;0x0001&nbsp;Aligns with the left edge.<br />Qt::AlignRight&nbsp;0x0002&nbsp;Aligns with the right edge.<br />Qt::AlignHCenter&nbsp;0x0004&nbsp;Centers horizontally in the available space.<br />Qt::AlignJustify&nbsp;0x0008&nbsp;Justifies the text in the available space.<br />The vertical flags are:</p>
<p>Constant&nbsp;Value&nbsp;Description<br />Qt::AlignTop&nbsp;0x0020&nbsp;Aligns with the top.<br />Qt::AlignBottom&nbsp;0x0040&nbsp;Aligns with the bottom.<br />Qt::AlignVCenter&nbsp;0x0080&nbsp;Centers vertically in the available space.<br />You can use only one of the horizontal flags at a time. There is one two-dimensional flag:</p>
<p>Constant&nbsp;Value&nbsp;Description<br />Qt::AlignCenter&nbsp;AlignVCenter | AlignHCenter&nbsp;Centers in both dimensions.<br />You can use at most one horizontal and one vertical flag at a time. Qt::AlignCenter counts as both horizontal and vertical.</p>
<p>Three enum values are useful in applications that can be run in right-to-left mode:</p>
<p>Constant&nbsp;Value&nbsp;Description<br />Qt::AlignAbsolute&nbsp;0x0010&nbsp;If the widget's layout direction is Qt::RightToLeft (instead of Qt::LeftToRight, the default), Qt::AlignLeft refers to the right edge and Qt::AlignRight to the left edge. This is normally the desired behavior. If you want Qt::AlignLeft to always mean "left" and Qt::AlignRight to always mean "right", combine the flag with Qt::AlignAbsolute.<br />Qt::AlignLeading&nbsp;AlignLeft&nbsp;Synonym for Qt::AlignLeft.<br />Qt::AlignTrailing&nbsp;AlignRight&nbsp;Synonym for Qt::AlignRight.<br />Masks:</p>
<p>Constant&nbsp;Value<br />Qt::AlignHorizontal_Mask&nbsp;AlignLeft | AlignRight | AlignHCenter | AlignJustify | AlignAbsolute<br />Qt::AlignVertical_Mask&nbsp;AlignTop | AlignBottom | AlignVCenter<br />Conflicting combinations of flags have undefined meanings.</p>
<p>The Alignment type is a typedef for QFlags&lt;AlignmentFlag&gt;. It stores an OR combination of AlignmentFlag values.</p>
<p>第四个：可以用来控制一些输入格式，可以无须借助正则<br />用到函数主要是<br />void&nbsp;setInputMask ( const QString &amp; inputMask )</p>
<p>直接看介绍<br />inputMask : QString<br />This property holds the validation input mask.</p>
<p>If no mask is set, inputMask() returns an empty string.</p>
<p>Sets the QLineEdit's validation mask. Validators can be used instead of, or in conjunction with masks; see setValidator().</p>
<p>Unset the mask and return to normal QLineEdit operation by passing an empty string ("") or just calling setInputMask() with no arguments.</p>
<p>The table below shows the characters that can be used in an input mask. A space character, the default character for a blank, is needed for cases where a character is permitted but not required.</p>
<p>Character&nbsp;Meaning<br />A&nbsp;ASCII alphabetic character required. A-Z, a-z.<br />a&nbsp;ASCII alphabetic character permitted but not required.<br />N&nbsp;ASCII alphanumeric character required. A-Z, a-z, 0-9.<br />n&nbsp;ASCII alphanumeric character permitted but not required.<br />X&nbsp;Any character required.<br />x&nbsp;Any character permitted but not required.<br />9&nbsp;ASCII digit required. 0-9.<br />0&nbsp;ASCII digit permitted but not required.<br />D&nbsp;ASCII digit required. 1-9.<br />d&nbsp;ASCII digit permitted but not required (1-9).<br />#&nbsp;ASCII digit or plus/minus sign permitted but not required.<br />H&nbsp;Hexadecimal character required. A-F, a-f, 0-9.<br />h&nbsp;Hexadecimal character permitted but not required.<br />B&nbsp;Binary character required. 0-1.<br />b&nbsp;Binary character permitted but not required.<br />&gt;&nbsp;All following alphabetic characters are uppercased.<br />&lt;&nbsp;All following alphabetic characters are lowercased.<br />!&nbsp;Switch off case conversion.<br />\&nbsp;Use \ to escape the special characters listed above to use them as separators.<br />The mask consists of a string of mask characters and separators, optionally followed by a semicolon and the character used for blanks. The blank characters are always removed from the text after editing.</p>
<p>Examples:</p>
<p>Mask&nbsp;Notes<br />000.000.000.000;_&nbsp;IP address; blanks are _.<br />HH:HH:HH:HH:HH:HH;_&nbsp;MAC address<br />0000-00-00&nbsp;ISO Date; blanks are space<br />&gt;AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;#&nbsp;License number; blanks are - and all (alphabetic) characters are converted to uppercase.<br />To get range control (e.g., for an IP address) use masks together with validators.</p>
<p>Access functions:</p>
<p>QString&nbsp;inputMask () const<br />void&nbsp;setInputMask ( const QString &amp; inputMask )<br />See also maxLength.<br />看下程序用到的地方：<br />&nbsp;&nbsp;&nbsp; switch (index) {<br />&nbsp;&nbsp;&nbsp; case 0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputMaskLineEdit-&gt;setInputMask("");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; case 1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputMaskLineEdit-&gt;setInputMask("+99 99 99 99 99;_");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; case 2:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputMaskLineEdit-&gt;setInputMask("0000-00-00");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputMaskLineEdit-&gt;setText("00000000");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputMaskLineEdit-&gt;setCursorPosition(0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; case 3:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputMaskLineEdit-&gt;setInputMask("&gt;AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;#");<br />其中分号后面跟的符号会代替掉前面的那些通配符<br />比如选到License Key ，QLIneEdit内容变为<br />#####-#####-#####-#####-#####<br />输入时只能输入字母，同时-会自动跳过，不可改变，不被删除，总之试下就知道了哈哈</p>
<p>5.<br />很简单，设置内容是否可更改<br />readOnly : bool<br />This property holds whether the line edit is read only.</p>
<p>In read-only mode, the user can still copy the text to the clipboard, or drag and drop the text (if echoMode() is Normal), but cannot edit it.</p>
<p>QLineEdit does not show a cursor in read-only mode.</p>
<p>By default, this property is false.</p>
<p>几个函数组合使用，功能很强大<br /></p><img src ="http://www.cppblog.com/izualzhy/aggbug/146696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-05-18 21:09 <a href="http://www.cppblog.com/izualzhy/archive/2011/05/18/146696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QtExamples之ToolTips学习</title><link>http://www.cppblog.com/izualzhy/archive/2011/05/17/146601.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Tue, 17 May 2011 13:30:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/05/17/146601.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/146601.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/05/17/146601.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/146601.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/146601.html</trackback:ping><description><![CDATA[<p>ToolTips可以用来创建三种形状，这些图形都可以用鼠标拖动，当鼠标停留在上面时，还有tooltips<br /></p>
<p><img height="300" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/ToolTipExample.png" width="500" border="0" /><br />该例子有两个主要的类：<br />ShapeItem is a custom widget representing one single shape item.<br />SortingBox inherits from QWidget and is the application's main widget.<br />1.SortingBox<br />SortingBox类里重新实现了很多event，用途如下：<br />The event() function provides tooltips, the resize() function makes sure the application appears consistently when the user resizes the main widget, and the paintEvent() function displays the shape items within the SortingBox widget. The mouse event handlers are reimplemented to make the user able to move the items around.<br />三个私有的槽函数分别对应创建三种图形<br />在构造函数里调用三个函数：<br />initialItemPosition(), initialItemColor() and createToolButton()<br />看名字就知道在做什么了<br />2.<br />要显示tooltip必须要知道鼠标移动事件，默认在不按下键时是不记录鼠标轨迹的，因此需要设置下<br />setMouseTracking(true);<br />To be able to show the appropiate tooltips while the user is moving the cursor around, we need to enable mouse tracking for the widget.</p>
<p>If mouse tracking is disabled (the default), the widget only receives mouse move events when at least one mouse button is pressed while the mouse is being moved. If mouse tracking is enabled, the widget receives mouse move events even if no buttons are pressed.<br />3.如何画出的三角形，矩形，椭圆<br />矩形，椭圆用QPainter的函数就可以了，三角形用drawLine画三次，每次画三角形是不是太费劲了那？或者如果遇到其他不规则的图形，怎么画出来的呢？<br />这里就用到了QPainterPath类了<br />先看个addRect函数<img height="294" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QPainterPath__addRect.png" width="1159" border="0" /><br /><br />再看个addEllips<img height="285" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QPainterPath__addEllipse.png" width="818" border="0" />e<br /><br />再来个贝泽尔曲<img height="263" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QPainterPath__cubicTo.png" width="731" border="0" />线的<br /><br />先定义曲线，然后用QPainter::drawPath()就OK了<br />有一个问题是，drawPath（）并不能指定position<br />看下定义<br /><img height="200" alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/QPainter__drawPath.png" width="685" border="0" /><br /><br />因此在想要在某个点开始画出想要的曲线，先移动坐标系<br />&nbsp;&nbsp;&nbsp; foreach (ShapeItem shapeItem, shapeItems) {<br />//! [8] //! [9]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; painter.translate(shapeItem.position());<br />//! [9] //! [10]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; painter.setBrush(shapeItem.color());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; painter.drawPath(shapeItem.path());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; painter.translate(-shapeItem.position());<br />&nbsp;&nbsp;&nbsp; }<br />这么做的解释：<br />The painter will by default draw all the shape items at position (0,0) in the SortingBox widget. The QPainter::translate() function translates the coordinate system by the given offset, making each shape item appear at its defined position. But remember to translate the coordinate system back when the item is drawn, otherwise the next shape item will appear at a position relative to the item we drawed last.<br />4.如何实现移动？<br />思考一下，肯定是在mousePressEvent,mouseMoveEvent,moutReleaseEvent上修改。<br />而且说是移动，其实是完全重绘了一遍整个widget。<br />那么，怎么知道当前鼠标点在哪个图形上呢？<br />其实这个问题比之前我想的要简单：<br />程序利用了如下函数：<br />int SortingBox::itemAt(const QPoint &amp;pos)<br />{<br />&nbsp;&nbsp;&nbsp; for (int i = shapeItems.size() - 1; i &gt;= 0; --i) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const ShapeItem &amp;item = shapeItems[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (item.path().contains(pos - item.position()))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return i;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return -1;<br />}<br />循环遍历每个shapwItem，逆序遍历的原因是当这个点在多个shapeitem上时，返回最上面的一个，利用QPainterPath的函数contains<br />bool QPainterPath::contains ( const QPointF &amp; point ) const<br />Returns true if the given point is inside the path, otherwise returns false.<br />记录鼠标移动前后的偏移量，设置给当前的shapeItem，然后update（）重绘。<br />值得注意的是对shapeItems，即存储图形的列表的修改，假设要以动的图形在列表里索引是index，调用下列语句<br />&nbsp;shapeItems.move(index, shapeItems.size() - 1);<br />是当前修改位置的图形跑到列表最后。<br />5.如何实现toolTops的？<br />bool SortingBox::event(QEvent *event)<br />{<br />//! [5] //! [6]<br />&nbsp;&nbsp;&nbsp; if (event-&gt;type() == QEvent::ToolTip) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QHelpEvent *helpEvent = static_cast&lt;QHelpEvent *&gt;(event);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int index = itemAt(helpEvent-&gt;pos());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (index != -1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QToolTip::showText(helpEvent-&gt;globalPos(), shapeItems[index].toolTip());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QToolTip::hideText();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event-&gt;ignore();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return QWidget::event(event);<br />}<br />直接看Qt assistant的解释<br />If the type is QEvent::ToolTip, we cast the event to a QHelpEvent, otherwise we propagate the event using the QWidget::event() function.</p>
<p>The QHelpEvent class provides an event that is used to request helpful information about a particular point in a widget.</p>
<p>For example, the QHelpEvent::pos() function returns the event's position relative to the widget to which the event is dispatched. Here we use this information to determine if the position of the event is contained within the area of any of the shape items. If it is, we display the shape item's tooltip at the position of the event. If not, we hide the tooltip and explicitly ignore the event. This makes sure that the calling code does not start any tooltip specific modes as a result of the event. Note that the QToolTip::showText() function needs the event's position in global coordinates provided by QHelpEvent::globalPos().<br /></p><img src ="http://www.cppblog.com/izualzhy/aggbug/146601.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-05-17 21:30 <a href="http://www.cppblog.com/izualzhy/archive/2011/05/17/146601.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】QPainter::begin: Widget painting can only begin as a result of a paintEvent</title><link>http://www.cppblog.com/izualzhy/archive/2011/03/21/142414.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Mon, 21 Mar 2011 14:00:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/03/21/142414.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/142414.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/03/21/142414.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/142414.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/142414.html</trackback:ping><description><![CDATA[<div class=gemfieldphone id=read_tpc>在Qt里，默认情况下要使用QPainter画图必须在paintEvent()函数里，如果在其它地方的话，运行时会提示如下错误<br>QPainter::begin: Widget painting can only begin as a result of a paintEvent<br>要避免这个问题可以设置你要画图的那个widget的一个属性，加上类似这样的代码this-&gt;setAttribute(Qt::WA_PaintOutsidePaintEvent);<br>就可以了。<br>qpainter.cpp 代码里相应实现逻辑，可以看下面<br>&nbsp;&nbsp; 1081&nbsp;&nbsp;&nbsp;&nbsp; switch (pd-&gt;devType()) {<br>&nbsp;&nbsp; 1082&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case QInternal::Widget:<br>&nbsp;&nbsp; 1083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp; 1084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const QWidget *widget = static_cast(pd);<br>&nbsp;&nbsp; 1085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Q_ASSERT(widget);<br>&nbsp;&nbsp; 1086<br>&nbsp;&nbsp; 1087&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!d-&gt;engine-&gt;hasFeature(QPaintEngine::PaintOutsidePaintEvent)<br>&nbsp;&nbsp; 1088&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; !widget-&gt;testAttribute(Qt::WA_PaintOutsidePaintEvent)<br>&nbsp;&nbsp; 1089&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; !widget-&gt;testAttribute(Qt::WA_WState_InPaintEvent)) {<br>&nbsp;&nbsp; 1090&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qWarning("QPainter::begin: Widget painting can only begin as a "<br>&nbsp;&nbsp; 1091&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;"result of a paintEvent");<br>&nbsp;&nbsp; 1092&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br>&nbsp;&nbsp; 1093&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp; 1094&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp; 1095&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<img src ="http://www.cppblog.com/izualzhy/aggbug/142414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-03-21 22:00 <a href="http://www.cppblog.com/izualzhy/archive/2011/03/21/142414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Qt里的globalPos和pos</title><link>http://www.cppblog.com/izualzhy/archive/2011/03/21/142408.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Mon, 21 Mar 2011 13:11:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/03/21/142408.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/142408.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/03/21/142408.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/142408.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/142408.html</trackback:ping><description><![CDATA[<span class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium 宋体; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 24px; FONT-FAMILY: arial, 宋体, sans-serif"></span></span><font face=Arial>新建一个窗口程序，然后创建一个QMenu对象。在构造函数里初始化<br>menu = new QMenu("menu", this); //menu在头文件声明<br>QAction *action = new QAction(tr("1111"), this); //为使目录较大，能看见，我们添加一个action<br>menu-&gt;addAction(action);<br><br>然后在mousePressEvent里看到效果<br>void Dialog::mousePressEvent(QMouseEvent *e)<br>{<br>&nbsp;&nbsp;&nbsp; if(e-&gt;button() == Qt::RightButton) //鼠标右键。避免无法关掉窗口<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QPoint p(0, 0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //menu-&gt;exec(p); //测试用，坐标相对于桌面<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; menu-&gt;exec(e-&gt;globalPos()); //坐标相对于窗口<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //menu-&gt;exec(e-&gt;pos()); //坐标相对于桌面<br>&nbsp;&nbsp;&nbsp; }<br>}<br><br>可以看到，pos不管窗口怎样移动，menu总是出现在相同的地方。globalPos相对于窗口，跟着窗口移动.<br><br>pos不管窗口怎样移动，menu总是出现在相同的地方。<br>假设我们一直点击的是窗口右上角，menu总是出现在同样的地方。也就是类似于执行menu-&gt;exec(QPoint(1000,0))<br>所以p的值没变，但相对于桌面我们点的地方已经变了，只是相对窗口的坐标p一直是(1000,0)，所以pos是相对窗口的。。。<br>globalPos相对于窗口，跟着窗口移动。不论我点哪菜单就在哪show，所以是相对桌面的，要不叫global呢~~</font>
<img src ="http://www.cppblog.com/izualzhy/aggbug/142408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-03-21 21:11 <a href="http://www.cppblog.com/izualzhy/archive/2011/03/21/142408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Example &amp; Codecs Example</title><link>http://www.cppblog.com/izualzhy/archive/2011/03/18/142171.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Fri, 18 Mar 2011 13:49:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/03/18/142171.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/142171.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/03/18/142171.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/142171.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/142171.html</trackback:ping><description><![CDATA[<p>Codecs Example<br>学习这个例子主要是想了解下在文本处理时如何确定文本的编码格式问题～～<br>Qt assistant里只用一句话介绍了下～<br>The Codecs example demonstrates the principles behind importing and exporting text using codecs to ensure that characters are encoded properly, avoiding loss of data and retaining the correct symbols used in various scripts<br>总结一句话，就是要学习QTextCodec类，界面次之～～<br>ps:<br>打开这个例子看到saveAs菜单后面那么多的Action就想到刚学的QOject::sender()了～～</p>
<p>该例子由两个主要的类<br>MainWindow：public QMainWindow <br>PreviewForm: public QDialog<br>1.<br>文本输入界面使用的QTextEdit，通过 setCentralWidget(textEdit);而设定为MainWindow的主窗口，应该是很熟悉这个了～～<br>QTextEdit有一个属性是<br>enum QTextOption::WrapMode<br>This enum describes how text is wrapped in a document.</p>
<p>Constant&nbsp;Value&nbsp;Description<br>QTextOption::NoWrap&nbsp;0&nbsp;Text is not wrapped at all.<br>QTextOption::WordWrap&nbsp;1&nbsp;Text is wrapped at word boundaries.<br>QTextOption::ManualWrap&nbsp;2&nbsp;Same as QTextOption::NoWrap<br>QTextOption::WrapAnywhere&nbsp;3&nbsp;Text can be wrapped at any point on a line, even if it occurs in the middle of a word.<br>QTextOption::WrapAtWordBoundaryOrAnywhere&nbsp;4&nbsp;If possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.<br>表示在行末如何换行或者不换行。<br>2.<br>由于编码方式很多，为了使菜单看上去美观些，要设置一下那些匹配到一块，于是用到了QRegExp<br>这里用的正则是很简单的，我也只看了下用到的两个函数<br>A。<br>bool QRegExp::exactMatch ( const QString &amp; str ) const<br>Returns true if str is matched exactly by this regular expression; otherwise returns false. You can determine how much of the string was matched by calling matchedLength().</p>
<p>For a given regexp string R, exactMatch("R") is the equivalent of indexIn("^R$") since exactMatch() effectively encloses the regexp in the start of string and end of string anchors, except that it sets matchedLength() differently.</p>
<p>For example, if the regular expression is blue, then exactMatch() returns true only for input blue. For inputs bluebell, blutak and lightblue, exactMatch() returns false and matchedLength() will return 4, 3 and 0 respectively.<br>这个表示的是要完全匹配，而不是从中间开始。类似于Python里正则表达式的search()和match（）<br>B。<br>QString QRegExp::cap ( int nth = 0 ) const<br>Returns the text captured by the nth subexpression. The entire match has index 0 and the parenthesized subexpressions have indexes starting from 1 (excluding non-capturing parentheses).<br>通过在rx里添加括号查看返回值～～<br>匹配好了之后会同时产生一个int类型的rank值，加在codec的名字前作为key，codec作为value组成QMap<br>3.<br>在private里定义了QList&lt;QTextCodec *&gt; codecs;<br>将刚定义的QMap通过values（）函数赋给该私有变量，注意values（）函数的描述：<br>QList&lt;T&gt; QMap::values () const<br>Returns a list containing all the values in the map, in ascending order of their keys. If a key is associated with multiple values, all of its values will be in the list, and not just the most recently inserted one.<br>会有一个顺序的问题，这也是我们添加rank的原因了～～<br>这样赋值之后，QList codecs里就是排序之后的了～～<br>得先忙工作的东西了，有空要再研究下</p>
<p><br>&nbsp;</p>
<img src ="http://www.cppblog.com/izualzhy/aggbug/142171.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-03-18 21:49 <a href="http://www.cppblog.com/izualzhy/archive/2011/03/18/142171.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Example &amp; CodeEditor Example</title><link>http://www.cppblog.com/izualzhy/archive/2011/03/18/142170.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Fri, 18 Mar 2011 13:48:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/03/18/142170.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/142170.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/03/18/142170.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/142170.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/142170.html</trackback:ping><description><![CDATA[<p>这个例子其实很多没看懂的，先写点看懂的部分做下笔记～～特别是QPlainTextEditor的每一行的高度是怎么与显示行号的widget对应的这么合理的。<br>CodeEditor Example由两个类组成<br>LineNumberArea + CodeEdit<br>CodeEdit负责文字输入，LineNumberArea则负责行数的显示。两者之间组成关系是<br>We paint the line numbers on this widget（LineNumberArea）, and place it over the CodeEditor's viewport()'s left margin area.<br>如果我们setViewportMargins（）设定了margin，LineNumberArea的parent又是CodeEdit，那么LineNumberArea自动生成在margin上？<br>在以下三种情况下，需要draw LineNumberArea（只有这个想清楚了才能写好信号和槽阿～～我是没想明白。。。）<br>1.when the number of lines in the editor changes<br>2.when the editor's viewport() is scrolled<br>3.Of course, it is also done when the editor's size changes<br>先说下viewport<br>viewport部分就是主窗口用于输入的，四周是verticalScrollBar或者horizontalScrollBar。当然也可以通过setViewportMargins()来在viewport周围先加一些空白～～<br>具体的Qt文档里这么介绍的：<br>The QAbstractScrollArea widget provides a scrolling area with on-demand scroll bars.</p>
<p>QAbstractScrollArea is a low-level abstraction of a scrolling area. The area provides a central widget called the viewport, in which the contents of the area is to be scrolled (i.e, the visible parts of the contents are rendered in the viewport).</p>
<p>Next to the viewport is a vertical scroll bar, and below is a horizontal scroll bar. When all of the area contents fits in the viewport, each scroll bar can be either visible or hidden depending on the scroll bar's Qt::ScrollBarPolicy. When a scroll bar is hidden, the viewport expands in order to cover all available space. When a scroll bar becomes visible again, the viewport shrinks in order to make room for the scroll bar.</p>
<p>It is possible to reserve a margin area around the viewport, see setViewportMargins(). The feature is mostly used to place a QHeaderView widget above or beside the scrolling area. Subclasses of QAbstractScrollArea should implement margins.1</p>
<p>1.<br>fontMetrics().width(QLatin1Char('9'))<br>返回只有一个字符&#8216;9&#8217;时的合理宽度～～<br>2.<br>void QAbstractScrollArea::setViewportMargins ( int left, int top, int right, int bottom )<br>这个函数一直弄混了，该函数实际上是创建了四个margin<br>setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);<br>例如该语句即是在左边创建一个margin～～虽然只传进了一个int值，但viewport周围的margin是环绕整个viewport的，所以另一条边是固定大小的（早想到这点就不会看不明白了。。。）<br>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/izualzhy/aggbug/142170.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-03-18 21:48 <a href="http://www.cppblog.com/izualzhy/archive/2011/03/18/142170.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Example &amp;Shape Analog Clock example</title><link>http://www.cppblog.com/izualzhy/archive/2011/03/18/142168.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Fri, 18 Mar 2011 13:39:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/03/18/142168.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/142168.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/03/18/142168.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/142168.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/142168.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>Shape Analog Clock example<br>1.<br>Qt::FramelessWindowHint可以使窗口去掉关闭 最大化 最小化等，但是需要重新自定义move等事件<br>该flag在Qt里介绍：<br>Produces a borderless window. The user cannot move or resize a borderless window via the window system<br>在这个例子里于是我们需要自定义mouseMoveEvent,mousePressEvent，原文如下：<br>We inform the window manager that the widget is not to be decorated with a window frame by setting the Qt::FramelessWindowHint flag on the widget. As a result, we need to provide a way for the user to move the clock around the screen.<br>该例子实现后可以在桌面上拖动一个类似于表的widget，同时没有边框，很美观，那么定义mouseMoveEvent()时，我们如何确定该widget应当move到什么地方呢？<br>例子里定一个一个private data ：<br>QPoint dragPosition;<br>在mousePressEvent里<br>dragPosition = event-&gt;globalPos() - frameGeometry().topLeft();<br>在mouseMoveEvent里<br>move(event-&gt;globalPos() - dragPosition);<br>即把鼠标按下时的位置与控件左上的坐标距离作为一个偏移量<br><img height=185 alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/displacement.png" width=225 border=0><br>原文介绍如下：<br>If the left mouse button is pressed over the widget, we record the displacement in global (screen) coordinates between the top-left position of the widget's frame (even when hidden) and the point where the mouse click occurred. This displacement will be used if the user moves the mouse while holding down the left button. Since we acted on the event, we accept it by calling its accept() function.<br>注意这里时globalPos()~~<br>2.sizeHint()<br>刚开始没有弄懂为什么要定义sizeHint()<br>去掉后对比下图像发现图大了不少，才明白在图像未指定大小时第一次show的时候会自动调用sizeHint（）<br>例子中说明如下<br>Finally, we implement the sizeHint() for the widget so that it is given a reasonable default size when it is first shown:<br><img height=420 alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/ShapedAnalogClock_sizeHint.png" width=491 border=0>去掉sizeHint函数的<br><img height=116 alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/ShapedAnalogClock_nosizeHint.png" width=130 border=0>用了sizeHint的就比较美观了<br>3.mask<br>那么如何是窗口呈现为一个圆形的呢？<br>其实窗口还是矩形的，不过通过mask设为一部分可见，一部分透明了<br>setMask有两种形式，不过作用都是类似的<br>void QWidget::setMask ( const QBitmap &amp; bitmap )<br>Causes only the pixels of the widget for which bitmap has a corresponding 1 bit to be visible<br>void QWidget::setMask ( const QRegion &amp; region )<br>Causes only the parts of the widget which overlap region to be visible.<br>即是区域内可见，其余不可见。<br>另外一个关于透明性的函数为<br>void&nbsp;setWindowOpacity ( qreal level )<br>windowOpacity : double<br>This property holds the level of opacity for the window.<br>The valid range of opacity is from 1.0 (completely opaque) to 0.0 (completely transparent).<br>该函数控制的是整个widget的透明性～<br>如果setMask（）与setWindowOpacity（）一起用了，QREgion外仍是透明的，不过mask的区域透明度因为setWindowOpacity（）改变了。<br>这是我用了该函数之后的例子<br><img height=90 alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/setWindowOpacity.png" width=125 border=0>&nbsp;可以看到变得透明了<br>这张图对比就更明显了<img height=231 alt="" src="http://www.cppblog.com/images/cppblog_com/izualzhy/AnalogClock_Opacity.png" width=401 border=0><br>4.如何按下鼠标右键弹出Action的？<br>直接new一个QAction出来然后add就行了～～<br>估计是因为在这种widget下没有其他地方放就默认放在右键里了，需要进一步学习才能确定～～</p>
<img src ="http://www.cppblog.com/izualzhy/aggbug/142168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-03-18 21:39 <a href="http://www.cppblog.com/izualzhy/archive/2011/03/18/142168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt Example &amp; Scribble Example</title><link>http://www.cppblog.com/izualzhy/archive/2011/03/18/142167.html</link><dc:creator>izualzhy</dc:creator><author>izualzhy</author><pubDate>Fri, 18 Mar 2011 13:33:00 GMT</pubDate><guid>http://www.cppblog.com/izualzhy/archive/2011/03/18/142167.html</guid><wfw:comment>http://www.cppblog.com/izualzhy/comments/142167.html</wfw:comment><comments>http://www.cppblog.com/izualzhy/archive/2011/03/18/142167.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/izualzhy/comments/commentRss/142167.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/izualzhy/services/trackbacks/142167.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>在Qt4.0里Scribble example里画线条是先draw在一个image上，image在通过drawImage画到widget上，给出了这样的理由<br>At this point, you might wonder why we don't just draw directly onto the widget instead of drawing in a QImage and copying the QImage onto screen in paintEvent(). There are at least three good reasons for this:</p>
<p>The window system requires us to be able to redraw the widget at any time. For example, if the window is minimized and restored, the window system might have forgotten the contents of the widget and send us a paint event. In other words, we can't rely on the window system to remember our image.<br>Qt normally doesn't allow us to paint outside of paintEvent(). In particular, we can't paint from the mouse event handlers. (This behavior can be changed using the Qt::WA_PaintOnScreen widget attribute, though.)<br>If initialized properly, a QImage is guaranteed to use 8-bit for each color channel (red, green, blue, and alpha), whereas a QWidget might have a lower color depth, depending on the monitor configuration. This means that if we load a 24-bit or 32-bit image and paint it onto a QWidget, then copy the QWidget into a QImage again, we might lose some information.</p>
<p>image比widget要稍大一点，理由如下<br>When the user starts the Scribble application, a resize event is generated and an image is created and displayed in the scribble area. We make this initial image slightly larger than the application's main window and scribble area, to avoid always resizing the image when the user resizes the main window (which would be very inefficient). But when the main window becomes larger than this initial size, the image needs to be resized.</p>
<p>当需要重绘的事件paintEvent时，通过传给update（）一个参数可能会提高效率，当然前提是你知道这个参数<br>We could call the update() function with no parameter, but as an easy optimization we pass a QRect that specifies the rectangle inside the scribble are needs updating, to avoid a complete repaint of the widget.<br>例如这里传入的是，鼠标新画的线段 与笔的大小组成的一个矩形区域。这样只会重新绘制这里了～～<br>&nbsp;Painter painter(&amp;image);<br>&nbsp;&nbsp;&nbsp;&nbsp; painter.setPen(QPen(myPenColor, myPenWidth, Qt::SolidLine, Qt::RoundCap,<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; Qt::RoundJoin));<br>&nbsp;&nbsp;&nbsp;&nbsp; painter.drawLine(lastPoint, endPoint);<br>&nbsp;&nbsp;&nbsp;&nbsp; modified = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; int rad = (myPenWidth / 2) + 2;<br>&nbsp;&nbsp;&nbsp;&nbsp; update(QRect(lastPoint, endPoint).normalized()<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; .adjusted(-rad, -rad, +rad, +rad));</p>
<p>当有多个signal连接到一个槽时，例如在保存文件时，给出的QAction有 BMP JPG JPEG 等，此时只需要一个save（）的槽函数，save（）函数需要知道是哪个signal发送过来，此时将根据QObject * QObject::sender () const&nbsp;&nbsp; [protected]来判断sender<br>该函数介绍如下：<br>QObject * QObject::sender () const&nbsp;&nbsp; [protected]<br>Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; otherwise it returns 0. The pointer is valid only during the execution of the slot that calls this function from this object's thread context.</p>
<p>The pointer returned by this function becomes invalid if the sender is destroyed, or if the slot is disconnected from the sender's signal.</p>
<p>Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.</p>
<p>Warning: As mentioned above, the return value of this function is not valid when the slot is called via a Qt::DirectConnection from a thread different from this object's thread. Do not use this function in this type of scenario.<br>具体scribble 里代码如下<br>&nbsp;void MainWindow::save()<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; QAction *action = qobject_cast&lt;QAction *&gt;(sender());<br>&nbsp;&nbsp;&nbsp;&nbsp; QByteArray fileFormat = action-&gt;data().toByteArray();<br>&nbsp;&nbsp;&nbsp;&nbsp; saveFile(fileFormat);<br>&nbsp;}<br>第一句：<br>QAction *action = qobject_cast&lt;QAction *&gt;(sender());<br>虽然不知道sender（）具体是哪一个QAction，但我们知道肯定是一个QAction，因此可以cast过来。<br>用static_cast&lt;&gt;也是可以的，这里使用qobject_cast的原因例子里说明如下<br>but as a defensive programming technique we use a qobject_cast(). The advantage is that if the object has the wrong type, a null pointer is returned. Crashes due to null pointers are much easier to diagnose than crashes due to unsafe casts.<br>第二句：<br>QAction里有setdata（） 和 data（）两个函数作用是这样的<br>1.<br>QVariant QAction::data () const<br>Returns the user data as set in QAction::setData.<br>2.<br>void QAction::setData ( const QVariant &amp; userData )<br>Sets the action's internal data to the given userData.</p>
<p>在创建QAction的时候，我们setData（）<br>&nbsp;&nbsp;&nbsp;&nbsp; foreach (QByteArray format, QImageWriter::supportedImageFormats()) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QString text = tr("%1...").arg(QString(format).toUpper());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QAction *action = new QAction(text, this);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; action-&gt;setData(format);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connect(action, SIGNAL(triggered()), this, SLOT(save()));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; saveAsActs.append(action);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>此时通过ction-&gt;data().toByteArray();取出来<br>然后传给第三句，saveFile函数就知道该存为哪种格式了</p>
<p>ps：<br>在界面编程里，例如写一个save（）函数，可能saveFile（）才是实现保存文件的作用的。<br>但点击saveaction时，调用save（），实际上需要判断各种情况，例如文件名合法/同名等，需要根据不同情况弹出不同的对话框，当全都判断true后，才会调用saveFile（）函数，这可能就是跟之前自己编程差别比较大的情况了～～</p>
<img src ="http://www.cppblog.com/izualzhy/aggbug/142167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/izualzhy/" target="_blank">izualzhy</a> 2011-03-18 21:33 <a href="http://www.cppblog.com/izualzhy/archive/2011/03/18/142167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>