64 Star 180 Fork 34

qtguide / qtguide

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
ch04-04.htm 112.97 KB
一键复制 编辑 原始数据 按行查看 历史
qtguide 提交于 2015-07-09 21:02 . update 4.5, add 4.6
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>ch04-04</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="thumbnailviewer.css" type="text/css">
<script src="thumbnailviewer.js" type="text/javascript">
/***********************************************
* Image Thumbnail Viewer Script- © Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/
</script> </head>
<body>
<div class="os1"> 4.4 属性系统 </div>
<br>
Qt 元对象系统最主要的功能是实现信号和槽机制,当然也有其他功能,就是支持属性系统。有些高级语言通过编译器的 __property 或者
[property] 等关键字实现属性系统,用于提供对成员变量的访问权限,Qt 则通过自己的元对象系统支持属性访问,Qt 是基于标准 C++
的,不需要底层编译器支持属性,Qt 本身提供了通用的跨平台的属性系统。关于属性系统可以在 Qt 助手索引里面输入“The Property
System”,找到相应的主题文档。Qt 类库大量使用属性,通常开发基于 Qt
的类库时,也会用到属性系统。下面我们介绍简化版的属性系统,只列举了属性系统里面几个基本的条目。<br>
<br>
<div class="os2"> 4.4.1 属性系统简介 </div>
<br>
为了保持类的封装特性,通常成员变量需要保持私有状态,而为了与其他对象协作,就需要提供相应的 get/set
函数。如果成员变量的数值发生了变化,通常也需要提供通知(NOTIFY)信息告知相关对象,Qt 里的通知一般都是使用信号触发。set
函数可以作为槽函数,方便接收相关对象的信号以实现自动调整,比如上一节标签控件的 setText 槽函数。set
函数会导致成员变量数值变化,为了通知相关对象,set 函数里通常会 emit 该成员变量发生变化的信号。<br>
属性系统也是通过元对象系统实现的,它也是需要直接或间接从 QObject 类继承,并在类的声明里需要 Q_OBJECT
宏。下面介绍简化版的属性声明,第一类是不指明与属性相关的私有成员变量,这时必须至少提供该属性的读函数:<br>
<div class="code">Q_PROPERTY(type name<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; READ
getFunction <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [WRITE
setFunction]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [RESET
resetFunction]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [NOTIFY
notifySignal] )</div>
Q_PROPERTY()宏就是属性的声明:<br>
<ul>
<li>type 是指属性的类型,可以是 C++ 标准类型、类名、结构体、枚举等,name 就是属性的名字。</li>
<li>READ 标出该属性的读函数 getFunction,Qt 属性的读函数通常省略 get 三个字母。</li>
<li>WRITE 标出该属性的写函数 setFunction,中括号表示可选,写函数不是必须的。</li>
<li>RESET 标出该属性的重置函数 resetFunction,重置函数将属性设为某个默认值,中括号表示可选,重置函数不是必须的。</li>
<li>NOTIFY 标出该属性变化时发出的通知信号 notifySignal,中括号表示可选,这个信号不是必须的。</li>
</ul>
这仅仅列举了属性声明里简单的几行,复杂需要查阅 Qt 帮助文档。对于属性,注意 name
仅仅是一个用于标识属性的名字,它不是实际存在的成员变量,属性系统不会自动生成成员变量,它就是虚无的名字代号(不同属性的名字不能相同)。对于属性用到的数值会存在一
个真正的私有成员变量里面, 私有成员变量、读函数、写函数、信号等需要另外编写这些声明,对于函数还需要编写实体代码。<br>
<br>
上面是不明确指出私有成员变量的情形,也可以明确指出使用了哪个成员变量,这时候属性声明为:<br>
<div class="code">Q_PROPERTY(type name<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MEMBER
memberName<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [READ
getFunction]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [WRITE
setFunction]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [RESET
resetFunction]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [NOTIFY
notifySignal] )</div>
这里的 MEMBER 标出属性使用的成员变量 memberName,其他的行与上面的声明类似。<br>
<br>
在明确标出属性使用的成员变量的情况下,属性的读写函数可以省略不写,Qt 的 moc
工具会自动为成员变量生成读写代码;而重置函数、信号等需要自己声明,并编写必须的代码;如果声明了属性值变化的通知信号,那么 moc
工具生成的写属性代码会自动触发该通知信号。<br>
<br>
如果希望自己的编写的类库支持 QML,那么 NOTIFY
通知信号是必须的,一般建议把成员变量、读函数、写函数、通知信号都明确标出来,这样方便程序员阅读和使用。<br>
<br>
<div class="os2"> 4.4.2 普通属性示例 </div>
<br>
使用
Q_PROPERTY()宏声明的其实都是声明好的普通属性,在程序编译时就已经规定好了,本小节示范普通属性的例子,下一小节示范在运行时动态添加属性。本
小节示范为窗口类添加自定义的属性,然后从 main 函数里面设置和打印属性的值。<br>
打开 QtCreator ,新建一个 Qt Widgets Application 项目,在新建项目的向导里填写:<br>
①项目名称 normalpros,创建路径 D:\QtProjects\ch04,点击下一步;<br>
②套件选择里面选择全部套件,点击下一步;<br>
③基类选择 QWidget,点击下一步;<br>
④项目管理不修改,点击完成。<br>
建好项目之后,打开头文件 widget.h,添加属性的声明代码、读写函数声明、信号声明和成员变量:<br>
<div class="code"><span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;">
</span>WIDGET_H
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">WIDGET_H</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QWidget&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">Widget</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//声明属性</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//不直接标出成员变量的形式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Q_PROPERTY</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span>nickName<span style=" color:#c0c0c0;"> </span>READ<span
style=" color:#c0c0c0;"> </span>nickName<span style=" color:#c0c0c0;"> </span>WRITE<span
style=" color:#c0c0c0;"> </span>setNickName<span style=" color:#c0c0c0;"> </span>NOTIFY<span
style=" color:#c0c0c0;"> </span>nickNameChanged<span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//直接标出成员变量的形式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Q_PROPERTY</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>count<span
style=" color:#c0c0c0;"> </span>MEMBER<span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_count</span><span style=" color:#c0c0c0;"> </span>READ<span
style=" color:#c0c0c0;"> </span>count<span style=" color:#c0c0c0;"> </span>WRITE<span
style=" color:#c0c0c0;"> </span>setCount<span style=" color:#c0c0c0;"> </span>NOTIFY<span
style=" color:#c0c0c0;"> </span>countChanged<span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//标出成员变量,可以省略读写函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Q_PROPERTY</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span>value<span style=" color:#c0c0c0;"> </span>MEMBER<span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_value</span><span
style=" color:#c0c0c0;"> </span>NOTIFY<span style=" color:#c0c0c0;"> </span>valueChanged<span
style=" color:#000000;">)</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//nickName读函数声明</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#000000;">&amp;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nickName</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//count读函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//value属性声明时,指出了成员变量并省略了读写函数,它的读写代码由moc工具自动生成</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//value数值被修改时,valueChanged信号会自动触发</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//自动生成的读写代码只有简单的读写功能,不能做数值有效性检查</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">signals</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//三个属性数值变化时发信号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nickNameChanged</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#000000;">&amp;</span><span style=" color:#c0c0c0;"> </span>strNewName<span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">countChanged</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>nNewCount<span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">valueChanged</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span>dblNewValue<span style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">slots</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//写函数通常可以作为槽函数,方便与其他信号关联,自动调整数值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//nickName写函数声明</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">setNickName</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#000000;">&amp;</span><span style=" color:#c0c0c0;"> </span>strNewName<span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//count写函数声明</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">setCount</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>nNewCount<span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//value写代码由</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">moc</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">自动生成,没有写函数</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//三个私有变量,对应是三个属性</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nickName</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_count</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_value</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">WIDGET_H</span></pre>
</div>
上面代码声明了三个属性,首先是 nickName:<br>
<ul>
<li>没有直接指出其成员变量,但其实是有的;</li>
<li>读函数为 nickName(),返回值为属性里声明的 QString 类型(引用也算的);</li>
<li>写函数为 setNickName(),写函数接收 QString 类型参数,并返回 void;</li>
<li>当属性值变化时,发送 nickNameChanged 信号,信号参数里会带有新的数值。</li>
</ul>
属性声明里的读写函数都需要程序员自己编写,信号自己声明,并在写函数里触发。写函数 setNickName()
的声明放到槽函数声明部分了,这样方便关联其他信号,实现自动调整属性值。虽然属性声明里没说有成员变量,但是需要自己定义一个私有变量 m_nickName
保存属性的数值。<br>
<br>
第二个属性是 count:<br>
<ul>
<li>直接指出它对应的成员变量是 m_count;</li>
<li>读函数是 count(),返回 int 类型;</li>
<li>写函数是 setCount(),接收一个 int 参数,并返回 void;</li>
<li>当属性值变化时,发送 countChanged 信号,信号参数里会带有新的数值;</li>
</ul>
count 属性的工作原理 nickName 属性差不多,仅仅是在声明里明确说了对应的成员变量为 m_count。<br>
<br>
第三个属性是 value ,这是属性声明的极简形式,读写函数都省略了,属性读写的代码由 moc
工具自动生成。因此这种极简形式的属性,它只需要在头文件里放三行声明代码,其他所有代码都不需要:<br>
<div class="code"><span style=" color:#800080;">&nbsp;&nbsp;&nbsp;
Q_PROPERTY</span><span style=" color:#000000;">(</span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span>value<span style=" color:#c0c0c0;"> </span>MEMBER<span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_value</span><span
style=" color:#c0c0c0;"> </span>NOTIFY<span style=" color:#c0c0c0;"> </span>valueChanged<span
style=" color:#000000;">)<br>
</span><br>
<span style=" color:#000000;"><span style=" color:#808000;">signals</span><span
style=" color:#000000;">:</span><br>
</span><span style=" color:#808000;">&nbsp;&nbsp;&nbsp; void</span><span style=" color:#c0c0c0;">
</span><span style=" color:#000000;">valueChanged</span><span style=" color:#000000;">(</span><span
style=" color:#808000;">double</span><span style=" color:#c0c0c0;"> </span>dblNewValue<span
style=" color:#000000;">);<br>
</span><br>
<span style=" color:#808000;">private</span><span style=" color:#000000;">:<br>
</span><span style=" color:#808000;">&nbsp;&nbsp;&nbsp; double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_value</span><span
style=" color:#000000;">;</span></div>
除了属性声明本身的一句,就只需要声明属性值变化是的信号和私有成员变量。<br>
<br>
moc 工具自动生成的读写代码仅仅是代码片段(4.5 节专门讲这些代码),没有函数的,自然没有相关的槽函数,所以如果希望把写函数作为槽函数来用,就得用类
似 count 属性的声明,并自己编读写函数的实体代码。<br>
<br>
头文件代码就如上编辑,下面来添加 widget.cpp 中必须的函数实体代码:<br>
<div class="code"><span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"widget.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"ui_widget.h"</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">Widget</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QWidget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setupUi</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">::~</span><span
style=" font-style:italic; color:#000000;">Widget</span><span style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//读函数定义</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//读nickName数值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">const</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QString</span><span style=" color:#000000;">&amp;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">nickName</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nickName</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//读count数值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_count</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//写函数,在数值发生变化是才发信号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">setNickName</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&amp;</span><span
style=" color:#000000;">strNewName</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">strNewName</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">==</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_nickName</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//数值没变化,直接返回</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//修改数值并触发信号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nickName</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">strNewName</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">emit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nickNameChanged</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">strNewName</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">setCount</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nNewCount</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">nNewCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">==</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_count</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//数值没变化,直接返回</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//修改数值并触发信号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_count</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nNewCount</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">emit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">countChanged</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">nNewCount</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
在 widget.cpp 只需要为 nickName 和 count 两个属性添加读写函数的代码。读函数 nickName() 和 count()
非常简 单,就是返回相应的私有成员变量数值。<br>
对于写函数
setNickName()里面代码,首先判断传入的参数值是否与旧的值相同,如果是一样的就不用修改,直接返回。如果新旧数值不同,那就设置成员变量为新的值,并发送数
值发生变化的信号 nickNameChanged,并把新值作为参数放到信号里面。set 函数里其实可以顺便做一下数值的有效性检查,上面代码里省略了有效性
检查。<br>
对于写函数 setCount 是类似的过程,新旧数值一样就不变,不一样就修改成员变量并发信号。<br>
<br>
窗口类 Widget 的代码就是上面那么多。如何使用这些属性呢?我们可以编辑 main.cpp ,尝试修改和读取这些属性:<br>
<div class="code"><span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"widget.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QApplication&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QDebug&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">main</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">char</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">[])</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QApplication</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//属性读写</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//通过写函数、读函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">setNickName</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"Wid"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">nickName</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">setCount</span><span style=" color:#000000;">(</span><span
style=" color:#000080;">100</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//通过</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">setProperty()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">函数</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"></span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">property()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">setProperty</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"value"</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">2.3456</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span>fixed<span style=" color:#000000;">&lt;&lt;</span><span
style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span style=" color:#000000;">property</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"value"</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">toDouble</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//显示窗体</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">show</span><span style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">exec</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
属性的读写既可以使用各个属性自己的读写函数,如
setNickName()、nickName()、setCount()、count(),也可以使用属性通用的函数:setProperty()
写属性,property() 读属性,都是通过属性的名称来寻找特定属性实现读写。<br>
注意由于上面的 value 属性没有声明读写函数,所以对它的读写只能靠 setProperty() 和 property()
函数,这对通用的属性读写函数的声明如下:<br>
<div class="code">bool QObject::​setProperty(const char * name, const
QVariant &amp; value)</div>
<div class="code">QVariant QObject::​property(const char * name) const</div>
​setProperty() 第一个参数是普通字符串,就是属性的名称,第二个参数是属性的数值,QVariant 是 Qt 定义的通用变量类型,标准
C++ 的类型和 Qt 自己的数值类型都可以自动转为 QVariant 类的对象。<br>
​property() 函数以变量名的字符串作为输入参数,返回一个通用的 QVariant 对象,将 QVariant 对象转为标准类型或者 Qt
数值类型,可以用对应的 to**** 函数,toDouble 是转为双精度浮点数,toInt 是转为整型数, toString 是转为 QString
字符串,还有其他转换函数,详细的请查阅 QVariant 帮助文档。<br>
<br>
代码先添加这些,我们运行这个示例,它执行的结果会打印到输出面板,如下图所示:<br>
<center><img src="images/ch04/ch04-04-01.png" alt="run1" width="800"></center>
<br>
这个例子展示属性的声明和访问,但是还有一个问题,我们在 set***
函数里修改了属性值,应该发了值改变的信号,我们没有接收这些信号,还不知道它们真发信号还是假发信号,得验验货。<br>
我们为这个例子添加一个 C++ 类,名字为 ShowChanges,基类为 QObject:<br>
<center><img src="images/ch04/ch04-04-02.png" alt="class" width="800"></center>
编辑 showchanges.h,为 valueChanged 信号添加对应的槽函数 RecvValue 声明:<br>
<div class="code"><span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;">
</span>SHOWCHANGES_H
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">SHOWCHANGES_H</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QObject&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">ShowChanges</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QObject</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">ShowChanges</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QObject</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">ShowChanges</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">signals</span><span style=" color:#000000;">:</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">slots</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//槽函数,接收</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">value</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">变化信号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">RecvValue</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span>v<span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">SHOWCHANGES_H</span></pre>
</div>
然后编辑 showchanges.cpp,为槽函数添加实体代码:<br>
<div class="code"><span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"showchanges.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QDebug&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">ShowChanges</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">ShowChanges</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QObject</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QObject</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">ShowChanges</span><span style=" color:#000000;">::~</span><span
style=" font-style:italic; color:#000000;">ShowChanges</span><span style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//接收并打印</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">value</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">变化后的新值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">ShowChanges</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">RecvValue</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">v</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#008000;">"RecvValue:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"</span><span style=" color:#000000;">&lt;&lt;</span>fixed<span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#000000;">v</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
这个仅仅是类的代码,接收信号必须要定义一个对象,然后才能关联源头信号和接收端槽函数,下面修改 main.cpp 代码,添加接收端对象和关联函数代码:<br>
<div class="code"><span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"widget.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QApplication&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QDebug&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"showchanges.h"</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">main</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">char</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">[])</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QApplication</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//源头对象</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//接收端对象</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">ShowChanges</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">s</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//关联</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QObject</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">connect</span><span
style=" color:#000000;">(&amp;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SIGNAL</span><span
style=" color:#000000;">(</span>valueChanged<span style=" color:#000000;">(</span><span
style=" color:#808000;">double</span><span style=" color:#000000;">)),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&amp;</span><span
style=" color:#000000;">s</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">SLOT</span><span style=" color:#000000;">(</span>RecvValue<span
style=" color:#000000;">(</span><span style=" color:#808000;">double</span><span
style=" color:#000000;">)));</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//属性读写</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//通过写函数、读函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">setNickName</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"Wid"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">nickName</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">setCount</span><span style=" color:#000000;">(</span><span
style=" color:#000080;">100</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//通过</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">setProperty()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">函数</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"></span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">property()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">setProperty</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"value"</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">2.3456</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span>fixed<span style=" color:#000000;">&lt;&lt;</span><span
style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span style=" color:#000000;">property</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"value"</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">toDouble</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//显示窗体</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">show</span><span style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">exec</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
value 属性值被修改成了 2.3456,这个值一被修改,就会触发 valueChanged 信号,槽函数 RecvValue
被自动调用,并且会接收到新数值并打印出来。运行这个修改后的示例,得到的结果如下:<br>
<center><img src="images/ch04/ch04-04-03.png" alt="run2" width="800"></center>
可以看到,槽函数打印的信息会在 qDebug()&lt;&lt;fixed&lt;&lt;w.property("value").toDouble();
这行调用之前打印出来。无论使用通用的 <br>
setProperty() 函数,还是属性自己独有的 set 函数,变化信号都会正确地发出来。<br>
上面只接收了 valueChanged 信号,还有 nickNameChanged 信号和 countChanged
信号没接收,这个两个信号对应的槽函数和关联函数代码作为练习,请读者自己动手完成。下面小节示范动态属性的使用。<br>
<br>
<div class="os2"> 4.4.3 动态属性示例</div>
<br>
不仅在源代码里面添加属性声明,程序运行时也可以通过 setProperty() 函数为当前类对象添加动态属性,获取动态属性的值也是用
property() 函数。获取全部的动态属性名称列表可以通过 ​dynamicPropertyNames 函数:<br>
<div class="code"> QList&lt;QByteArray&gt; QObject::​dynamicPropertyNames()
const</div>
​dynamicPropertyNames 返回当前所有动态属性名称字符串的列表。<br>
如果尝试用 property() 函数获取不存在的属性名的数值,那么会得到一个特殊的 QVariant 对象,这个对象处于不可用状态,这时
QVariant 对象的 isValid() 函数返回 false。下面示范动态属性的例子。<br>
重新打开 QtCreator ,新建一个 Qt Widgets Application 项目,在新建项目的向导里填写:<br>
①项目名称 dynamicpros,创建路径 D:\QtProjects\ch04,点击下一步;<br>
②套件选择里面选择全部套件,点击下一步;<br>
③基类选择 QWidget,点击下一步;<br>
④项目管理不修改,点击完成。<br>
建好项目之后,Widget 类的代码不需要修改,动态属性不需要额外声明,直接在 main 函数里面使用就行了,我们编辑 main.cpp:<br>
<div class="code"><span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"widget.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QApplication&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QDebug&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">main</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">char</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">[])</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QApplication</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//如果动态属性不存在,QVariant</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">对象的</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">isValid()</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">函数返回</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">false,变量不可用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">property</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"myValue"</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">isValid</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//添加属性</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">myValue</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">setProperty</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"myValue"</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">2.3456</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//获取并打印</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">property</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"myValue"</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">toDouble</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//添加属性</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">myName</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">setProperty</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"myName"</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"Wid"</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//获取并打印</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">property</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"myName"</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">toString</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//获取所有动态属性名称,打印名称列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">dynamicPropertyNames</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">show</span><span style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">exec</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
在 main 函数里,我们先尝试获取一个不存在的属性 myValue,property() 函数返回 QVariant 对象,由于属性不存在,所以
QVariant 对象 isValid() 函数会返回 false,表明不可用状态,也就意味着该属性是不存在的。<br>
<br>
然后我们向窗体对象 w 添加了动态属性 myValue,并用 property() 函数获取了该属性的 QVariant
对象,然后转成双精度浮点数打印。接着我们向窗体对象 w 添加了动态属性 myName,类似地用 property() 函数获取属性的 QVariant
对象,然后转为字符串打印。<br>
最后我们用窗体对象 w 的 dynamicPropertyNames() 函数获取了所有的动态属性名称列表,并打印了动态属性名称列表。<br>
<br>
例子修改的代码只有上面那些,例子运行的效果如下图所示:<br>
<center><img src="images/ch04/ch04-04-04.png" alt="run" width="800"></center>
通过在头文件声明普通的属性,可以为属性标明相关的成员变量、读函数、写函数、变化通知信号等等,而动态属性就没有这些特性,它其实就是以成对的属性名、属性值的
形式存在,可以通过 setProperty() 和 property() 读写,仅此而已,所以动态属性应用得比较少。<br>
<br>
属性系统不仅可以声明普通属性和在运行时添加动态属性,还有一个衍生功能,就是为类添加一些附加信息,运行时可以查询这些附加信息,方便程序员或用户查询相关信
息,下面学习为类添加附加信息的例子。<br>
<br>
<div class="os2"> 4.4.4 类的附加信息</div>
<br>
Qt 程序运行时可以查询当前对象的名称,我们之前 4.2.3 节用 QObject::objectName()
函数获取过对象名称。运行时还可以查询类的信息,主要包括两种类信息,一种是基本的类信息,Qt
类会自动生成这些信息,包括当前类名、继承树上的基类名称等;另一类是程序员手动添加的类附加信息,通过 Q_CLASSINFO()
宏,在类的声明里添加类附加信息,比如:<br>
<div class="code">Q_CLASSINFO("Version", "1.0.0")</div>
附加信息也是成对的“名称-值”,不过注意 名称和值 都是普通字符串。如果希望在运行时查询类的附加信息,可以先用
QObject::metaObject() 获取当前对象包含的元对象数据,然后使用 QMetaObject::​classInfo
函数查询某个序号的附加信息:<br>
<div class="code">const QMetaObject * QObject::​metaObject()
const&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="font-weight: bold;">[virtual]</span></div>
<div class="code">QMetaClassInfo QMetaObject::​classInfo(int index) const</div>
<br>
对于基本信息,可以用 QMetaObject::className() 函数获取类名。如果要判断继承树上是否有某个基类,使用
QObject::​inherits() 函数判断。这两个函数声明如下:<br>
<div class="code">const char * QMetaObject::​className() const</div>
<div class="code">bool QObject::​inherits(const char * className) const</div>
下面示范类的附加信息例子,并顺路打印类的基本信息,判断基类名。<br>
重新打开 QtCreator ,新建一个 Qt Widgets Application 项目,在新建项目的向导里填写:<br>
①项目名称 classinfo,创建路径 D:\QtProjects\ch04,点击下一步;<br>
②套件选择里面选择全部套件,点击下一步;<br>
③基类选择 QWidget,点击下一步;<br>
④项目管理不修改,点击完成。<br>
建好项目之后,编辑 widget.h 头文件,添加附加信息:<br>
<div class="code"><span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;">
</span>WIDGET_H
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">WIDGET_H</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QWidget&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Widget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">Widget</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//类的附加信息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Q_CLASSINFO</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"Version"</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"1.0.0"</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Q_CLASSINFO</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"Author"</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"Winland"</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Q_CLASSINFO</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"Site"</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"https://lug.ustc.edu.cn/sites/qtguide/"</span><span
style=" color:#000000;">)</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">WIDGET_H</span></pre>
</div>
头文件里添加了三行,也就是三对“名称-值”,都是普通字符串。附加信息只需要添加到声明里,不需要其他代码,所以 widget.cpp
文件保持原样,不修改。<br>
下面我们在 main.cpp 里面访问窗体的附加信息和基本信息:<br>
<div class="code"><span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;">
</span><span style=" color:#008000;">"widget.h"</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QApplication&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QDebug&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QMetaClassInfo&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">main</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">char</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">[])</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QApplication</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">argc</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">argv</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">Widget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//获取类的附加信息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QMetaObject</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">pMO</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">metaObject</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//附加信息个数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nInfoCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">pMO</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">classInfoCount</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//打印所有的附加信息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">&lt;</span><span style=" color:#000000;">nInfoCount</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QMetaClassInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">info</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">pMO</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">classInfo</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">i</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">info</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">name</span><span style=" color:#000000;">()&lt;&lt;</span><span
style=" color:#008000;">"\t"</span><span style=" color:#000000;">&lt;&lt;</span><span
style=" color:#000000;">info</span><span style=" color:#000000;">.</span><span style=" color:#000000;">value</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//基本信息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#008000;">"Class</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">Name:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"</span><span style=" color:#000000;">&lt;&lt;</span><span
style=" color:#000000;">pMO</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">className</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#008000;">"Object</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">Name:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"</span><span style=" color:#000000;">&lt;&lt;</span><span
style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span style=" color:#000000;">objectName</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//判断是否为基类</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">inherits</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"QWidget"</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">w</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">inherits</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"nothing"</span><span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//显示窗口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">w</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">show</span><span style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">a</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">exec</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
文件开头添加了 &lt;QDebug&gt;&lt;QMetaClassInfo&gt; 两个头文件,QMetaClassInfo
就是存储附加信息项的类,它有两个公开函数:name() 获取附加信息项的名称,value() 获取附加信息项的值。<br>
在 main 函数里,定义好窗体对象 w,之后,先通过 metaObject() 函数得到一个 QMetaObject 常量指针 pMO;<br>
通过 pMO-&gt;classInfoCount() 获知附加信息项的个数;<br>
然后在 for 循环里枚举 pMO-&gt;classInfo(i) 信息项,打印信息项的名称和值。<br>
<br>
接下来是一些基本信息的获取,类的名字也是通过元对象指针获取 pMO-&gt;className();<br>
窗体对象名可以直接用 w.objectName() 获取;<br>
判断窗体是否从某个基类派生,使用 inherits 函数,这个函数接收一个字符串,如果是对象的直接或间接基类名称就返回 true,否则返回 false。<br>
<br>
这个示例运行结果如下图所示(这里窗体的类名和对象名正好是一样的,其他情况可能不一样):<br>
<center><img src="images/ch04/ch04-04-05.png" alt="run" width="800"></center>
本节大部分内容是上面这些,后面留两个练习,希望读者动手实践一下,并复习一下 C++ 类继承的多态性。下两节我们把本章最复杂的问题尝试讲解一下,就是由
Qt 工具自动生成的代码 ui_*.h 和 moc_*.cpp 等。<br>
<br>
<br>
<div class="practice">
<table>
<tbody>
<tr>
<td><img src="images/pics/practice.png" alt="tip"></td>
<td> <b>练习</b> </td>
</tr>
</tbody>
</table>
① 4.4.2 小节的示例留了两个信号 nickNameChanged 和 countChanged ,没有接收它们的槽函数,请仿造
RecvValue 槽函数的写法,为这两个信号编写对应的槽函数,并实现关联,测试一下效果。<br>
② 修改 4.4.4 例子的代码,将原来的这句:<br>
&nbsp;&nbsp;&nbsp; const QMetaObject *pMO = w.metaObject();<br>
替换为新的两句:<br>
&nbsp;&nbsp;&nbsp; QObject *pObj = &amp;w;<br>
&nbsp;&nbsp;&nbsp; const QMetaObject *pMO = pObj-&gt;metaObject();<br>
然后运行修改后的例子,查看结果有没有变化。注意 pObj 是 QObject 类对象指针,由于 metaObject()
具有多态性,它实际调用的是派生类 Widget 对象的 metaObject() 函数。<br>
</div>
<br>
<br>
<br>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="width: 40%;">
<div style="text-align: center;"><a href="ch04-03.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="prev" src="images/pics/prev.png"></a></div>
</td>
<td style="width: 20%;">
<div style="text-align: center;"><a href="contents.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="contents" src="images/pics/contents.png"></a></div>
</td>
<td style="width: 40%;">
<div style="text-align: center;"><a href="ch04-05.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="next" src="images/pics/next.png"></a></div>
</td>
</tr>
</tbody>
</table>
</body>
</html>
HTML
1
https://gitee.com/qtguide/qtguide.git
git@gitee.com:qtguide/qtguide.git
qtguide
qtguide
qtguide
master

搜索帮助