• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            zhonghua

            C++博客 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
              72 Posts :: 1 Stories :: 4 Comments :: 0 Trackbacks

            #

            Qt提供了一個(gè)絕妙的屬性系統(tǒng)。跟那些由編譯器提供的屬性差不多。然而,作為一個(gè)獨(dú)立于編譯器和平臺(tái)的庫(kù),Qt不依賴于非標(biāo)準(zhǔn)的編譯特性,比如 __property 或[property]。Qt可以在任何平臺(tái)上的標(biāo)準(zhǔn)編譯器下編譯。Qt屬性系統(tǒng)基于元數(shù)據(jù)對(duì)象系統(tǒng)--就是那個(gè)提供了對(duì)象內(nèi)置信號(hào)和槽通訊機(jī)制的家伙。


            聲明屬性需要什么


            要聲明一個(gè)屬性,需在繼承自QObject的類中使用Q_PROPERTY()宏。
            Q_PROPERTY(type name
               READ getFunction
               [WRITE setFunction]
               [RESET resetFunction]
               [NOTIFY notifySignal]
               [DESIGNABLE bool]
               [SCRIPTABLE bool]
               [STORED bool]
               [USER bool]
               [CONSTANT]
               [FINAL])

            下面是一些典型的聲明屬性的示例:

            1. Q_PROPERTY(bool focus READ hasFocus)  
            2. Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)  
            3. Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)  
            • 一個(gè)屬性的行為就像類的數(shù)據(jù)成員,但是它還具有附加的特性,這些特性可以被元數(shù)據(jù)對(duì)象系統(tǒng)操作。這些特性是:
              需要一個(gè)READ訪問器函數(shù)。用于讀屬性的值。理想情況下,有一個(gè)不變的函數(shù)用于此目的,并且它必須返回屬性的類型的值或指針或引用。例如,QWidget::focus是一個(gè)只讀的屬性,它對(duì)應(yīng)一個(gè)讀函數(shù):QWidget::hasFocus()。
            • 一 個(gè)可選的WRITE訪問器函數(shù)。它用于設(shè)置屬性的值。它必須返回空并且至少具有一個(gè)參數(shù),參數(shù)是屬性類型的值或指針或引用。例 如:QWidget::enabled具有WRITE函數(shù)QWidget::setEnable()。只讀屬性不需要寫函數(shù)。例 如,QWidget::focus沒有對(duì)應(yīng)的寫函數(shù)。
            • 一個(gè)可選的RESET函數(shù)。用于設(shè)置屬性的值到它的默認(rèn)值。例 如:QWidget::cursor具有典型的READ和WRITE函數(shù),QWidget::cursor()和 QWidget::setCursor(),并且它也具有一個(gè)RESET函數(shù),QWidget::unsetCursor()。RESET函數(shù)必須返回 void并且不帶有任何參數(shù)。
            • 一個(gè)可選的NOTIFY信號(hào)。如果被定義了,信號(hào)將在屬性的值改變時(shí)發(fā)出。信號(hào)必須帶有一個(gè)參數(shù),這個(gè)參數(shù)的類型必須與屬性相同;參數(shù)保存的是屬性的新值。
            • 一個(gè)DESIGNABLE變量表明此屬性是否在界面設(shè)計(jì)器的屬性編輯器中出現(xiàn)。大多數(shù)屬性是可見的,除了為這個(gè)變量傳入true或false,你還可以指定一個(gè)bool型的成員函數(shù)。
            • SCRIPTABLE變量表明這個(gè)屬性是否可以被一個(gè)腳本引擎操作(默認(rèn)是true)。你也可以賦予它true或false或bool型函數(shù)。
            • STORED 變量表明了屬性是否被認(rèn)為是獨(dú)立存在還是依賴于其它的值而存在。它也表明是否在保存對(duì)象狀態(tài)時(shí)保存此屬性的值。大多數(shù)屬性都是需要保存的,但是,如 QWidget::minimumWidth()就是不被保存的,因?yàn)樗闹凳菑牧硪粋€(gè)屬性QWidget::minimumSize()得來的。
            • USER變量表明屬性是否被設(shè)計(jì)為面向用戶的或用戶可修改的類屬性。通常,每個(gè)類只有一個(gè)USER屬性。例如,QAbstractButton::checked是按鈕類的用戶可修改屬性。注意QItemDelegate獲取和設(shè)置widget的USER屬性。
            • CONSTANT的出現(xiàn)表明屬性的值是不變的。對(duì)于一個(gè)object實(shí)例,常量屬性的READ方法在每次被調(diào)用時(shí)必須返回相同的值。此常量值可能在不同的object實(shí)例中不相同。一個(gè)常量屬性不能具有WRITE方法或NOYIFY信號(hào)。
            • FINAL變量的出現(xiàn)表明屬性不能被派生類所重寫。有些情況下,這可以用于效率優(yōu)化,但不是被moc強(qiáng)制的。程序員必須永遠(yuǎn)注意不能重寫一個(gè)FINAL屬性。

            READ,WRITE和RESET函數(shù)都可以被繼承。它們也可以是虛函數(shù)。當(dāng)它們?cè)诒欢嘀乩^承中被繼承時(shí),它們必須出現(xiàn)在第一個(gè)被繼承的類中。

            屬性的類型可以是被QVariant支持的所有類型,也可以是用戶定義的類型。在下面的例子中,類QDate被當(dāng)作用戶自定義類型。
            Q_PROPERTY(QDate data READ getDate WRITE setDate)
            因?yàn)镼Date是用戶定義的,你必須包含<QDate>頭文件。

            對(duì) 于QMap,QList和QValueList屬性,屬性的值是一個(gè)QVariant,它包含整個(gè)list或map。注意Q_PROPERTY字符串不能 包含逗號(hào),因?yàn)槎禾?hào)會(huì)劃分宏的參數(shù)。因此,你必須使用QMap作為屬性的類型而不是QMap<QString,QVariant>。為了保持 一致性,也需要用QList和QValueList而不是QList<QVariant>和 QValueList<QVariant>。


            通過元數(shù)據(jù)對(duì)象系統(tǒng)讀寫屬性

            一 個(gè)屬性可以使用常規(guī)函數(shù)QObject::property()和QObject::setProperty()進(jìn)行讀寫,不用知道屬性所在類的任何細(xì) 節(jié),除了屬性的名字。在下面的小代碼片段中,調(diào)用QAbstractButton::setDown()和QObject::setProperty() 都把屬性設(shè)置為“down”。

            1. QPushButton *button = new QPushButton;  
            2. QObject *object = button;  
            3. button->setDown(true);  
            4. object->setProperty("down", true);  

            通 過WRITE操作器來操作一個(gè)屬性是上面兩者中更好的,因?yàn)樗觳⑶以诰幾g時(shí)給于更好的診斷幫助,但是以這種方式設(shè)置屬性要求你必須在編譯時(shí)了解其類。通 過名字來操作屬性使你可以操作在編譯器你不了解的類。你可以在運(yùn)行時(shí)發(fā)現(xiàn)一個(gè)類的屬性們,通過查詢它的QObject,QMetaObject和 QMetaProerties。

            1. QObject *object = ...  
            2. const QMetaObject *metaobject = object->metaObject();  
            3. int count = metaobject->propertyCount();  
            4. for (int i=0; i<count; ++i) {  
            5.     QMetaProperty metaproperty = metaobject->property(i);  
            6.     const char *name = metaproperty.name();  
            7.     QVariant value = object->property(name);  
            8.     ...  
            9. }  

            在上面的代碼片段中,QMetaObject::property()被用于獲取未知類中的屬性的metadata。從metadata中獲取屬性名然后傳給QObject::property()來獲取

            一個(gè)簡(jiǎn)單例子


            假 設(shè)我們有一個(gè)類MyClass,它從QObject派生并且在它的private區(qū)使用 了Q_OBJECT宏。我們想在MyClass類中聲明一個(gè)屬性來持續(xù)追蹤一個(gè)Priorty值。屬性的值叫做priority,并且它的類型是一個(gè)在類 MyClass中定義的叫做Priority的枚舉。

            我們?cè)陬惖膒rivate區(qū)使用Q_PROPERTY()來聲明屬性。READ函數(shù) 叫做priority,并且我們包含一個(gè)WRITE函數(shù)叫做setPriority。枚舉類型必須使用Q_ENUMS()注冊(cè)到元數(shù)據(jù)對(duì)象系統(tǒng)中。注冊(cè)一 個(gè)枚舉類型使得枚舉的名字可以在調(diào)用QObject::setProperty()時(shí)使用。我們還必須為READ和WRITE函數(shù)提供我們自己的聲明。 MyClass的聲明看起來應(yīng)該是這樣的:

            1. class MyClass : public QObject  
            2. {  
            3.     Q_OBJECT  
            4.     Q_PROPERTY(Priority priority READ priority WRITE setPriority)  
            5.     Q_ENUMS(Priority)  
            6. public:  
            7.     MyClass(QObject *parent = 0);  
            8.     ~MyClass();  
            9.     enum Priority { High, Low, VeryHigh, VeryLow };  
            10.     void setPriority(Priority priority);  
            11.     Priority priority() const;  
            12. };  

            READ函數(shù)是const的并且返回屬性的類型。WRITE函數(shù)返回void并且具有一個(gè)屬性類型的參數(shù)。元數(shù)據(jù)對(duì)象編譯器強(qiáng)制做這些事情。

            在有了一個(gè)指向MyClass實(shí)例的指針時(shí),我們有兩種方法來設(shè)置priority屬性:

            1. MyClass *myinstance = new MyClass;  
            2.  QObject *object = myinstance;  
            3.  myinstance->setPriority(MyClass::VeryHigh);  
            4.  object->setProperty("priority", "VeryHigh");  

            在 此例子中,枚舉類型在MyClass中聲明并被使用Q_ENUMS()注冊(cè)到元數(shù)據(jù)對(duì)象系統(tǒng)中。這使得枚舉值可以在調(diào)用setProperty()時(shí)做為 字符串使用。如果枚舉類型是在其它類中聲明的,那么我們就需要用枚舉的全名(如OtherClass::Priority),并且這個(gè)其它類也必須從 QObject中派生并且也要注冊(cè)枚舉類型。
            另一個(gè)簡(jiǎn)單的Q_FLAGS()也是可用的。就像Q_ENUMS(),它注冊(cè)一個(gè)枚舉類型,但是它把 枚舉類型作為一個(gè)flag的集合,也就是,值可以用OR操作來合并。一個(gè)I/O類可能具有枚舉值Read和Write并且 QObject::setProperty()可以接受 Read|Write。此時(shí)應(yīng)使用Q_FLAGS()來注冊(cè)枚舉值。

            動(dòng)態(tài)屬性

            Qobject::setProperty() 也可以用來在運(yùn)行時(shí)向一個(gè)類的實(shí)例添加新的屬性。當(dāng)使用一個(gè)名字和值調(diào)用它時(shí),如果一個(gè)對(duì)應(yīng)的屬性已經(jīng)存在,并且如果值的類型與屬性的類型兼容,那么值就 被存儲(chǔ)到屬性中,然后返回true。如果值類型不兼容,屬性的值就不會(huì)發(fā)生改變,就會(huì)返回false。但是如果對(duì)應(yīng)名字的屬性不存在,那么一個(gè)新的屬性就 誕生了,以傳入的名字為名,以傳入的值為值,但是依然會(huì)返回false。這表示返回值不能用于確定一個(gè)屬性是否被設(shè)置值,除非你已經(jīng)知道這個(gè)屬性已經(jīng)存在 于QObject中了。
            注意動(dòng)態(tài)屬性被添加到單個(gè)實(shí)現(xiàn)的基礎(chǔ)中,也就是,被添加到QObject,而不是QMetaObject。一個(gè)屬性可以從 一個(gè)實(shí)例中刪除,通過傳入屬性的名字和非法的QVariant值給QObject::setProperty()。默認(rèn)的QVariant構(gòu)造器構(gòu)造一個(gè) 非法的QVariant。
            動(dòng)態(tài)屬性可用QObject::property()來查詢,就行使用Q_PROPERTY()聲明的屬性一樣。

            屬性和自定義類型

            被屬性使用的自定義類型需要使用Q_DECLARE_METATYPE()宏注冊(cè),以使它們的值能被保存在QVariant對(duì)象中。這使得它們可以用于被Q_PROPERTY()聲明的靜態(tài)類型中,也可以被用于動(dòng)態(tài)類型中。

            posted @ 2013-06-05 09:53 米米 閱讀(1020) | 評(píng)論 (0)編輯 收藏

            QGraphicsItem類是視圖框架的一部分,是在一個(gè)QGraphicsScene中最基本的圖形類,它為繪制你
             
             
             
            自己的item提供了一個(gè)輕量級(jí)的窗口,包括聲明item的位置,碰撞檢測(cè),繪制重載和item之間的相
             
             
             
            互作用通過事件處理
             
            Qt提供了一系列標(biāo)準(zhǔn)的items對(duì)一些常見的圖像,非常的方便,有下面這些:
             
            QGraphicsEllipseItem  提供一個(gè)橢圓item
             
            QGraphicsLineItem     提供一條線的item
             
            QGraphicsPathItem     提供一個(gè)任意的路徑item
             
            QGraphicsPixmapItem   提供一個(gè)圖形item
             
            QGraphicsPolygonItem  提供一個(gè)多邊形item
             
            QGraphicsRectItem     提供一個(gè)矩形item
             
            QGraphicsSimpleTextItem 提供一個(gè)簡(jiǎn)單的文本item
             
            QGraphicsTextItem     提供一個(gè)文本瀏覽item
             
            item 的所有幾何位置信息都建立在本地坐標(biāo)系統(tǒng)上,item的位置,使用pos()獲得,是唯一一個(gè)不再本地item中實(shí)現(xiàn)的。它返回的是item在父親坐標(biāo)系 統(tǒng)中的位置,關(guān)于坐標(biāo)系統(tǒng)可以詳細(xì)參看 The Graphics View Coordinate System
             
             
             
            通 過調(diào)用哪個(gè)setVisible(),可以設(shè)置item是否可見,隱藏一個(gè)item同時(shí)也隱藏了他的孩子,相似的,你可以通過調(diào)用 setEnabled()來是指item是否可用。如果禁用了item,那么它所有的孩子都不可用。默認(rèn)的,items都是可見和可用的。來開關(guān)一個(gè) item是否被選擇,首先通過設(shè)置itemsSelectable flag來使能選擇。然后調(diào)用setSelect(),通常,是否可被選擇的開關(guān)時(shí)打開的
             
             
             
            寫自己的item圖形,首先應(yīng)該繼承QGraphicsItem,然后重寫他的兩個(gè)純虛公共函數(shù),

            boundingRect()和paint(),第一個(gè)函數(shù)返回繪制item大概的區(qū)域,第二個(gè)函數(shù)用來繪制item內(nèi)容
             
             
             


            boundingRect() 函數(shù)有很多用處,場(chǎng)景在boundingRect()來建立它的item的index,視圖view使用它來剪切可見的item,在重新繪制item時(shí) 候,來決定相互重疊的部分,此外,item的碰撞檢測(cè)機(jī)制也使用的boundingRect()來提供一個(gè)高效的定點(diǎn),在 collidesWithItem()更好的碰撞算法建立在調(diào)用函數(shù)shape(),shape()函數(shù)以QpainterPath類型返回item的精 準(zhǔn)的輪廓。
             
            一般的,場(chǎng)景不希望item的boundingRect()和shape()變化,除非該item被通告,如果想通過一些方法改變item的形狀,首先應(yīng)該調(diào)用QgraphicsScene()來允許場(chǎng)景QgraphicsScene來刷新它的item記錄。
             
             
             
            碰撞檢測(cè)可以通過下面兩種方法來完成
             
            1、重寫shape()函數(shù)來返回item的精準(zhǔn)輪廓,依靠默認(rèn)的collidesWithItem()來做外形交集。如果item輪廓和復(fù)雜時(shí)候,這個(gè)消耗是很大的
             
            2、重寫collidesWithItem(),提供一個(gè)自己的item和輪廓碰撞的算法
             
             
             
            Contains()函數(shù)可以調(diào)用,用來決定一個(gè)item是否包含一個(gè)點(diǎn)。這個(gè)函數(shù)也可以重寫,contains()函數(shù)默認(rèn)的方法是通過調(diào)用shape()來完成的。
             
            Items中也可以包含其他的items,也可以被別的items包含,所有的items可以有一個(gè)父親item和一串孩子items,除非一個(gè)item沒有父親,否則它的位置是在父親坐標(biāo)中,父親items遺傳他的位置和轉(zhuǎn)換給孩子item
             
            轉(zhuǎn)換
             
            QgraphicsItem 支持投射轉(zhuǎn)換,有很多方法來改變item的轉(zhuǎn)換,對(duì)于簡(jiǎn)單的轉(zhuǎn)換,可以調(diào)用函數(shù)setRotation()或者setScale(),可以傳遞一個(gè)轉(zhuǎn)換矩 陣給函數(shù)setTransform(),對(duì)于一些更復(fù)雜的轉(zhuǎn)換,可以通過調(diào)用函數(shù)setTransformations()來設(shè)置一系列組合的轉(zhuǎn)換。
             
            Item 轉(zhuǎn)換從父親到孩子進(jìn)行聚集,因此如果一個(gè)父親和孩子item都旋轉(zhuǎn)90度,那么孩子就旋轉(zhuǎn)了180度,相似的,如果父親item放大了2X倍,那么孩子 item就被方法4X倍,一個(gè)item的轉(zhuǎn)換不影響他的外觀,所有和外觀有關(guān)的函數(shù)(例如contains(),update()和所有的映射 mapping函數(shù))將會(huì)在本地坐標(biāo)中操作,更方便的,QgraphicsItem提供函數(shù)sceneTransform(),將會(huì)返回item所有的轉(zhuǎn) 換矩陣,scenePos()將會(huì)返回item在場(chǎng)景坐標(biāo)中的位置,重新設(shè)置item的矩陣,調(diào)用函數(shù)resetTransform()
             
            一 般的轉(zhuǎn)換回產(chǎn)生一個(gè)不同的結(jié)果,這取決于轉(zhuǎn)換應(yīng)用的順序,例如,如果你放大一個(gè)轉(zhuǎn)換,然后再旋轉(zhuǎn)它,可能和你先旋轉(zhuǎn)它得到的結(jié)果不一樣,你設(shè)置轉(zhuǎn)換屬性的 順序并不影響轉(zhuǎn)換的結(jié)果,(也就是仍舊會(huì)按照你的轉(zhuǎn)換命令去轉(zhuǎn)換,只是最后得到的圖形不一樣而已),QgraphicsItem經(jīng)常應(yīng)用一個(gè)合適的順序如 下:
             


            繪圖painting
             
            paint()函數(shù)被QgrapicsView類調(diào)用來繪制item的 內(nèi)容,item默認(rèn)是沒有背景或者填充顏色的。在函數(shù)中沒有被繪制的所有區(qū)域都將會(huì)發(fā)亮,可以調(diào)用update()來重繪item,可以選擇傳遞需要重繪 的矩形區(qū)域(不是必須的)。取決于item在view中是否可見,item可能會(huì)也可能不會(huì)重繪,QgraphicsItem里面沒有和 Qwidget::repaint()函數(shù)等價(jià)的
             
            item通過view來繪制,從父items開始,然后是自items,以上升的棧的 順序,可以通過調(diào)用setZValue()設(shè)置item的棧順序,通過zValue()來測(cè)試,具有低z-values的item比具有高z-value 的item先繪制,棧順序應(yīng)用于兄弟items,父items總是比子items更早繪制。
             
             
             
            排序sort
             
            所有的items都按照一個(gè)已經(jīng)聲明的,穩(wěn)定的順序來繪制,這個(gè)順序也決定了當(dāng)你在場(chǎng)景中點(diǎn)擊鼠標(biāo)時(shí)候,哪個(gè)items最先接受鼠標(biāo)的輸入。一般的,你不需要擔(dān)心排序問題,因?yàn)樗械膇tems都按照一個(gè)在場(chǎng)景中聲明的自然的順序
             


            在一個(gè)棧中,子item在父item的上面,兄弟item按照插入場(chǎng)景的順序來入棧,如果你先添加了item A ,然后是item B,然后是item C ,這樣棧中的順序從下往上就是A,B,C
             
            Drag and Drop Robot例子中展示了該robot的棧順序,軀干順序是根item(其他所有的item都是軀干item的子item或者后代item),然后是頭 item被繪制,由于它是軀干item的子item列表中的第一個(gè)item,然后是左臂膀上面的那部分item,下面那個(gè)臂膀item是上面臂膀item 的子item,所以會(huì)在和3號(hào)item同等級(jí)的兄弟item繪制完后被繪制,接著就是右邊上面的的臂膀item,就是5號(hào)item。
             
             。可以調(diào)用setZvalue()來設(shè)置一個(gè)item的相對(duì)亦另一個(gè)向上,向下或者兄弟棧順序。默認(rèn)的Z值是0,具有同樣的Z值的item會(huì)按照插入的順序來入棧。
             
            。可以調(diào)用stackBefore()來備份孩子item的列表,這可以直接更正item的順序。
             
            。如果想讓孩子item在父item的后面,也就是先繪制孩子item,然后在繪制父item,怎么辦呢?可以設(shè)置ItemStacksBehindParent屬性給這個(gè)item,利用函數(shù)setFlag();
             
            兩個(gè)兄弟item的順序也決定了他們的子item 和后代item的順序,如果一個(gè)父item的在兩個(gè)父item的后面,那么他所有的孩子items都在另一個(gè)父item的孩子items后面。
             
             
             
            事件Event
             
            QgraphicsItem從場(chǎng)景中通過sceneEvent()函數(shù)來接受事件,這個(gè)函數(shù)通過一些方便的操作分散大部分事件
             
            ContextMenuEvent()函數(shù)接受上下文菜單事件
             
            FocusInEvent()和focusOutEvent()函數(shù)接受焦點(diǎn)進(jìn)出事件
             
            hoverEnterEvent(), hoverMoveEvent(), and hoverLeaveEvent() 接受鼠標(biāo)懸浮 移動(dòng)和離開事件
             
            inputMethodEvent()函數(shù)處理輸入法事件,
             
            keyPressEvent() and keyReleaseEvent()事件處理鍵盤按下和松開事件
             
            mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and mouseDoubleClickEvent()處理鼠標(biāo)按下,移動(dòng),松開,雙擊事件
             
            也 可以為一些item過濾一些事件通過安裝過濾器,這個(gè)和QT一般的事件過濾器不一樣,一般的過濾器只工作在Qobject和它的子類,通過調(diào)用 installSceneEventFilter()為item安裝了過濾器后,被過濾的事件將會(huì)被虛函數(shù)sceneEventFilter().捕捉 到,可以通過調(diào)用函數(shù)removeSceneEventFilter().來去除掉事件過濾器
             
             
             
            Custom Data數(shù)據(jù)
             
            有 些時(shí)候?yàn)閕tem注冊(cè)一些數(shù)值很有用,做一個(gè)普通的item或者標(biāo)準(zhǔn)的item,可以調(diào)用setData()來為任一個(gè)item設(shè)置值,這個(gè)值使用 key-value對(duì),(key是整形,value是變種數(shù)據(jù)Qvarient)來得到item的數(shù)據(jù),通過調(diào)用data(),
             
             
             
             
             
             
             
             
             
             
             
            1、QVariant QGraphicsItem::itemChange ( GraphicsItemChange change, const QVariant & value )   [virtual protected]
             
            這個(gè)函數(shù)被QGraphicsItem調(diào)用用來標(biāo)明items的一些狀態(tài)改變了,通過重載這個(gè)函數(shù),可以對(duì)自己定義事件響應(yīng),在一些情況下,可以做一些調(diào)整。
             
            參數(shù)change是改變的那個(gè)item的改變狀態(tài)參數(shù),value是一個(gè)新的數(shù)據(jù),他的類型取決于change,
             
             
             
            change是QGraphicsItem::GraphicsItemChange的枚舉變量
             
            enum      GraphicsItemChange { ItemEnabledChange, ItemEnabledHasChanged,

             
             
            ItemMatrixChange, ItemPositionChange, ..., ItemScenePositionHasChanged }
             
            例如:
             
             QVariant Component::itemChange(GraphicsItemChange change, const QVariant &value)
             
             {
             
                 if (change == ItemPositionChange && scene()) {
             
                     // value is the new position.
             
                     QPointF newPos = value.toPointF();
             
                     QRectF rect = scene()->sceneRect();
             
                     if (!rect.contains(newPos)) {
             
                         // Keep the item inside the scene rect.
             
                         newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
             
                         newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
             
                         return newPos;
             
                     }
             
                 }
             
                 return QGraphicsItem::itemChange(change, value);
             
             }
             
            默認(rèn)的函數(shù)什么都不做,只返回value
             
            注 意:在使用這個(gè)函數(shù)時(shí)候,在函數(shù)內(nèi)部調(diào)用函數(shù)時(shí)候要小心,因?yàn)檫@可能導(dǎo)致一些意想不到的結(jié)果,例如:你不能再這個(gè)函數(shù)里面調(diào)用setPos()在 change是ItemPositionChange時(shí)候,由于setPos()函數(shù)將會(huì)再次調(diào)用 itemChange(ItemPositionChange),如此就一直循環(huán)下去了。
             
            2、void QGraphicsItem::setFlag ( GraphicsItemFlag flag, bool enabled = true )
             
            void QGraphicsItem::setFlags ( GraphicsItemFlags flags )
             
            把flags設(shè)置為item的屬性,如果item獲得了光標(biāo),但是flags沒有使能ItemsFocusable,這個(gè)item
             
             
             
            將會(huì)丟失光標(biāo),同樣的,當(dāng)item被選擇到,但是沒有使能ItemsSelectable,這個(gè)item會(huì)自動(dòng)的失去
             
             
             
            選擇。
             
            默認(rèn)的,所有的flags都是不可用的。(QGraphicsWidget 為了獲得位置變化默認(rèn)使能了
             
             
             
            ItemSendsGeometryChanges)
             
            相近的函數(shù)
             
            GraphicsItemFlags QGraphicsItem::flags () const
             
            返回item的所有使能的flags,例如,如果flags里面包含了ItemIsFocusable,這個(gè)item可以接受
             
             
             
            輸入光標(biāo)
             
            3、QPainterPath QGraphicsItem::shape () const   [virtual]
             
            以QPainterPath返回item在local坐標(biāo)中的形狀,這個(gè)形狀可以用來做很多事情,包括碰撞偵測(cè),
             
             
             
            打擊測(cè)試,還有用來 QGraphicsScene::items() 函數(shù)
             
            默認(rèn)的函數(shù)調(diào)用boundingRect()返回一個(gè)簡(jiǎn)單的矩形形狀,但是子類可以重載這個(gè)函數(shù),為非矩形
             
             
             
            的item返回一個(gè)更加精準(zhǔn)的形狀,例如一個(gè)圓形的item可以選擇返回一個(gè)橢圓形,用來獲得更好的
             
             
             
            碰撞偵測(cè)效果。代碼:
             
            QPainterPath RoundItem::shape() const
             
             {
             
                 QPainterPath path;
             
                 path.addEllipse(boundingRect());
             
                 return path;
             
             }
             
            形狀的輪廓線可以通過繪制時(shí)候的pen來變化
             
            4、QRectF QGraphicsItem::boundingRect () const   [pure virtual]
             
            這個(gè)純虛函數(shù)用矩形聲明了item的邊界輪廓,所有的繪制都必須限定在item的矩形邊框內(nèi)。
             
             
             
            QGraphicsView使用這個(gè)方法來決定item是否需要重繪
             
            盡管item的形狀可以是任意的,但是邊框一直都是矩形,不影響items的變換
             
            如果想改變items的邊框,應(yīng)該首先調(diào)用prepareGeometryChange(),這將通知場(chǎng)景scene即將發(fā)生的變化,這樣場(chǎng)景可以刷新item的位置下標(biāo)。否則,場(chǎng)景將不會(huì)察覺到item的變化,結(jié)果也未知。
             
            如果要重繪item時(shí)候,重載這個(gè)函數(shù)來讓QGraphicsView來決定item的邊界區(qū)域,
             
            注意:由于繪制邊界時(shí)候的邊界輪廓線,在這個(gè)矩形區(qū)域內(nèi)包含畫筆pen寬度的一半很重要,不需
             
             
             
            要補(bǔ)償畫圖走樣  例如
             
             QRectF CircleItem::boundingRect() const
             
             {
             
                 qreal penWidth = 1;
             
                 return QRectF(-radius - penWidth / 2, -radius - penWidth / 2,
             
                               diameter + penWidth, diameter + penWidth);
             
             }
             
             
             
            同樣的一個(gè)返回item輪廓的函數(shù)
             
            QRegion QGraphicsItem::boundingRegion ( const QTransform & itemToDeviceTransform ) const
             
            返回該item的輪廓區(qū)域,返回的區(qū)域的坐標(biāo)系統(tǒng)依賴于參數(shù)itemToDeviceTransform,如果你傳遞一個(gè)Qtransform對(duì)象作為參數(shù),那么函數(shù)將返回本地坐標(biāo)系統(tǒng)區(qū)域
             
            返回的區(qū)域是item內(nèi)容可見的一個(gè)大概的輪廓,盡管計(jì)算起來很浪費(fèi)空間和時(shí)間,但是比boundingRect()更精準(zhǔn),而且當(dāng)重繪時(shí)候,它還能避免不必要的重繪。對(duì)像線或者簡(jiǎn)單的多邊形來說非常有效。
             
            也可以調(diào)節(jié)輪廓區(qū)域的粒度通過調(diào)用setBoundingRegionGranularity(),默認(rèn)的粒度是0,這時(shí)候item的區(qū)域和輪廓矩形一樣的。
             
            itemToDeviceTransform是從item坐標(biāo)系統(tǒng)到設(shè)備坐標(biāo)系統(tǒng)的一個(gè)轉(zhuǎn)換。如果你想讓這個(gè)函數(shù)返回一個(gè)場(chǎng)景坐標(biāo)區(qū)域,可以用函數(shù)sceneTransform()作為參數(shù)。
             
             
             
            相關(guān)函數(shù)qreal QGraphicsItem::boundingRegionGranularity () const
             
            返回item的輪廓區(qū)域粒度
             
             
             
            5、void QGraphicsItem::setPos ( const QPointF & pos )
             
            在父對(duì)象坐標(biāo)系統(tǒng)中設(shè)置item的位置為pos,對(duì)沒有父對(duì)象的items,pos使用的場(chǎng)景的坐標(biāo)系統(tǒng),
             
            6、QPointF QGraphicsItem::scenePos () const
             
            返回該item在場(chǎng)景中的坐標(biāo)點(diǎn),等價(jià)于調(diào)用函數(shù)mapToScene(0, 0).
             
            7、QPointF QGraphicsItem::pos () const
             
            返回item在父坐標(biāo)系中的位置,如果沒有父坐標(biāo)系,那么返回在場(chǎng)景坐標(biāo)系中的位置,此時(shí)等價(jià)于調(diào)用scenePos (),可以直接調(diào)用scenePos ()來獲取該item在場(chǎng)景中的位置,從而忽略其父對(duì)象。
             
             
             
            8、enum QGraphicsItem::CacheMode
            設(shè)置繪圖的緩沖模式,默認(rèn)是沒有緩沖,如果使用緩沖區(qū)的話,在重繪時(shí)候,非常快
             
            設(shè)置緩沖模式使用函數(shù)QGraphicsItem::setCacheMode().
             
             
             
            9、bool QGraphicsItem::acceptDrops () const
             
            如果item能夠接受拖拽事件,就返回真,否則返回假,默認(rèn)的不能接受拖拽事件
             
             同類函數(shù)
             
            void QGraphicsItem::setAcceptDrops ( bool on )
             
            如果On是真的話,就設(shè)置item可以接受拖拽事件,否則對(duì)拖拽事件是透明的,也就是不能響應(yīng)拖拽,默認(rèn)是不響應(yīng)的。
             
            10、bool QGraphicsItem::acceptHoverEvents () const
             
            如果可以接受鼠標(biāo)懸浮在他上面的事件,就返回真,否則返回假。默認(rèn)也是不接受該事件的。
             
            同樣的用于設(shè)置是否接受該事件的函數(shù)
             
            void QGraphicsItem::setAcceptHoverEvents ( bool enabled )
             
            如果enabled為真,就接受,否則就不接受。
             
            11、Qt::MouseButtons QGraphicsItem::acceptedMouseButtons () const
             
            返回這個(gè)item所能接受的鼠標(biāo)事件的鼠標(biāo)鍵,默認(rèn)的是所有的鼠標(biāo)鍵事件都能接受。
             
            同 樣的使用函數(shù)void QGraphicsItem:: setAcceptedMouseButtons ( Qt::MouseButtons buttons )來設(shè)置接受的鼠標(biāo)鍵事件,如果想忽略某個(gè)鼠標(biāo)鍵事件,可以用setAcceptedMouseButtons(0)
             
            12、void QGraphicsItem::advance ( int phase )   [virtual]
             
            這 個(gè)虛函數(shù)被QGraphicsScene::advance()調(diào)用兩次,第一次調(diào)用,所有的items都調(diào)用,使用參數(shù)phase=0,表示場(chǎng)景中所有 的items都將advance(前進(jìn)),然后所有的items都將調(diào)用,使用參數(shù)phase=1,重寫這個(gè)函數(shù),可以來刷新你的item,如果你需要簡(jiǎn) 單的場(chǎng)景控制動(dòng)畫。
             
            默認(rèn)的該函數(shù)什么事都不做
             
            如果想寫動(dòng)畫,可以使用兩種方法,一個(gè)使用 QGraphicsItemAnimation,,或多重繼承Qobject和QgraphicsItem,然后使用 QObject::startTimer() 和 QObject::timerEvent().來使item成動(dòng)畫。
             
             
             
            13、QList<QGraphicsItem *> QGraphicsItem::childItems () const
             
            返回孩子item的一個(gè)鏈表,這些items按照棧順序排列,考慮了item的插入順序和Z-values
             
            14、QRectF QGraphicsItem::childrenBoundingRect () const
             
            返回這個(gè)item的所有子孫items的本地坐標(biāo)系統(tǒng)輪廓矩形。這個(gè)矩形包括了這個(gè)item所有的子孫item,如果這個(gè)item不含有子孫item,這個(gè)函數(shù)將返回一個(gè)空的矩形。
             
            返回的矩形不包括item本身的輪廓矩形,只返回子孫item的矩形輪廓,如果你想包含item本身的矩形區(qū)域,可以使用QRectF::operator|()把boundingRect()和hildrenBoundingRect()或起來。
             
            這個(gè)函數(shù)很復(fù)雜,它決定了返回輪廓的大小通過重復(fù)所有子孫item
             
             
             
            15、void QGraphicsItem::clearFocus ()
             
            去除item的光標(biāo),如果原來有光標(biāo)焦點(diǎn),當(dāng)焦點(diǎn)失去時(shí)候,事件focus out event會(huì)發(fā)送給這個(gè)item,提示他將會(huì)失去焦點(diǎn)。
             
            Item只有設(shè)置了ItemsFocusable屬性,或者widget設(shè)置了合適的焦點(diǎn)策略,才能接受鍵盤焦點(diǎn)。
             
             
             
             
             
            16、 bool QGraphicsItem::collidesWithItem ( const QGraphicsItem * other, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const   [virtual]
             
            如 果這個(gè)item和另一個(gè)item碰撞就返回真,mode是應(yīng)用于其他item的,默認(rèn)是Qt::IntersectsItemShape,如果其他的 item和這個(gè)item相互影響或者包含,被包含于這個(gè)item的形狀(詳見Qt::ItemSelectionMode)。
             
            默認(rèn)的函 數(shù)是就基于外形相互影響,它調(diào)用兩個(gè)item的shape()函數(shù),這將會(huì)花費(fèi)很大時(shí)間,你可以在QgraphicsItem子類中重寫這個(gè)函數(shù),提供一 個(gè)簡(jiǎn)單的算法。這樣你可以使用自己item的一些參數(shù),這樣可以提高碰撞偵測(cè)的效果。例如,兩個(gè)完全沒有轉(zhuǎn)換的圓item的碰撞可以通過對(duì)比他們的圓心位 置和半徑
             
             
             
            17、bool QGraphicsItem::collidesWithPath ( const QPainterPath & path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const   [virtual]
             
            如果item按照path碰撞就返回真,
             
             
             
            18、QList<QGraphicsItem *> QGraphicsItem::collidingItems ( Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const
             
            返回和這個(gè)item相互碰撞的item的鏈表
             
            碰撞偵測(cè)模式取決于mode,
             
             
             
            19\ QGraphicsItem * QGraphicsItem::commonAncestorItem ( const QGraphicsItem * other ) const
             
            返回item最近的祖先item,如果other為0,或者沒有祖先item,就返回0
             
             
             
            20、bool QGraphicsItem::contains ( const QPointF & point ) const   [virtual]
             
            如果item包含了點(diǎn)point就返回TRUE,否則返回FALSE,最常用的是在QgraphicsView中調(diào)用,來判斷這個(gè)item是否在光標(biāo)下面,如果要重寫這個(gè)函數(shù),那就盡可能的簡(jiǎn)單。默認(rèn)的這個(gè)函數(shù)調(diào)用的shape()函數(shù)
             
             
             
            21、void QGraphicsItem::contextMenuEvent ( QGraphicsSceneContextMenuEvent * event )   [virtual protected]
             
            右鍵菜單事件,可以在子類中重寫這個(gè)函數(shù),event里面包含了事件要具體處理的數(shù)據(jù)。
             
            如果忽略這個(gè)事件,調(diào)用函數(shù)QEvent::ignore(),事件event將會(huì)被傳播到任何在該item之下的items,如果沒有item響應(yīng)這個(gè)事件,那么場(chǎng)景就忽略這個(gè)事件,傳遞給view視圖
             
            通常是響應(yīng)該事件打開一個(gè)右鍵菜單,例如
             
            void CustomItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)  {      QMenu menu;      QAction *removeAction = menu.addAction("Remove");      QAction *markAction = menu.addAction("Mark");      QAction *selectedAction = menu.exec(event->screenPos());      // ...  }
             
             
            默認(rèn)是忽略該事件。
             
             
             
             
             
            22、QVariant QGraphicsItem::data ( int key ) const
             
            以Qvariant的格式返回item中的數(shù)據(jù),當(dāng)前的item數(shù)據(jù)對(duì)存儲(chǔ)任意數(shù)據(jù)很有用,例如
             
            static const int ObjectName = 0;    QGraphicsItem *item = scene.itemAt(100, 50);  if (item->data(ObjectName).toString().isEmpty()) {      if (qgraphicsitem_cast<ButtonItem *>(item))          item->setData(ObjectName, "Button");  }
            void QGraphicsItem::setData ( int key, const QVariant & value )
             
            用來設(shè)置item的數(shù)據(jù)
             
            23、QTransform QGraphicsItem::deviceTransform ( const QTransform & viewportTransform ) const
             
            返回item設(shè)備的轉(zhuǎn)換矩陣,使用viewportTransform來從場(chǎng)景到設(shè)備影射坐標(biāo),這個(gè)矩陣可以用來從這個(gè)item本地坐標(biāo)到視圖口坐標(biāo)系統(tǒng)映射坐標(biāo)或者幾何圖形,如果要映射視圖口坐標(biāo)到本地坐標(biāo),首先應(yīng)該轉(zhuǎn)換返回的這個(gè)矩陣。
             
            QGraphicsRectItem rect;  rect.setPos(100, 100);    rect.deviceTransform(view->viewportTransform()).map(QPointF(0, 0));  // returns the item's (0, 0) point in view's viewport coordinates    rect.deviceTransform(view->viewportTransform()).inverted().map(QPointF(100, 100));  // returns view's viewport's (100, 100) coordinate in item coordinates
            這個(gè)函數(shù)是結(jié)合了到場(chǎng)景的轉(zhuǎn)換和到視圖的轉(zhuǎn)換,設(shè)備轉(zhuǎn)換可以用來對(duì)那些沒有進(jìn)行轉(zhuǎn)換坐標(biāo)的item計(jì)算碰撞。
             
            24、拖拽類函數(shù)
             
            void QGraphicsItem::dragEnterEvent ( QGraphicsSceneDragDropEvent * event )   [virtual protected]
             
            void QGraphicsItem::dragLeaveEvent ( QGraphicsSceneDragDropEvent * event )   [virtual protected]
             
            void QGraphicsItem::dragMoveEvent ( QGraphicsSceneDragDropEvent * event )   [virtual protected]
             
            void QGraphicsItem::dropEvent ( QGraphicsSceneDragDropEvent * event )   [virtual protected]
             
             
             
            25、qreal QGraphicsItem::effectiveOpacity () const
             
            返回item的有效透明度,這個(gè)數(shù)值在0.0~~1.0之間
             
            同樣的可以用函數(shù)void QGraphicsItem::setOpacity ( qreal opacity )來設(shè)置透明度,
             
            默認(rèn)的子item繼承父item的透明度
             
            同樣可以設(shè)置item的屬性QGraphicsItem::ItemIgnoresParentOpacity 來忽略父item的透明度對(duì)自己的影響
             
            設(shè)置子item的屬性QGraphicsItem::ItemIgnoresTransformations來忽略視圖轉(zhuǎn)換(放大,縮小)等操作對(duì)自己的影響,在顯示文本時(shí)候很有用。
             
             
             
            26、void QGraphicsItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event )   [virtual protected]
             
            void QGraphicsItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event )   [virtual protected]
             
            void QGraphicsItem::hoverMoveEvent ( QGraphicsSceneHoverEvent * event )   [virtual protected]
             
            鼠標(biāo)懸浮事件
             
             
             
            27、void QGraphicsItem::mouseDoubleClickEvent ( QGraphicsSceneMouseEvent * event )   [virtual protected]
             
            void QGraphicsItem::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )   [virtual protected]
             
            void QGraphicsItem::mousePressEvent ( QGraphicsSceneMouseEvent * event )   [virtual protected]
             
            void QGraphicsItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )   [virtual protected]
             
            鼠標(biāo)雙擊,移動(dòng),釋放的事件
             
             
             
             
             
             
             
            28、QPointF QGraphicsItem::mapFromItem ( const QGraphicsItem * item, const QPointF & point ) const
             
            QPolygonF QGraphicsItem::mapFromItem ( const QGraphicsItem * item, const QRectF & rect ) const
             
            QPainterPath QGraphicsItem::mapFromItem ( const QGraphicsItem * item, const QPainterPath & path ) const
             
            QPolygonF QGraphicsItem::mapFromItem ( const QGraphicsItem * item, qreal x, qreal y, qreal w, qreal h ) const
             
            QPointF QGraphicsItem::mapFromItem ( const QGraphicsItem * item, qreal x, qreal y ) const
             
            QPointF QGraphicsItem::mapFromParent ( const QPointF & point ) const
             
            QPolygonF QGraphicsItem::mapFromParent ( const QRectF & rect ) const
             
            QPolygonF QGraphicsItem::mapFromParent ( const QPolygonF & polygon ) const
             
            QPainterPath QGraphicsItem::mapFromParent ( const QPainterPath & path ) const
             
            QPolygonF QGraphicsItem::mapFromParent ( qreal x, qreal y, qreal w, qreal h ) const
             
            QPointF QGraphicsItem::mapFromParent ( qreal x, qreal y ) const
             
            QPointF QGraphicsItem::mapFromScene ( const QPointF & point ) const
             
            QPolygonF QGraphicsItem::mapFromScene ( const QRectF & rect ) const
             
            QPolygonF QGraphicsItem::mapFromScene ( const QPolygonF & polygon ) const
             
            QPainterPath QGraphicsItem::mapFromScene ( const QPainterPath & path ) const
             
            QPolygonF QGraphicsItem::mapFromScene ( qreal x, qreal y, qreal w, qreal h ) const
             
            QPointF QGraphicsItem::mapFromScene ( qreal x, qreal y ) const
             
            QRectF QGraphicsItem::mapRectFromItem ( const QGraphicsItem * item, const QRectF & rect ) const
             
            QRectF QGraphicsItem::mapRectFromItem ( const QGraphicsItem * item, qreal x, qreal y, qreal w, qreal h ) const
             
            。。。。。。。。。。太多了
             
            轉(zhuǎn)換矩陣函數(shù)
             
             
             
             
             
            29、void QGraphicsItem::moveBy ( qreal dx, qreal dy )
             
            向x,y方向上移動(dòng)dx,dy的距離,等價(jià)于調(diào)用setPos(pos()+QpointF(dx,dy))
             
             
             
             
             
            30\最重要的一個(gè)函數(shù)
             
            void QGraphicsItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 )   [pure virtual]
             
            這個(gè)函數(shù)通常被view調(diào)用,然后再本地坐標(biāo)系統(tǒng)中繪制item的內(nèi)容
             
             
             
            31、qreal QGraphicsItem::rotation () const
             
            返回item的旋轉(zhuǎn)度,
             
            設(shè)置旋轉(zhuǎn)度函數(shù)使用setRotation(),
             
             
             
            32、qreal QGraphicsItem::scale () const
             
            返回縮放系數(shù)
             
            設(shè)置縮放使用setScale()
             
             
             
            33、bool QGraphicsItem::sceneEvent ( QEvent * event )   [virtual protected]
             
            截獲事件,在事件沒有分發(fā)給各個(gè)具體的事件處理函數(shù)之前。
             
            相當(dāng)于bool QObject::event ( QEvent * e )   [virtual]
             
             
             
            34、void QGraphicsItem::scroll ( qreal dx, qreal dy, const QRectF & rect = QRectF() )
             
            滾動(dòng)item
             
             
             
            35、在使item能響應(yīng)一些事件之前,需要先使能這個(gè)功能,例如
             
            void QGraphicsItem::setAcceptDrops ( bool on ) 

            如果on為真,那么就使能拖拽,否則將會(huì)忽略拖拽事件。默認(rèn)是不接受的
             
            void QGraphicsItem::setAcceptHoverEvents ( bool enabled )
             
            如果on為真,使能鼠標(biāo)懸浮事件。默認(rèn)不接受該事件。
             
            void QGraphicsItem::setAcceptTouchEvents ( bool enabled )
             
            在一些支持觸摸的設(shè)備上,這個(gè)函數(shù)將使能觸摸事件。
             
             
             
            36、void QGraphicsItem::setEnabled ( bool enabled )
             
            使該item有效,如果enabled為假,則該item不能用了
             
             
             
            37、void QGraphicsItem::setGraphicsEffect ( QGraphicsEffect * effect )、
             
            設(shè)置item的效果,可以用模糊效果,印象效果,給定顏色繪制效果,透明效果等
             
            詳細(xì)的可以參見QgraphicsEffect類
             
             
             
            38、const int QGraphicsItem::Type
             
            返回該item的類型值,這個(gè)值是自己通過定義Type的值,然后使用type()虛函數(shù)來返回的,看例子
             
            class QGraphicsPathItem : public QAbstractGraphicsShapeItem  {   public:    enum { Type = 2 };      int type() const { return Type; }    ...  };
             
             
            39、T qgraphicsitem_cast ( QGraphicsItem * item )
             
            如果item是T類型的,把item轉(zhuǎn)換成T類型的item,如果失敗,則返回0
             
            如果想讓他正確的工作,需要重新實(shí)現(xiàn)函數(shù)type()來進(jìn)行判斷

            posted @ 2013-05-24 11:08 米米 閱讀(4150) | 評(píng)論 (0)編輯 收藏

            一:qt plugin 介紹

                  Qt Plugin和其他類型的插件一樣,是一種計(jì)算機(jī)應(yīng)用程序,它和主應(yīng)用程序(host application)互相交互,以提供特定的功能。應(yīng)用程序支持Plugin有許多原因,一些主要原因包括:使得第三方開發(fā)者有能力擴(kuò)展應(yīng)用程序,以提供無法先期預(yù)料的特色;減小應(yīng)用程序的大小;由于軟件版權(quán)之間的不兼容性將源代碼和應(yīng)用程序分享。Qt Plugin 分動(dòng)態(tài)插件和靜態(tài)插件兩種。

            二:qt plugin 創(chuàng)建和使用方法

            Qt有兩種與插件有關(guān)的API。一種用來擴(kuò)展Qt本身的功能,如自定義數(shù)據(jù)庫(kù)驅(qū)動(dòng),圖像格式,文本編解碼,自定義分格,等等,稱為Higher-Level API。另一種用于應(yīng)用程序的功能擴(kuò)展,稱為Lower-Level API。前一種是建立在后一種的基礎(chǔ)之上的。這里討論的是后一種,即用來擴(kuò)展應(yīng)用程序的Lower-level API

            讓應(yīng)用程序支持插件擴(kuò)展的步驟:

             1. 定義一個(gè)接口集(只有純虛函數(shù)的類),用來與插件交流。

             2. 用宏Q_DECLARE_INTERFACE()將該接口告訴Qt元對(duì)象系統(tǒng)。

             Q_DECLARE_INTERFACE(BrushInterface,"com.trolltech.PlugAndPaint.BrushInterface/1.0")

             3. 應(yīng)用程序中用QPluginLoader來裝載插件。

             4. 用宏qobject_cast()來確定一個(gè)插件是否實(shí)現(xiàn)了接口。

             QObject *obj = new QTimer; 

             QTimer *timer = qobject_cast<QTimer *>(obj);

            寫一個(gè)插件的步驟:

             1. 聲明插件類,該類從QObject和該插件希望實(shí)現(xiàn)的接口繼承而來。

             2. 用宏Q_INTERFACES()將該接口告訴Qt元對(duì)象系統(tǒng)。

              class BasicToolsPlugin : public QObject,

                                        public BrushInterface,

                                        public ShapeInterface,

                                        public FilterInterface

              {

                   Q_OBJECT

                   Q_INTERFACES(BrushInterface ShapeInterface FilterInterface)

              public:

                   ...

               };

             3. 用宏Q_EXPORT_PLUGIN2()導(dǎo)出插件。

              Q_EXPORT_PLUGIN2 ( PluginName, ClassName )

             4. 用適當(dāng)?shù)?/span>.pro文件構(gòu)建插件。

            下面的代碼聲明了一個(gè)接口類:

             

            class FilterInterface

             {

             public:

                    virtual ~FilterInterface() {}

                    virtual QStringList filters() const = 0;

                    virtual QImage filterImage(const QString &filter, const QImage &image, QWidget* parent)=0;

              };

            Q_DECLARE_INTERFACE(FilterInterface, "com.trolltech.PlugAndPaint.FilterInterface/1.0")

            這里是實(shí)現(xiàn)該接口的插件類的定義:

             

             #include <QObject>

             #include <QStringList>

             #include <QImage>

             #include <plugandpaint/interfaces.h>

             class ExtraFiltersPlugin : public QObject, public FilterInterface

             {

             Q_OBJECT

             Q_INTERFACES(FilterInterface)

             public:

                 QStringList filters() const;

                 QImage filterImage(const QString &filter, const QImage &image,

                 QWidget *parent);

             };

            根據(jù)插件的類型不同,pro文件中配置上有不同。下面是pro文件分析:

            TEMPLATE      = lib                                  // 聲明為lib,動(dòng)態(tài)和靜態(tài)插件一樣。

            CONFIG       += plugin static                // 聲明為plugin,帶static表面為靜態(tài),否則為動(dòng)態(tài)。

            INCLUDEPATH += ../..

            HEADERS       = basictoolsplugin.h

            SOURCES       = basictoolsplugin.cpp

            TARGET        = $$qtLibraryTarget(pnp_basictools)           // 指明插件的名稱

            DESTDIR       = ../../plugandpaint/plugins

            加載插件的主應(yīng)用程序默認(rèn)在當(dāng)前目錄下的plugins文件夾中尋找可用插件,如果是動(dòng)態(tài)插件,則直接放在plugins文件夾中便可,如果是靜態(tài),則需要在主應(yīng)用程序的main函數(shù)的開始的地方用宏:Q_IMPORT_PLUGIN(pluginname(和pro文件中聲明的一致))聲明需要加載的插件并在工程配置中指明插件的lib位置。

            三:基于qt plugin 技術(shù)的框架結(jié)構(gòu)設(shè)想

            1.      愿景

            由于我們目前系統(tǒng)功能多,模塊多,缺乏系統(tǒng)的整體性。我們想借助Qt Plugin技術(shù),把各個(gè)獨(dú)立的功能模塊實(shí)現(xiàn)為一個(gè)個(gè)插件,統(tǒng)一在主體框架中,并能根據(jù)不同地方的用戶的不同需求,在主框架中加載不同的功能模塊,以實(shí)現(xiàn)整個(gè)系統(tǒng)的功能集中,體現(xiàn)出系統(tǒng)的整體性。

            2.      plugin 接口

            通過技術(shù)驗(yàn)證得出,目前我們采用動(dòng)態(tài)插件,各個(gè)功能的插件實(shí)現(xiàn)定義的統(tǒng)一接口,具體功能放在插件界面中實(shí)現(xiàn),此部分就像開發(fā)獨(dú)立的應(yīng)用程序,只是需要注意的是:

            功能部分的主界面需要繼承至插件界面基類:PluginWidget,插件接口中用具體的實(shí)現(xiàn)類指針給插件界面基類指針賦值,在加載插件的主框架中通過插件接口中定義的基類指針統(tǒng)一調(diào)用,利用C++動(dòng)態(tài)技術(shù)動(dòng)態(tài)識(shí)別具體指向的實(shí)現(xiàn)類。

            插件界面類必須實(shí)現(xiàn)基類的虛函數(shù):CreateActions()用于創(chuàng)建Action

            創(chuàng)建Action需要使用基類的方法newAction創(chuàng)建,在此函數(shù)中加入了保存創(chuàng)建的Action功能。

            插件接口定義如下:

            class QPluginInterface

            {

            public:

                // 析構(gòu)函數(shù)

                virtual ~QPluginInterface() {}

               

                // 插件名稱

                virtual    QString    PluginName() = 0;

               

                // 插件顯示在主框架中的圖標(biāo)文件路徑

                virtual    QString PluginIconurl() = 0;

               

                // 插件提供的對(duì)外操作接口集

                virtual QList<QAction*>* Actions() = 0;

             

                // 創(chuàng)建插件提供的操作方法

                virtual    void CreateActions()=0;

             

                // 插件的主界面

                virtual QWidget* Widget() = 0;

            protected:

                // 插件的主界面基類

                PluginWidget *pluginWidget;

            };

            插件界面基類定義如下:

            class PluginWidget :public QMainWindow

            {

                Q_OBJECT

            public:

                PluginWidget(QWidget*parent=0);

                ~PluginWidget();

                QList<QAction*>* Actions();

                virtual void      CreateActions(){}

                QActionnewAction(const QIcon &icon,const QString &text,QObject*parent);

                QAction *         newAction(const QString &text,QObject*parent);

                void       AppendAction(QAction*act);

            protected:

                // action鏈表

                QList<QAction*> *m_actlist;

            };

            下圖是一個(gè)實(shí)現(xiàn)案例中各類之間的關(guān)系圖:

            基于QT Plugin框架結(jié)構(gòu)  - yleesun - 與青春有關(guān)的日子...

            3.      插件調(diào)用

            插件在主框架中動(dòng)態(tài)加載,目前考慮主框架基本結(jié)構(gòu)是繼承至QMainWindow,工具欄上顯示當(dāng)前加載的插件的功能鍵,并留有返回鍵可以回退到上一級(jí)。主工作區(qū)是一個(gè)QStackWidget,保存插件的界面,并把插件序號(hào)和插件對(duì)應(yīng)的界面建立映射,保存在QMap<int,QWidget>中。通過序號(hào)到QStackWidget中切換界面。

            下圖是把DBManager做成插件加載到主框架的運(yùn)行界面:

            基于QT Plugin框架結(jié)構(gòu)  - yleesun - 與青春有關(guān)的日子...

            下圖是把一個(gè)簡(jiǎn)單的繪圖程序做成了插件,加載到主框架的運(yùn)行界面:

            基于QT Plugin框架結(jié)構(gòu)  - yleesun - 與青春有關(guān)的日子...

            四:總結(jié)

                   目前只是通過實(shí)現(xiàn)兩個(gè)動(dòng)態(tài)插件在主框架中運(yùn)行,基本算是功能性的驗(yàn)證,離具體實(shí)施還有很多工作需要進(jìn)一步的研究,比如主框架的風(fēng)格,插件的管理等等。由于本人的能力有限,可能有很多認(rèn)識(shí)不夠的地方,請(qǐng)指正。

            posted @ 2013-02-22 15:10 米米 閱讀(746) | 評(píng)論 (0)編輯 收藏

            概念

            名稱 含義
            View 視圖 視覺化一個(gè)場(chǎng)景
            Scene 場(chǎng)景 用于管理圖形項(xiàng)
            Item 圖形項(xiàng) 具體的圖形對(duì)象

             

            QT的圖形視圖架構(gòu)采用Model-View模型,Scence里面包含多個(gè)Item,可以用多個(gè)View以不同的方式觀察一個(gè)Scence

            功能
            Scene(QGraphicsScene)

            • 添加,刪除,查詢圖項(xiàng)

            • 事件分發(fā)

            • 管理圖項(xiàng)的選擇狀態(tài)和焦點(diǎn)

            View (QGraphicsView)

            • 為Scene提供一個(gè)視圖接口
            • 接收鼠標(biāo)鍵盤事件,轉(zhuǎn)換后發(fā)給Scene
            • 負(fù)責(zé)View和Scence之間的坐標(biāo)變換 

            可以為View設(shè)置不同的ViewPort控件,比如QGLWidget來支持OpenGL,Read More!

            Item (QGraphicsItem)

             

            圖形項(xiàng)的基類是QGraphicItem

            基礎(chǔ)的Feature包括:

            • 處理鼠標(biāo)鍵盤事件
            • 拖放
            • 分組
            • 碰撞檢測(cè)

            每個(gè)圖形項(xiàng)都有自己的本例坐標(biāo)系統(tǒng),并提供它和場(chǎng)景坐標(biāo)的轉(zhuǎn)換函數(shù)。所以可以單獨(dú)旋轉(zhuǎn)或縮放某個(gè)一圖形項(xiàng)


            除了pos等很少的幾個(gè)函數(shù),圖形項(xiàng)的多數(shù)函數(shù)所處理的坐標(biāo)都是它的本地坐標(biāo)(例如bounding rect)

            坐標(biāo)系統(tǒng)

            如上所述視圖體系采用三種坐標(biāo)系統(tǒng):

            • 視口坐標(biāo): 對(duì)應(yīng)物理坐標(biāo)/設(shè)備坐標(biāo)
            • 場(chǎng)景坐標(biāo): 對(duì)應(yīng)邏輯坐標(biāo)
            • 項(xiàng)坐標(biāo): 本地坐標(biāo)

            window-viewport概念

            window指定了邏輯坐標(biāo)的矩形范圍,viewport指定了設(shè)備坐標(biāo)的矩形范圍,和WorldTransform(世界轉(zhuǎn)換矩陣)一起,決定了邏輯坐標(biāo)和設(shè)備坐標(biāo)之間的轉(zhuǎn)換

             

            可以使用QGraphicsItemAnimation來動(dòng)畫一個(gè)Item,使用QTimeLine來控制時(shí)間進(jìn)度

             

            其它特性

            Animation動(dòng)畫

            一個(gè)Item只能有效的和一個(gè)Animation對(duì)象關(guān)聯(lián)(by QGraphicsItemAnimation::setItem),因?yàn)锳nimation對(duì)象設(shè)置圖項(xiàng)Item的轉(zhuǎn)換矩陣時(shí),會(huì)替換對(duì)象現(xiàn)有的矩陣。 所以你不能通過綁定多個(gè)Animation對(duì)象來做多重動(dòng)畫,但是你可以在一個(gè)Animation對(duì)象中設(shè)置多種變換效果(或者用分組的方法,分級(jí)控 制?)


            QGraphicsItemAnimation直接繼承自QObject,和普通的QAbstractAnimation沒有關(guān)系,所以沒法只用用QAnimationGroup來組裝,然后串行/并行使用多個(gè)動(dòng)畫。

             

            圖形控件和布局管理

            QGraphicsWidget的目的是在圖形對(duì)象的功能基礎(chǔ)上提供類似QWidget的功能。(從QGraphicsObject和 QGraphicsLayoutItem繼承來),從而可以使用完整的Widget控件屬性,設(shè)置字體,Style,提供size hints,以及信號(hào)槽機(jī)制等。

             

            QGraphicsLayout是專門用來布局QGraphicsWidget的布局控件。你可以通過多重繼承QGraphicsLayoutItem來定制QGraphicsItem使其能被QGraphicsLayout所管理

            嵌入普通控件

            你可以通過QGraphicsScene::addWidget來將一個(gè)普通QWidget嵌入到視圖體系中來使用,本質(zhì)是通過創(chuàng)建一個(gè)代理控件 (QGraphicsProxyWidget)來在QWidget和QGraphicsItem之間傳遞事件。需要注意的是,這只是一個(gè)特殊的實(shí)現(xiàn)方式, 對(duì)性能有要求的程序不宜使用這個(gè)機(jī)制。(沒有太看出哪里對(duì)性能有很大影響)

             

            QGraphicsProxyWidget能夠處理復(fù)雜的控件嵌套,甚至能自動(dòng)對(duì)被嵌套控件的子Popup Window控件創(chuàng)建代理控件。
             

            QGraphicsView本身也是一個(gè)普通QWidget控件,所以可以被添加到Scene中,創(chuàng)建復(fù)雜的嵌套視圖體系

            posted @ 2013-02-06 10:38 米米 閱讀(2020) | 評(píng)論 (0)編輯 收藏

             QRect rectWorkArea = qApp->desktop()->availableGeometry();
             QPoint ptLeftTop = geometry().topRight() + QPoint(2, 0);
             QSize sizeSettingsWindow = m_pSettingsWindow->size();
             if(ptLeftTop.x() + sizeSettingsWindow.width() > rectWorkArea.right())
              ptLeftTop.setX(rectWorkArea.right() - sizeSettingsWindow.width());
             m_pSettingsWindow->move(ptLeftTop);
            posted @ 2013-02-06 10:00 米米 閱讀(327) | 評(píng)論 (0)編輯 收藏

            看《C++必知必會(huì)》比看《C++編程思想》編程思想有趣多了,《C++編程思想》是為C程序員寫的,而我基本上一來就直接學(xué)的C++,因而《C++編程思想》并不適合我。而《C++必知必會(huì)》是直接從實(shí)際出發(fā),直接點(diǎn)出來在編程中遇到的各種問題,因而很是實(shí)用,深得我心。  
            1.?dāng)?shù)據(jù)結(jié)構(gòu) 
            摘要:為類型選擇一個(gè)描述性名字。如果難以為這個(gè)類型命名,那就說明你還不知道你想要實(shí)現(xiàn)什么。 
            評(píng):很是精辟,每當(dāng)我想到了這個(gè)類的名字,我就知道了如何去做和做些什么。摘要:列舉類型所能執(zhí)行的操作。......要避免在實(shí)現(xiàn)時(shí)簡(jiǎn)單地為數(shù)據(jù)成員提供一串get/set操作——那不叫做數(shù)據(jù)抽象而是懶惰且缺乏想象力的表現(xiàn)。 
            評(píng):不太明白,在我看來,C++中的類型僅僅是把數(shù)據(jù)按照一定的規(guī)律(類型)進(jìn)行封裝,其目的就是為了進(jìn)行數(shù)據(jù)之間的交換。我的確不僅僅是用了一串get/set操作,但不是的操作也僅僅比get/set有一點(diǎn)延伸,比如按照某個(gè)條件來get/set一個(gè)或一組數(shù)據(jù)。 
             2.多態(tài) 
            摘要:基類可以不知道除自身以外的任何事物。 
            評(píng):很是恰當(dāng),基類可以看成派生類的接口,派生類可以看成是基類的實(shí)現(xiàn)。 
             3.設(shè)計(jì)模式 
            摘要:一旦設(shè)計(jì)完成后,甚至你的經(jīng)理都能夠理解完整的設(shè)計(jì)方案,只要他具備一些必需的模式方面的知識(shí)。 
            評(píng):以前我一直沒有看過關(guān)于設(shè)計(jì)模式方面的書,也不理解什么是設(shè)計(jì)模式和為什么需要設(shè)計(jì)模式。現(xiàn)在,通俗的話說設(shè)計(jì)模式是程序員之間的“黑話”,它與使用的平臺(tái)、語言毫無關(guān)系,它指的是你在制作程序時(shí)的一種構(gòu)想或方法,而這些構(gòu)造方法都是大家熟知的、經(jīng)過驗(yàn)證的、有效的、高效率的。  
            4.STL  
            摘要:STL包含三大組件:容器、算法和迭代器。......STL的優(yōu)秀思想體現(xiàn)在:容器與在容器上執(zhí)行的算法之間無需彼此了解,這種戲法是通過迭代器實(shí)現(xiàn)的。 
            評(píng):上面已經(jīng)很好的解釋了什么是STL了,而且還道出了C++中的精髓,無需彼此了解,不是侵入式的設(shè)計(jì),還象那個(gè)基類、派生類。 
             5.引用 
            評(píng):我只會(huì)把引用用在函數(shù)形參上,一般還給它加上一個(gè)const,其他的地方么,我一般使用指針。 
             6.?dāng)?shù)組形參 
            摘要:數(shù)組在傳入時(shí),實(shí)質(zhì)上只傳入指向其首元素的指針。 
            評(píng):要小心!書中用一個(gè)準(zhǔn)確的詞“退化“來描述這種狀況。不過自從我使用了vector后也就找不出什么理由使用數(shù)組了。我很高興是這樣的結(jié)果。什么,你說你一定要用多維數(shù)組,那么我說,你去死吧,我一般用一維代替多維,或者使用vector進(jìn)行鑲套。  
            7.產(chǎn)量指針和指向產(chǎn)量的指針 
            評(píng):我背下了一個(gè)簡(jiǎn)單的方法來區(qū)別這兩個(gè)。我把*和它前面的作為一組,*后面的作為一組,如const T *ptr,讀后面的部分,ptr是指針,指向const T,又如T *const ptr,讀為一個(gè)const指針,指向T類型。不過話說回來,我一直沒有用過,也還沒有想到使用的理由。  
            8.指向指針的指針 
            評(píng):對(duì)這一點(diǎn)我一直提不起興趣,討厭這么復(fù)雜的冬冬。不過在實(shí)際中漸漸明白。如 vector my_circle; vector::iterator p=my_circle.begin(); for(;p!=my_circle.end();p++) {(*p)->draw();}  
            9.新式轉(zhuǎn)型操作符 
            摘要:更丑陋,更難用,并且威力較小。 
            評(píng):看到了這一章,我心里面咯噔了一下。我的程序里面還有那么野蠻的、不講理的轉(zhuǎn)換。我得盡快用這種更丑陋的方式去改過來,以減少錯(cuò)誤的可能性。要注意static_const和dynamic_cast;  
            10.常量成員函數(shù)含義 
            摘要: 
            class X{  
            Public: void modify_buffer(int index,int val) const //不德!!!!!! { Buffer[index] = val;} Private: int *buffer; };  
            評(píng):的確是不道德的,const的函數(shù)偷偷的改了一個(gè)數(shù)據(jù),沒有發(fā)現(xiàn)因?yàn)闆]有修改class X中的對(duì)象。我得小心了,不干這種事情。 
             11.編譯器會(huì)在類中放東西 
            摘要:如果一個(gè)類聲明了一個(gè)或多個(gè)虛函數(shù),那么編譯器將會(huì)為該類的每一個(gè)對(duì)象插入一個(gè)指向虛函數(shù)表的指針。 
            摘要:如果使用了虛擬繼承,對(duì)象將會(huì)通過嵌入的指針、嵌入的偏移或其他的信息來保持對(duì)其虛基類子對(duì)象位置的跟蹤。 
            摘要:一個(gè)POD(“plain old data”)非常重要。比如int、double、C struct、union都是POD。摘要:如果希望復(fù)制一個(gè)類對(duì)象,那么永遠(yuǎn)都不要使用memcpy這樣的標(biāo)準(zhǔn)內(nèi)存塊復(fù)制函數(shù)。......相反,應(yīng)該使用對(duì)象的初始化或者賦值操作。 
            評(píng):看到最后這條我才明白為何有這章。看來對(duì)于高層的東西要使用高層的操作。  
            12.賦值和初始化并不相同 
            摘要:直截了當(dāng)?shù)恼f,賦值發(fā)生于當(dāng)你賦值時(shí),除此之外遇到的所有其他的復(fù)制情況均為初始化,包括聲明,函數(shù)返回,參數(shù)傳遞以及捕俘描述異常中的初始化。 
            評(píng):突然想起鼻祖書中的話,賦值是對(duì)一個(gè)結(jié)構(gòu)良好的存儲(chǔ)區(qū)去做,而初始化是對(duì)一個(gè)未定義的存儲(chǔ)區(qū)去做。如果要賦值,那么就確立一下賦值的對(duì)象是否還是磁盤上的荒蕪地帶。  
            13.復(fù)制操作  
            摘要:復(fù)制構(gòu)造和復(fù)制賦值是兩種不同的操作。  
            14.函數(shù)指針 
            摘要:將一個(gè)函數(shù)的地址初始化或賦值給一個(gè)指向函數(shù)的指針時(shí),無需顯示的取得函數(shù)地址。 
            例子:void (*fp)(int);  
            extern void h(int);  
            fp = h; //OK  
            fp = &h; //OK  
            摘要:為了調(diào)用函數(shù)指針?biāo)赶虻暮瘮?shù),而對(duì)指針進(jìn)行解引用操作也是不必要的。 
            例子:(*fp)(12); //顯示調(diào)用  
            fp(12); //隱式調(diào)用 
            摘要:函數(shù)指針的一個(gè)傳統(tǒng)用途是實(shí)現(xiàn)回調(diào)(callback)。 
            評(píng):一個(gè)很好的例子就是windows中對(duì)左右手的變化,如果改變了就只需要交換一下函數(shù)指針就OK了。  
            15.指向類成員的指針并非指針 
            摘要:“指向類成員的指針”即不包含地址,行為也不像指針。通常看作一個(gè)偏移量。 
            摘要:指向數(shù)據(jù)成員的指針對(duì)于描述“逆變性”的概念很方便。 
            摘要:存在指向基類成員的指針到指向公有派生類成員的指針隱式轉(zhuǎn)換,反之不行。 
            評(píng):明白了它的作用卻不知道哪里有用,完全可以換個(gè)方式使用,即使是為了上一章的回調(diào)。如果要得到類中的成員,完全可以用類的對(duì)象或指向類對(duì)象的指針獲得,這個(gè)可能是為了C程序員吧。 
             tip:不能想著指向static成員,它們并不是存在于所有類對(duì)象的一個(gè)偏移量。使用的方式和普通的數(shù)據(jù)一樣。  
            16.指向成員函數(shù)的指針并非指針  
            摘要:NULL  
            17.處理函數(shù)和數(shù)組聲明 
            摘要: 
            int *f1(); //一個(gè)返回值為int *的函數(shù) 
             int (*fp1)(); //一個(gè)指針,指向一個(gè)返回值為int的函數(shù)  
            int *a1[N]; //一個(gè)具有N個(gè)int *元素的數(shù)組  
            int (*ap1)[N]; //一個(gè)指針,指向一個(gè)具有N個(gè)int元素的數(shù)組 
            評(píng):夠復(fù)雜吧,不過看了下面的就要。。。。。。  
            摘要: int(*af2[N])(); //一個(gè)具有N個(gè)元素的數(shù)組  
            //其元素類型指向返回值為int的函數(shù)指針 
            評(píng):夠嚇人的,雖然有解決法子可我沒在意。因?yàn)槔显缇蜎Q定不用數(shù)組了。 
             18.函數(shù)對(duì)象 
            摘要:函數(shù)對(duì)象也是一個(gè)普通的類對(duì)象,通過重載函數(shù)調(diào)用操作符()來創(chuàng)建類似于函數(shù)指針的東西。 
            評(píng):這可是個(gè)好東西,在泛型算法中作為謂詞。 
             19.Command模式與好萊塢法則 
            摘要:好萊塢法則即“不要call我們,我們會(huì)call你”。 
            摘要:將一個(gè)函數(shù)對(duì)象于好萊塢法則相結(jié)合,即為Command模式的一個(gè)實(shí)例。 
            摘要:好處是,函數(shù)對(duì)象可以封裝數(shù)據(jù),另一個(gè)好處是函數(shù)對(duì)象可以通過虛擬成員表現(xiàn)出動(dòng)態(tài)行為,第三個(gè)好處是處理類層次結(jié)構(gòu)而不是較為原始的,缺乏靈活性的結(jié)構(gòu)(例如函數(shù)指針)。  
            20.STL函數(shù)參數(shù) 
             摘要:NULL 
             21.重載與重寫并不相同 
            摘要:重載發(fā)生于同一個(gè)作用域內(nèi)有兩個(gè)或更多個(gè)函數(shù)具有相同的名字但簽名不同時(shí)。 
            摘要:重寫發(fā)生于派生類函數(shù)和基類有相同的的名字和簽名時(shí)。  
            22.Template Method 模式 
            摘要: Template Method(模板方式)模式和C++模板一點(diǎn)關(guān)系都沒有。實(shí)際上,它是基類設(shè)計(jì)者為派生類設(shè)計(jì)者提供清晰指示的一種方式,這個(gè)指示就是“應(yīng)該如何實(shí)現(xiàn)基類所規(guī)定的契約”。 
            摘要:一個(gè)基類的成員函數(shù)是否應(yīng)該為非虛擬的、虛擬的或純虛擬的,這樣的決策主要是基于該函數(shù)的行為如何被派生類定制。 
            摘要:如果基類成員是非虛擬的,那么基類設(shè)計(jì)者就是以該基類為所確立的層次結(jié)構(gòu)指明了一個(gè)不變式。派生類不應(yīng)該用同名的派生類成員去隱藏基類非虛函數(shù)。 
            摘要:虛函數(shù)和純虛函數(shù)指定的操作,其實(shí)現(xiàn)可以由派生類通過重寫機(jī)制定制。一個(gè)非純虛函數(shù)提供了一個(gè)默認(rèn)實(shí)現(xiàn),并不強(qiáng)迫派生類一定要重寫它,而一個(gè)純虛函數(shù)則必須在具體派生類中進(jìn)行重寫。 
            評(píng):這一章對(duì)于我們?nèi)绾味x基類有了一個(gè)很好的說明。函數(shù)是具體的實(shí)現(xiàn),而我們確定如何具體的實(shí)現(xiàn)函數(shù)。 
             Tip:另外有一種派生類作為基類接口的形式,那里的法則就不太一樣了。基類是實(shí)現(xiàn),派生類是為了給其他用戶的接口。  
            23.名字空間  
            摘要:本質(zhì)上,名字空間是對(duì)全局作用域的細(xì)分。 
            摘要:許多C++程序員建議將using指令放在全局作用域中,這是個(gè)餿注意。 
            評(píng):一定要很好的區(qū)分什么是using指令和using聲明。  
            Using namespace namespace_name //是指令  
            Using anamespace_name::名字空間聲明的的東西 //是聲明 
            如果在全局作用域中使用using指令那等于去掉了名字空間的作用域。這里一般指的是程序員自己定義的名字空間,不是默認(rèn)的std。  
            24.成員函數(shù)查找 
            摘要:調(diào)用一個(gè)成員函數(shù)時(shí),涉及三個(gè)步驟:第一步,編譯器查找函數(shù)的名字;第二步,從可用候選者中選取最佳匹配函數(shù);第三步,檢查是否具有訪問該匹配函數(shù)是權(quán)限; 
            評(píng):這里面隱含的說了一個(gè)冬冬,如果編譯器找到了函數(shù)的名字,它是不會(huì)再去找的了。如果無權(quán)限范圍該函數(shù),那么就會(huì)在第三步出現(xiàn)編譯錯(cuò)誤。  
            25.實(shí)參相依的查找 
            摘要:ADL(實(shí)參相依的查找)指的是,當(dāng)查找一個(gè)函數(shù)調(diào)用表達(dá)式中的函數(shù)名字時(shí),編譯器也會(huì)到“包含函數(shù)調(diào)用實(shí)參的類型”的名字空間查找。 
            評(píng):我卻好像記得不止是名字空間,也包括class,因?yàn)閏lass其實(shí)也是一種特殊的名字空間。回頭還得再看一遍鼻祖的書,那里面其實(shí)都有,只是沒有重點(diǎn)標(biāo)出來而已。  
            26.操作符函數(shù)查找 
            摘要:當(dāng)使用函數(shù)調(diào)用語法時(shí),應(yīng)用的是普通的查找規(guī)則(ADL)。而對(duì)重載操作符的中綴調(diào)用的處理機(jī)制不同。 
            例子: 
            class X{ X operator%(const X&)const;};  
            X x,y;  
            x % y; //中綴調(diào)用 
             x.operator%(y); //成員函數(shù)調(diào)用 
            摘要:對(duì)于中綴操作符調(diào)用來說,編譯器不僅會(huì)考慮成員操作符,也會(huì)考慮非成員操作符。 
            評(píng):說的有點(diǎn)讓人迷糊。我想主要注意使用.operator時(shí),記得有個(gè)默認(rèn)的*this實(shí)參。  
            27.能力查詢 
            摘要:能力查詢只是偶爾需要,但它們往往被過渡使用。它們通常是糟糕設(shè)計(jì)的“指示器”。最好避免對(duì)一個(gè)對(duì)象的能力進(jìn)行運(yùn)行期查詢。 
            評(píng):能力查詢指的是對(duì)一個(gè)類對(duì)象進(jìn)行dynamic_cast,來知道它是否是另外的類型,通常,是橫向轉(zhuǎn)換而不是普通的向上或者向下。  
            28.指針比較的含義 
            摘要:指針比較不是關(guān)于地址的問題,而是關(guān)于對(duì)象同一性的問題。 
            摘要:一個(gè)非常重要的經(jīng)驗(yàn),處理指向?qū)ο蟮囊没蛑羔槙r(shí),必須小心避免丟失類型信息(如把指針賦值給void*指針)。 
            評(píng):一個(gè)基類的指針是與其派生類的指針==的,并不是因?yàn)榈刂废嗤穷愋拖嗤驗(yàn)榕缮惥褪腔悾拖癜嚅L(zhǎng)就是學(xué)生一樣。這里比較的是基類的類型。  
            29.虛構(gòu)造函數(shù)與Prototype模式 
            評(píng):構(gòu)造函數(shù)是不能虛的,而這里指的是具有這樣功能的函數(shù)。如在一個(gè)類中,我們使用一個(gè)成員函數(shù)clone來調(diào)用復(fù)制構(gòu)造函數(shù)new X(*this),我的經(jīng)驗(yàn)無法告訴我為何需要,不過有一點(diǎn)是很明確的,這個(gè)例子證明了軟件設(shè)計(jì)的“不知情”模式。  
            30.Factory Method模式 
            評(píng):一個(gè)沉重的打擊,我在28、29看見了什么是比較高級(jí)的構(gòu)架,也讓我想起了別來call我,需要時(shí)我來call你的好萊塢模式。每個(gè)類都明白自己做什么,而你只是在問它們一個(gè)很大眾的問題,而不是很私人的問題。重點(diǎn)推薦,我得好好看看,認(rèn)真感受。如果能很明確的使用,我的認(rèn)識(shí)將能夠上一個(gè)檔次。  
            31.協(xié)變返回類型 
            摘要:協(xié)變的優(yōu)勢(shì)在于,總是可以在適當(dāng)程度的抽象層工作。如果我們是處理Shape,獲得一個(gè)抽象的ShapeEditor;如果在處理某種具體的形狀類型,比如Circle,我們就可以直接獲得CircleEditor。協(xié)變機(jī)制使得我們可以不使用類型轉(zhuǎn)換操作來“重新”提供類型信息,而這種信息是一開始就不應(yīng)該丟掉的。  
            32.禁止復(fù)制 
            摘要:訪問修飾符(public、protect、private)可以用于表達(dá)和執(zhí)行高級(jí)約束技術(shù),指明一個(gè)類可以被怎樣使用。這些技術(shù)中最常見的一種是不接受對(duì)象的復(fù)制操作,這是通過將其復(fù)制操作聲明為private同時(shí)不為之提供定義而做到的。 
            評(píng):有時(shí)候我們應(yīng)該把所有不想給其他人使用的函數(shù)全部放進(jìn)private。 
             (因?yàn)楹竺娴谋容^深,暫時(shí)作罷。勉強(qiáng)看也只能懂個(gè)浮淺的東西。未完待續(xù))  
            posted @ 2013-01-21 17:22 米米 閱讀(304) | 評(píng)論 (0)編輯 收藏

            一個(gè)正則表達(dá)式就是由普通字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式。該模式描述在查找文字主體時(shí)待匹配的一個(gè)或多個(gè)字符串。正則表達(dá)式作為一個(gè)模板,將某個(gè)字符模式與所搜索的字符串進(jìn)行匹配。

            這里有一些可能會(huì)遇到的正則表達(dá)式示例:

            Visual Basic Scripting Edition VBScript 匹配
            /^\[ \t]*$/ "^\[ \t]*$" 匹配一個(gè)空白行。
            /\d{2}-\d{5}/ "\d{2}-\d{5}" 驗(yàn)證一個(gè)ID 號(hào)碼是否由一個(gè)2位數(shù)字,一個(gè)連字符以及一個(gè)5位數(shù)字組成。
            /<(.*)>.*<\/\1>/ "<(.*)>.*<\/\1>" 匹配一個(gè) HTML 標(biāo)記。

            下表是元字符及其在正則表達(dá)式上下文中的行為的一個(gè)完整列表:

            字符 描述
            \ 將下一個(gè)字符標(biāo)記為一個(gè)特殊字符、或一個(gè)原義字符、或一個(gè) 后向引用、或一個(gè)八進(jìn)制轉(zhuǎn)義符。例如,'n' 匹配字符 "n"。'\n' 匹配一個(gè)換行符。序列 '\\' 匹配 "\" 而 "\(" 則匹配 "("。
            ^ 匹配輸入字符串的開始位置。如果設(shè)置了 RegExp 對(duì)象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 之后的位置。
            $ 匹配輸入字符串的結(jié)束位置。如果設(shè)置了RegExp 對(duì)象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 之前的位置。
            * 匹配前面的子表達(dá)式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。 * 等價(jià)于{0,}。
            + 匹配前面的子表達(dá)式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價(jià)于 {1,}。
            ? 匹配前面的子表達(dá)式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價(jià)于 {0,1}。
            {n} n 是一個(gè)非負(fù)整數(shù)。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個(gè) o。
            {n,} n 是一個(gè)非負(fù)整數(shù)。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價(jià)于 'o+'。'o{0,}' 則等價(jià)于 'o*'。
            {n,m} mn 均為非負(fù)整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m 次。劉, "o{1,3}" 將匹配 "fooooood" 中的前三個(gè) o。'o{0,1}' 等價(jià)于 'o?'。請(qǐng)注意在逗號(hào)和兩個(gè)數(shù)之間不能有空格。
            ? 當(dāng)該字符緊跟在任何一個(gè)其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面時(shí),匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認(rèn)的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對(duì)于字符串 "oooo",'o+?' 將匹配單個(gè) "o",而 'o+' 將匹配所有 'o'。
            . 匹配除 "\n" 之外的任何單個(gè)字符。要匹配包括 '\n' 在內(nèi)的任何字符,請(qǐng)使用象 '[.\n]' 的模式。
            (pattern) 匹配pattern 并獲取這一匹配。所獲取的匹配可以從產(chǎn)生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在Visual Basic Scripting Edition 中則使用 $0$9 屬性。要匹配圓括號(hào)字符,請(qǐng)使用 '\(' 或 '\)'。
            (?:pattern) 匹配 pattern 但不獲取匹配結(jié)果,也就是說這是一個(gè)非獲取匹配,不進(jìn)行存儲(chǔ)供以后使用。這在使用 "或" 字符 (|) 來組合一個(gè)模式的各個(gè)部分是很有用。例如, 'industr(?:y|ies) 就是一個(gè)比 'industry|industries' 更簡(jiǎn)略的表達(dá)式。
            (?=pattern) 正向預(yù)查,在任何匹配 pattern 的字符串開始處匹配查找字符串。這是一個(gè)非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如, 'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。預(yù)查不消耗字符,也就是說,在一個(gè)匹配發(fā)生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預(yù)查的字符之后開始。
            (?!pattern) 負(fù)向預(yù)查,在任何不匹配Negative lookahead matches the search string at any point where a string not matching pattern 的字符串開始處匹配查找字符串。這是一個(gè)非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。預(yù)查不消耗字符,也就是說,在一個(gè)匹配發(fā)生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預(yù)查的字符之后開始
            x|y 匹配 xy。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。
            [xyz] 字符集合。匹配所包含的任意一個(gè)字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
            [^xyz] 負(fù)值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
            [a-z] 字符范圍。匹配指定范圍內(nèi)的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范圍內(nèi)的任意小寫字母字符。
            [^a-z] 負(fù)值字符范圍。匹配任何不在指定范圍內(nèi)的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范圍內(nèi)的任意字符。
            \b 匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
            \B 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
            \cx 匹配由x指明的控制字符。例如, \cM 匹配一個(gè) Control-M 或回車符。 x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個(gè)原義的 'c' 字符。
            \d 匹配一個(gè)數(shù)字字符。等價(jià)于 [0-9]。
            \D 匹配一個(gè)非數(shù)字字符。等價(jià)于 [^0-9]。
            \f 匹配一個(gè)換頁(yè)符。等價(jià)于 \x0c 和 \cL。
            \n 匹配一個(gè)換行符。等價(jià)于 \x0a 和 \cJ。
            \r 匹配一個(gè)回車符。等價(jià)于 \x0d 和 \cM。
            \s 匹配任何空白字符,包括空格、制表符、換頁(yè)符等等。等價(jià)于 [ \f\n\r\t\v]。
            \S 匹配任何非空白字符。等價(jià)于 [^ \f\n\r\t\v]。
            \t 匹配一個(gè)制表符。等價(jià)于 \x09 和 \cI。
            \v 匹配一個(gè)垂直制表符。等價(jià)于 \x0b 和 \cK。
            \w 匹配包括下劃線的任何單詞字符。等價(jià)于'[A-Za-z0-9_]'。
            \W 匹配任何非單詞字符。等價(jià)于 '[^A-Za-z0-9_]'。
            \xn 匹配 n,其中 n 為十六進(jìn)制轉(zhuǎn)義值。十六進(jìn)制轉(zhuǎn)義值必須為確定的兩個(gè)數(shù)字長(zhǎng)。例如, '\x41' 匹配 "A"。'\x041' 則等價(jià)于 '\x04' & "1"。正則表達(dá)式中可以使用 ASCII 編碼。.
            \num 匹配 num,其中 num 是一個(gè)正整數(shù)。對(duì)所獲取的匹配的引用。例如,'(.)\1' 匹配兩個(gè)連續(xù)的相同字符。
            \n 標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)后向引用。如果 \n 之前至少 n 個(gè)獲取的子表達(dá)式,則 n 為后向引用。否則,如果 n 為八進(jìn)制數(shù)字 (0-7),則 n 為一個(gè)八進(jìn)制轉(zhuǎn)義值。
            \nm 標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)后向引用。如果 \nm 之前至少有is preceded by at least nm 個(gè)獲取得子表達(dá)式,則 nm 為后向引用。如果 \nm 之前至少有 n 個(gè)獲取,則 n 為一個(gè)后跟文字 m 的后向引用。如果前面的條件都不滿足,若  nm 均為八進(jìn)制數(shù)字 (0-7),則 \nm 將匹配八進(jìn)制轉(zhuǎn)義值 nm
            \nml 如果 n 為八進(jìn)制數(shù)字 (0-3),且 ml 均為八進(jìn)制數(shù)字 (0-7),則匹配八進(jìn)制轉(zhuǎn)義值 nml。
            \un 匹配 n,其中 n 是一個(gè)用四個(gè)十六進(jìn)制數(shù)字表示的 Unicode 字符。例如, \u00A9 匹配版權(quán)符號(hào) (?)。
            posted @ 2012-10-23 11:03 米米 閱讀(297) | 評(píng)論 (0)編輯 收藏

            this->tableView->horizontalHeader()->setStyleSheet("QHeaderView::section {background-color:darkcyan;"
                                                                   "color: black;padding-left: 4px;border: 1px solid #6c6c6c;}");


            this->tableView->verticalHeader()->setStyleSheet("QHeaderView::section {background-color:darkcyan;"
                                                                 "color: black;padding-left: 4px;border: 1px solid #6c6c6c;}");

             

            以下好看的樣式來自于http://blog.csdn.net/zenwanxin/article/details/6524559

            tableView->horizontalHeader()->setStyleSheet

            ("QHeaderView::section {background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,"

            "stop:0 #616161, stop: 0.5 yellow,stop: 0.6 green, stop:1 cyan);"
            "color: white;padding-left: 4px;border: 1px solid #6c6c6c;}"
            "QHeaderView::section:checked{background-color: red;}"
            "QHeaderView::down-arrow {image: url(down_arrow.png);}"
            "QHeaderView::up-arrow {image: url(up_arrow.png);}");

            posted @ 2012-09-05 21:36 米米 閱讀(5594) | 評(píng)論 (0)編輯 收藏

                 摘要: 一、基礎(chǔ) 1、說明:創(chuàng)建數(shù)據(jù)庫(kù) CREATE DATABASE database-name 2、說明:刪除數(shù)據(jù)庫(kù) drop database dbname 3、說明:備份sql server --- 創(chuàng)建 備份數(shù)據(jù)的 device USE master EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat...  閱讀全文
            posted @ 2012-08-30 09:43 米米 閱讀(300) | 評(píng)論 (0)編輯 收藏

            方案一:使用paintEvent
            C/C++ code
            void Widget::paintEvent(QPaintEvent *e)
            { QPainter painter(this);
             painter.drawPixmap(0,0,this->width(),this->height(),QPixmap(":/xxx.png"));
             }


            方案二:使用setStyleSheet
            C/C++ code
            widget->setStyleSheet("border-image: url(:/xxx.png)");
            posted @ 2012-08-28 10:56 米米 閱讀(1822) | 評(píng)論 (0)編輯 收藏

            僅列出標(biāo)題
            共8頁(yè): 1 2 3 4 5 6 7 8 
            久久精品成人影院| 久久AAAA片一区二区| 亚洲欧美国产精品专区久久| 久久综合综合久久97色| 色妞色综合久久夜夜| 久久国产视屏| 久久99精品国产麻豆不卡| 99久久夜色精品国产网站| 蜜臀久久99精品久久久久久| 国产精品99久久免费观看| 69国产成人综合久久精品| 潮喷大喷水系列无码久久精品| 国产精品99久久免费观看| 91精品国产91久久久久久蜜臀| 久久精品国产亚洲沈樵| 亚洲精品乱码久久久久久蜜桃图片| 亚洲香蕉网久久综合影视| 久久久www免费人成精品| 精品久久777| 久久青草国产手机看片福利盒子| 曰曰摸天天摸人人看久久久| 国产真实乱对白精彩久久| 中文无码久久精品| 欧美国产精品久久高清| 久久亚洲精品人成综合网| 久久99精品久久久久久野外| 久久国产精品99精品国产| 国产精品美女久久久久AV福利| 久久AV高清无码| 久久精品无码一区二区app| 国产精品久久久久久| 久久国产免费观看精品| 99国产精品久久| 无码日韩人妻精品久久蜜桃| 亚洲国产精品嫩草影院久久| 久久精品久久久久观看99水蜜桃| 久久国产精品77777| 日韩影院久久| 国产99精品久久| 97精品伊人久久大香线蕉app| 97久久国产综合精品女不卡|