基于tq2440智能家居控制系統(tǒng)設計源碼、大放送-包qt相關教程好_第1頁
基于tq2440智能家居控制系統(tǒng)設計源碼、大放送-包qt相關教程好_第2頁
基于tq2440智能家居控制系統(tǒng)設計源碼、大放送-包qt相關教程好_第3頁
基于tq2440智能家居控制系統(tǒng)設計源碼、大放送-包qt相關教程好_第4頁
基于tq2440智能家居控制系統(tǒng)設計源碼、大放送-包qt相關教程好_第5頁
已閱讀5頁,還剩56頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

Qt一——第一章 o, oWorld例子。它只包含你建立和運行Qt應用程序所需要的最**Qt一-intmain(intargc,char**argv{ o(" oworld!",0);o.resize(100,30);a.setMainWidget(& return}一行一行地這一行包含了QApplication類的定義。在每一個使用Qt的應用程序中都必須使用一個QApplication對象。QApplication管理了各種各樣的應用程序的廣泛資源,比如默認的字體和光這一行包含了QPushButton類的定義。參考文檔的文件的最上部分提到了使用哪個類就必須包uBtn感,就像其它每一個idgt的內容。一個uhButton可以顯示一段文本或者一個main(intargc,char**argv{main()函數(shù)是程序的。幾乎在使用Qt的所有情況下,main()只需要在把控制轉交給Qt庫之前執(zhí)行一些初始化,然后Qt庫通過事件來向程序告知用戶的行argc是命令行變量的數(shù)量,argv是命令行變量的數(shù)組。這是一個C/C++特征。它不是Qt專有的,無論如何Qt需要處理這些變量(請看下面)。-display)。請注意,所有被Qt識別令行參數(shù)都會從argv中被移除(并且argc也因此而減注意:在任何 的窗口系統(tǒng)部件被使用之前創(chuàng)建 對象是必須的 o( 這里,在QApplication之后,接著的是第一個窗口系統(tǒng)代碼:一個按鈕被創(chuàng)建這個按鈕被設置成顯示“oworld!”并且它自己構成了一個窗(因為在構造函數(shù)指定0為它的父窗口,在這個父窗口中按鈕被定位)。o.resize(100,30下,不用考慮按鈕的位置,并且接受默認值。 oreturn這里就是main()把控制轉交給Qt,并且當應用程序退出的時候exec()就會返在exec()中,Qt接受并處理用戶和系統(tǒng)的事件并且把它們傳遞給適當?shù)拇翱诓縸編編譯一個C++應用程序,你需要創(chuàng)建一個makefile。創(chuàng)建一個Qt的makefile的最容易的方法是使用Qt提供的連編工具qmake。如果你已經(jīng)把main.cpp保存到它自己的了,你所要做的就(系統(tǒng)相關的)makefile。你現(xiàn)在可以輸入make(或者nmake,如果你使用VisualStudio),然后運行你的第一個Qt應用程序!行以讀到著名的詞:owWorld!練試著改變窗口的大小。按下按鈕。如果你在X窗口下運行,使用-geometryQt一——第二章:調用退**Qt一-#include<qapplication.h>#include<qpushbutton.h>#include<qfonth>intmain(intargc,char**argv{QPushButtonquit("Quit",0);quitresize(75,30);quit.setFont(QFont("Times",18,QFont::Bold));QObject::connect(&quit,SIGNAL(clicked()),&a,SLOT(quit()));a.setMainWidget(&quit);return}一行一行地因為這個程序使用了QFont,所以它需要包含qfonth。Qt的字體提取和X中提供的可怕的字體QPushButtonquit("Quit",0quitresize(75,30 QObject::connect(&quit,SIGNAL(clicked()),&a,SLOT(quit())connect也許是Qt中最重要的特征了。注意connect()是QObject中的一個靜態(tài)函數(shù)。這個函數(shù)和socket庫中的connect()搞混了。這一行在兩個Qt對象(直接或間接繼承QObject對象的對象)中建立了一種單向的連接。每一QWidget,而QWidget繼承QObject。quitclicked()aquit()槽連接起來了,所以當這個按鈕被按下的行練是不是在QPushButton中還有其它的你可以連接到quit的信號?提示:QPushButtonQt一——第三章:家庭價**Qt一-#include<qfonth>#include<qvbox.h>intmain(intargc,char**argv{QVBoxbox;box.resize(200,120);quit.setFont(QFont("Times",18,QFont::Bold));QObject::connect(&quit,SIGNAL(clicked()),&a,SLOT(quit()));a.setMainWidget(&box);return}一行一行地添加了一個頭文件qvbox.h用來獲得要使用的布局類box.resize(200,120QPushButton通過一個文本(“text”)和一個父窗口部件(box)生成的。子窗口部件總是放在它行QWidget::sizeHint()和QWidget::setSizePolicy()來獲得關于這幾個函數(shù)的更詳細的信息。)練Qt一——第四章:使用窗口部**Qt一-#include<qapplication.h>#include<qpushbutton.h>#include<qfonth>classMyWidget:public{:QWidget(parent,name{ umSize(200,120QPushButton*quit=newQPushButton("Quit",this,"quit");quit->setGeometry(62,40,75,30);}intmain(intargc,char**argv{w.setGeometry(100,100,200,120);a.setMainWidget(&w);}一行一行地classMyWidget:public{這里創(chuàng)建了一個新類。因為這個類繼承了QWidget,所以新類是一個窗口部件,并且可以個構造函數(shù)是一個標準的Qt窗口部件構造函數(shù),當你創(chuàng)建窗口部件時,你應該:QWidget(parent,name構造函數(shù)的實現(xiàn)從這里開始。像大多數(shù)窗口部件一樣,它把parent和name傳遞給了QWidget的{ umSize(200,120因為這個窗口部件不知道如何處理重新定義大小,把它的最小大小和最大大小設置為相等的值,這樣就確定了它的大小。在下一章,演示窗QPushButton*quit=newQPushButton("Quit",this,"quit");quit->setGeometry(62,40,75,30);這里創(chuàng)建并設置了這個窗口部件的一個名稱為“quit”的子窗口部件(新窗口注意quit是這個構造函數(shù)中的局部變量。MyWidget不能它,但Qt可以,當MyWidget被刪除的時候,默認地它也會被刪除。這就是為什么MyWidget不需什么壞處,這個子窗口部件會自動告訴Qt它即將。)setGeometry()調用和上一章的move()和resize()是一樣的}因為MyWidget類不知道這個應用程序對象,它不得不連接到QtqApp需要和應用程序對象的這種情況下,Qt提供了一個別名,qAmain(intargc,char**argv{w.setGeometry(100,100,200,120);a.setMainWidget(&w);}這里舉例說明了的新子窗口部件,把它設置為主窗口部件,并且執(zhí)行行練試著添加的按鈕或者把除了QPushButton之外的東西放到窗口部件中。Qt一——第五章:組裝積**Qt一-#include<qslider.h>#include<qlcdnumberh>#include<qfonth>classMyWidget:public{:QVBox(parent,name{QPushButton*quit=newQPushButton("Quit",this,"quit");quit->setFont(QFont("Times",18,QFont::Bold));connect(quit,SIGNAL(clicked()),qApp,SLOT(quit()));QLCDNumber*lcd=newQLCDNumber(2,this,"lcd");QSlider*slider=newQSlider(Horizontal,this,"slider");slider->setRange(0,99);}intmain(intargc,char**argv{MyWidgetw;a.setMainWidget(&w);return}一行一行地#include<qapplicationh>#include<qslider.h>#include<qlcdnumberh>#include<qfonth>新的窗口部件,QSlider和QLCDNumber。qvbox.h在這里是因為使用了Qt的自動布局支classMyWidget:public{:QVBox(parent,name{MyWidget現(xiàn)在繼承了QVBox,而不是QWidget。通過這種方式來使用QVBox的布局(它可以把它的子窗口部件垂直地放在自己里面)。重新定義大小自動地被QVBox處理,因此現(xiàn)在也就被MyWidget處理了。QLCDNumber*lcd=newQLCDNumber(2,this,"lcd"lcd是一個QLCDNumber,一個可以按像LCD的方式顯示數(shù)字的窗口部件。這個實例被設置為顯示兩個數(shù)字,并且是this QSlider*slider=newQSlider(Horizontal,this,"slider");slider->setRange(0,99);QSlider是一個經(jīng)典的滑塊,用戶可以通過在拖動一個東西在一定范圍內調節(jié)一個整數(shù)數(shù)值的方參見QSlider::setRange()文檔)并且它的初始值是0。這里是用了信號/槽機制把滑塊的valueChanged()信號和LCD數(shù)字的display()槽連接起來這個新的值。因為這個信號已經(jīng)和LCD數(shù)字的display()槽連接起來了,當信號槽是和普通C++成員函數(shù)的方式不同,但有著普通C++行LCD數(shù)字反應了你對滑塊做的一切,并且這個窗口部件很好地處理了重新定義大小事件。注意當窗口被重新定義大?。ㄒ驗樗梢裕┑臅r候,LDC數(shù)字窗口練試著當 數(shù)字溢出的時候使這個應用程序退出Qt一——第六章:組裝豐富的積是容易。首先,使用一個自定義的窗口部件作為一個子窗口部件**Qt一-#include<qslider.h>#include<qlcdnumberh>#include<qfonth>#include<qvbox.h>#include<qgridh>classLCDRange:public{:QVBox(parent,name{QLCDNumber*lcd=newQLCDNumber(2,this,"lcd");QSlider*slider=newQSlider(Horizontal,this,"slider");slider->setRange(0,99);}classMyWidget:public{:QVBox(parent,name{QPushButton*quit=newQPushButton("Quit",this,"quit");quit->setFont(QFont("Times",18,QFont::Bold));connect(quit,SIGNAL(clicked()),qApp,SLOT(quit()));QGrid*grid=newQGrid(4,this);for(intr=0;r<4;r++for(intc=0;c<4;c++)(void)newLCDRange(grid);}intmain(intargc,char**argv{MyWidgetw;a.setMainWidget(&w);return}一行一行地classLCDRange:public{LCDRange窗口部件是一個沒有任何API的窗口部件。它只有一個構造函數(shù)。這種窗口部件不是很有用,所以一會兒會加入一些API。:QVBox(parent,name{QLCDNumber*lcd=newQLCDNumber(2,this,"lcd");QSlider*slider=newQSlider(Horizontal,this,"slider");slider->setRange(0,99);}classMyWidget:public{MyWidget也是除了一個構造函數(shù)之外沒有包含任何API:QVBox(parent,name{QPushButton*quit=newQPushButton("Quit",this,"quit");quit->setFont(QFont("Times",18,QFont::Bold));這個按鈕被放在LCDRange中,這樣就有了一個“Quit”按鈕和許LCDRangeQGrid*grid=newQGrid(4,this創(chuàng)建了一個四列的QGrid對象。這個QGrid窗口部件可以自動地把自己地子窗口部件排列到行列中,你可以指定行和列的數(shù)量,并且QGrid可以發(fā)現(xiàn)它的新子窗口部件并且把它們安放for(intr=0;r<4;r++for(intc=0;c<4;c++)(void)newLCDRange(grid);4*4個LCDRanges,所有這些都是這個grid對象的子窗口部件。這個QGrid窗口部件會安排它們。}行 數(shù)字的行為一章已經(jīng)提到過了。還有就是,就是實現(xiàn)的不同練源代碼中的“4”3次。如果你改變QGrid構造函數(shù)中調用的那個,會發(fā)生什么?改變另外tQ一——第七章:一個事物t另一連接起來。首先,源文件被分成幾部分并放在放在t7 t7/lcdrange.h包含LCDRange類定義。t7/lcdrange.cpp包含LCDRange類實現(xiàn)。t7/main.cpp包含MyWidget和main。#ifndefLCDRANGE_H#define這里是一個經(jīng)典的C語句,為了避免出現(xiàn)一個頭文件被包含不止一次的情況。如果你沒有使用過它,這是開發(fā)中的一個很好的。#ifndef需要把這個頭文件的全部都包含進去。qvboxh被包含了。LCDRange繼承了QVBox,所以父類的頭文件必須被包含。幾章里面偷了一點懶,通過包含其它一些頭文件,比如qpushbutton.h,這樣就可以間接地包含class是在實現(xiàn)中,在頭文件中使用一個前置的類,并且在.cpp文件中包含一個QSlider的頭classLCDRange:public{metaobjectfile注意Q_OBJECT。這個宏必須被包含到所有使用信號和/或槽的類。如果你很好publicslots:voidsetValue(intvoidvalueChanged(int定義槽,并且valueChanged()是第一個自定義信號。當CDage的值發(fā)生變化時,aueCagd()信號就會被使用——你從這個名可猜這會你看為Cagd()的最后一個信號。lcd,SLOT(display(int)));SIGNAL(valueChanged(int))這個代碼來自 的構造函數(shù)第一個connect和你在上一章中看到的一樣。第二個是新的,它把滑塊的valueChanged()信號和這個對象的valueChanged信號連接起來了。帶有三個參數(shù)的connect()函數(shù)連接到this對象的信發(fā)射了valueChanged()信號。這個信號被連接到QLCDNumber的display()槽和LCDRange的注意你并沒有保證執(zhí)行的任何順序——LCDRange::valueChanged()也許QLCDNumber::display()之前或者之后發(fā)射,這是完全任意intLCDRange::value(){}voidLCDRange::setValue(intvalue{}滑塊的值就會自動的改變LCDLCDRange*previous=0;for(intr=0;r<4;r++)for(intc=0;c<4;c++)LCDRange*lr=newLCDRange(gridif(previousprevious=lr;}}mincpp中所有的部分都是上一章的,除了yWiget函建16個RCRane象時在使信號槽機制連接它。每一個的vluChnged)信都和一個的etlue槽連接起來了。因為當LCRagevluehaned()號!創(chuàng)個槽。編它們自己的中,你所要做的就是這些:(系統(tǒng)相關的)makefile。你現(xiàn)在可以輸入make(或者nmake,如果你使用VisualStudio)行練sevenLCDsbackto50.使用右下角的滑塊并設置所有的LCD50。然后設置通40?,F(xiàn)在,你可以通過把最后一個調到左邊來把前七個LCD設置回50。tQ一——第八章:準備戰(zhàn)tt8/lcdrange.h包含LCDRange類定義。t8/lcdrange.cpp包含LCDRange類實現(xiàn)。t8/cannonh包含CannonField類定義。t8/cannon.cpp包含CannonField類實現(xiàn)。t8/main.cpp包含MyWidget和main。一行一行地voidsetRange(intminVal,intmaxVal現(xiàn)在添加了設置LCDRange范圍的可能性。直到現(xiàn)在,它就可以被設置在構造函數(shù)中有一個變化(稍 的){if(minVal<0||maxVal>99||minVal>maxVal)"\tRangemustbe"\tandminValmustnotbegreaterthanmaxVal",minVal,maxVal);}}setRange()設置了LCDRange中滑塊的范圍。因為已經(jīng)把QLCDNumber設置為只顯示兩位數(shù)字了,想通過限制minVal和maxVal為0~99來避免QLCDNumber的溢出。(可以允許最小值為-9,但是沒有那樣做。)如果參數(shù)是的,使用Qt的qWarning()函數(shù)來向用戶發(fā)出警告并立即返回。qWarning()是一個像printf一樣的函數(shù),默認情況下它的輸出發(fā)送到 是一個知道如何顯示自己的新的自定義窗口部件。classCannonField:public{intangle()const{returnang;publicvoidsetAngle(intdegreesvoidangleChanged(int目前,CanonField只包含一個角度值,使用了LCDRange中同樣的方式這是在QWidget中遇到的許多事件處理器中的第二個。只要一個窗口部件需要刷新它自己(比如,畫窗口部件表面),這個虛函數(shù)就會被Qt調用。:QWidget(parent,name{又一次使用和前一章中的 同樣的方式ang=setPalette(QPalette(QColor(250,250,200))}voidCannonField::setAngle(intdegrees{if(degrees<5)degrees=if(degrees>70)degrees=if(ang==degrees)ang=emitangleChanged(ang}這個函數(shù)設置角度值。選擇了一個5~70的合法范圍,并根據(jù)這個范圍來調節(jié)給定的degrees的值。當新的角度值超過了范圍,選擇了不使用警告然后設置新的角度值并重新畫的窗口部件。QWidget::repaint()函數(shù)清空窗口部件(通常{QStrings="Angle="+QString::number(ang);QPainterp(this);p.drawText(200,200,s}的QString,然后創(chuàng)建一個操作這個窗口部件的QPainter并使用它來畫這個字符串。一#include包含了的新類{這一次在頂層窗口部件中只使用了一個LCDRange和一個CanonFieldLCDRange*angle=newLCDRange(this,"angle"在構造函數(shù)中,創(chuàng)建并設置了的LCDRangeangle->setRange(5,70CannonField=newCannonField(this,"cannonField"創(chuàng)建了的CannonField這里把Dnge的vluehngd()信號和nnonField的tAngle()槽連接起來了。只要用戶操作Dng新nnonField的角度值。也把它反過來連接了,這樣nnonField中角度的變化就可以刷新Dnge的值。在的例子中,從來沒有直接改變nnonField的角度,但是通過的最后一個onnt()就可以確保沒有任何變化可以改變這兩個值之間的同步注意只有當角度確實發(fā)生變化時,才發(fā)射angleChanged()是重要。如果LCDRange和CanonField都省略了這個檢查,這個程序就會因為第一次數(shù)值變化QGridLayout*grid=newQGridLayout(this,2,2,10到現(xiàn)在為止,沒有因為幾何管理把QVBox和QGrid窗口部件集成到一起?,F(xiàn)在,無論如何,需要對的布局加一些控制,所以使用了更加強大的QGridLayout類。QGridLayout不是一個窗口部件,它是一個可以管理任何窗口部件作為子對象的不同的類。在網(wǎng)格的左上的單元格中加入一個Quit按鈕:0,0把angleLCDRange放到左下的單元格,在單元格內向上對齊。(這只是QGridLayout所允許的一種對齊方式,而QGrid不允許。)把 對象放到右下的單元格。(右上的單元格是空的。告訴QGridLayout右邊的列(1)是可拉伸的。因為左邊的列不是(0,這是默認值),QGridLayout就會在MyWidget被重新定義大小的時候試圖讓左面的窗口部件大小不變,而重新定義CannonField的大小。設置了一個初始角度值。注意這將會從LCDRange到CannonField的剛才做的是設置angle獲得鍵盤焦點,這樣默認情況下鍵盤輸入會到達LCDRange窗口部LCDRange沒有包含任何keyPressEvent(),所以這看起來不太可能有用。無論如點,滑塊就會就會注意到它。QSlider有一個相當好的鍵盤接口,所以就會出現(xiàn)給LCDRange添加的這一行。行鍵盤現(xiàn)在可以做一些事了——方向鍵、Home、End、PageUp和PageDown都可練如果你把AlignTop刪掉,LCDRange的位置會發(fā)生什么變化?為不考慮setFocus()調用。你更喜歡什么樣的試著在QButton::setText()調用中把“Quit”改為“&Quit”。按鈕看起來變成什么樣子了?如果你在程序運行的時候按下Alt+Q會發(fā)生什么?(在少量鍵盤中時Meta+Q。)CannonField的文本放到中t農(nóng)了t在這個例子中開始畫一個藍色可愛的小加農(nóng).只cannon.cpp和上一章不t9/lcdrange.h包含LCDRange類定義。t9/lcdrange.cpp包含LCDRange類實現(xiàn)。t9/cannonh包含CannonField類定義。t9/cannon.cpp包含CannonField類實現(xiàn)。t9/main.cpp包含MyWidget和main。一行一行地{QPainterp(thisp.setBrush(blue當一個QPainter填滿一個矩形、圓或者其它無論什么,它會用它的畫刷填滿這p.setPen(NoPen并且QPainter使用畫筆來畫邊界。這里設置為NoPen,就是說在邊界QPainter::translate()函數(shù)轉化QPainter的坐標系統(tǒng),比如,它通過偏移諒來移動。這里設置數(shù)(請看坐標系統(tǒng)獲得有關Qt的坐標系統(tǒng)的信息。)p.drawPie(QRect(-35,-35,70,70),0,90*16p.rotate(-angQpainter::rotate()函數(shù)繞QPainter坐標系統(tǒng)的初始位置旋轉它。旋轉的參數(shù)是一個按度數(shù)給定的針旋轉ang度數(shù)。p.drawRect(QRect(33,-4,15,8)在這種情況下,坐標系統(tǒng)先被轉化后被旋轉。如果矩形QRect(33415,8)被畫到這個轉化后的注意矩形被CannonField窗口部件的邊界省略了一部分。當選裝坐標系統(tǒng),以60度為例,矩形會以(0,0)為圓心被旋轉,也就是左下角,因為已經(jīng)轉化做完了,除了還沒有解釋為什么 在這個時候沒有發(fā)抖intmain(intargc,char**argv{QApplicationa(argc,argv);告訴Qt在這個程序中想使用一個不同的顏色分配策略。這里沒有單一正確的顏色分配策略。因為這個程序使用了不常用的黃色,但不是很多顏色,CustomColor最好。這里有幾個其行Quit中的字母QAlt+Q會實現(xiàn)你所要的。如果你不知道這練設置一個不同的畫筆代替NoPen。設置一個調色板的畫試著用“Q&uit”或者“Qu&it”作為按鈕的文本來提到“&Quit”。發(fā)生了什tQ一——第十章:像絲一樣t在這個例子中,介紹畫一個pixmap來除去閃爍。也會加入一個力量控t10/lcdrange.h包含LCDRange類定義。t10/lcdrange.cpp包含LCDRange類實現(xiàn)。t10/cannonh包含CannonField類定義。t10/cannon.cpp包含CannonField類實現(xiàn)。t10/main.cpp包含MyWidget和main。一行一行地 angle()const{returnang;} force()const{returnf;}public setAngle(intdegrees); setForce(intnewton angleChanged(int forceChanged(intintf;力量被到一個整數(shù)f中:QWidget(parent,name{ang=f=setPalette(QPalette(QColor(250,250,200))}voidCannonField::setAngle(intdegrees{if(degrees<5)degrees=if(degrees>70)degrees=if(ang==degrees)ang=emitangleChanged(ang}在setAngle()函數(shù)中做了一個小的改變。它只重畫窗口部件中含有加農(nóng)的一小部分。FALSE參數(shù)說明在一個繪畫事件發(fā)送到窗口部件之前指定的矩形將voidCannonField::setForce(intnewton{if(newton<0)newton=if(f==newton)f=emitforceChanged(f}setForce()的實現(xiàn)和setAngle()很相似。唯一的不同是因為不顯示力量值,我{QRectcr=cannonRect();QPixmappix(cr.size()然后,創(chuàng)建一個臨時的pixmap,用來不閃爍地畫。所有的繪畫操作都在這個pixmap中完成,并且之后只用一步操作來把這個pixmap錯誤。,你會得到閃爍。在這個例子中這個并不重要——當代碼被寫時,仍然是很慢的機器導致閃爍,但以后不會再閃爍了。由于教育目的保留了用這個pixmapQPainterp(&pix);p.setBrush(blue);p.setPen(NoPenp.translate(0,pix.height()-1p.drawPie(QRect(-35,-35,70,70),0,90*16p.rotate(-angp.drawRect(QRect(33,-4,15,8));就像第九章中一樣畫,但是現(xiàn)在是在pixmap上畫在這一點上,有一個繪畫工具變量和一個pixmap看起來相當正確,但是我p.begin(this所以在 上面打開繪圖工具并在這之后畫這個pixmapQRectCannonField::cannonRect()const{QRectr(0,0,50,50return}:QWidget(parent,name{LCDRange*force=newLCDRange(this,"force");force->setRange(10,50);加入了第二個LCDRange,用來設置力量QVBoxLayout*leftBox=newQVBoxLayout;grid->addLayout(leftBox,1,0);leftBox->addWidget(force);在第九章,把angle放到了布局的左下單元?,F(xiàn)在想在這個單元中放入兩個窗口部件,所一個用了一個垂直的盒子,把這個垂直的盒子放到這個網(wǎng)格單元中,并且把angle和force放到這個垂直的盒子中。行練試著加入一個更好的鍵盤接口。例如,用+和-來增加或者減少力量,用enter來發(fā)射。提示:QAccel和在LCDRange中新建addStep()和subtractStep(),就像QSlider::addStep()。如果你被左面tQ一——第十一章:給它一個t彈t11/lcdrangeh包含LCDRange類定義。t11/lcdrange.cpp包含LCDRange類實現(xiàn)。t11/cannon.h包含CannonField類定義。t11/cannon.cpp包含CannonField類實現(xiàn)。t11/main.cpp包含MyWidget和main。一行一行地t11/cannon private voidpaintShot(QPainter*inttimerCount;QTimer*autoShootTimer;floatshoot_ang;float這些私有變量包含了描述射擊的信息。timerCount保留了射擊進行后的時間。shoot_ang是加農(nóng)射擊時的角度,shoot_f是射擊時加農(nóng)的力量。#include包含了數(shù)學庫,因為需要使用sin() cos()函數(shù):QWidget(parent,name{ang=f=timerCount=autoShootTimer=newQTimer(this,"movementhandler");connect(autoShootTimer,SIGNAL(timeout()),this,SLOT(moveShot())shoot_ang=shoot_f=setPalette(QPalette(QColor(250,250,200))}初始化新的私有變量并且把QTimer::timeout()信號和的moveShot()槽相連。會void{timerCount=0;shoot_f=f;}void{QRectshotR=if(shotR.x()>width()||shotR.y()>height())r=r.unite(QRegion(shotR));repaint(r);}首先使用QRegion來保留舊的shotRect()。QRegion可以保留任何種類的區(qū)域,并且可下一步算出新的彈的矩形加新的shotRect()到QRegion。最后,重新繪制QRegion。這將會發(fā)送一個單一的繪畫事件,但僅僅有一{QRectupdateR=e->rect();QPainterp(this);paintCannon(&pif(autoShootTimer->isActive()&&updateR.intersects(shotRect()))paintShot(&p);}需要繪畫,檢查加農(nóng)和/或彈是否相交,并且如果需要的話,調用paintCannon()和/或paintShot()。{p->setBrush(black);p->setPen(NoPen}把paintCannon()的實現(xiàn)放到一邊,它和前一章中的paintEvent()一樣。QRectCannonField::shotRect()const{constdoublegravity=doubletime =timerCount/4.0;doublevelocity=shoot_f;double =doublevelx=velocity*cos(radians);doublevely=velocity*sin(radians);doublex0 =(barrelRect.right()+5)*cos(radians);doubley0 =(barrelRect.right()+5)*sin(radians);doublex =x0+velx*time;double =y0+vely*time-QRectr=QRect(0,0,6,6return}的timerCount之外,還使用初始時的加農(nóng)的力量和角度。在一個y坐標向上增加的坐標系統(tǒng)中計算中心點。在計算出中心點之后,構造一個6*6大小的QRect,并把它的中心移動到上面所計算出的中心點。同樣的操作把這個qRound()函數(shù)是一個在qglobal.h中定義的內嵌函數(shù)(被其它所有Qt頭文件包{唯一的增加是ShootQPushButton*shoot=newQPushButton("&Shoot",this,"shoot");shoot->setFont(QFont("Times",18,QFont::Bold));在構造函數(shù)中創(chuàng)建和設置Shoot按鈕就像對Quit按鈕所做的那樣。注意把Shoot按鈕的clicked()信號和CannonFieldshoot()行Thecannoncanshoot,butthere'snothingtoshoot練當彈在空中的時候,改變加農(nóng)的顏色tt在這個例子中,擴展的LCDRange類來包含一個文本。也會t12/lcdrange.h包含LCDRange類定義。t12/lcdrange.cpp包含LCDRange類實現(xiàn)。t12/cannonh包含CannonField類定義。t12/cannon.cpp包含CannonField類實現(xiàn)。t12/main.cpp包含MyWidget和main。一行一行地class名稱QLabel,因為在這個類中使用一個QLabel的指針classLCDRange:public{LCDRange(constchar*s,QWidget*parent=0,constchar*name=0);constchar*text()voidsetText(constchar*這個槽設置文本void因為現(xiàn)在有了兩個構造函數(shù),選擇把通常的初始化放在一個私有 還有一個新的私有變量:一個QLabel。QLabel是一個Qt標準窗口部件并且這里包含了QLabel類定義:QVBox(parent,name{}LCDRange::LCDRange(constchar*s,QWidget*parent,constchar*name):QVBox(parent,name{setText(s);}void{QLCDNumber*lcd=newQLCDNumber(2,this,"lcd");slider=newQSlider(Horizontal,this,"slider");label=newQLabel("",this,"label");label->setAlignment(AlignCenter);lcd,SLOT(display(int)));SIGNAL(valueChanged(int))}lcd和slider的設置和上一章一樣。接下來創(chuàng)建一個QLabel并且讓它的內容中間對齊(垂直constchar*LCDRange::text(){}voidLCDRange::setText(constchar*s{}這個函數(shù)設 文本CannonField現(xiàn)在有兩個新的信號:hit()和missed()。另外它還包含一個目標。 voidpaint(QPainter*#include包含了stdlib庫,因為需要rand()函數(shù)newCannonField窗口部件還是不可以見的。Qt保證在一個隱藏的窗口部件中調用 CannonField::new{staticbool_time=TRUE;if(_time){_time=QTimemidnight(0,0,0}=QPoint(200+rand()%190,10+rand()%255}使用rand()函數(shù)來獲得隨機整數(shù)。rand()函數(shù)通常會在你每次運行這個程序為了避免這些,須在這個函數(shù)第一次被調用的時候設置一個隨機。為了避免同樣一組數(shù)據(jù),隨機也必須是隨機的。解決方法就是使用從午夜if測試會成功,因為只有當這個函數(shù)第一次被調用的時候,在if塊中把_time設置然后創(chuàng)建一個QTime對象midnight,它將會提供時間00:00:00。接下來獲得從午夜到現(xiàn)在所過的秒數(shù)并且使用它作為一個隨機。請看QDate、QTime和QDateTime文檔來獲得更最后計算目標的中心點。把它放在一個矩形中(x=200,y=35,在一個把窗口邊界的下邊界作為y的零點,并且y向上增加,X軸向通常一樣,左邊界為零點,并且x向右增加的坐標系統(tǒng)中。注意rand()返回一個>=0的隨機整數(shù)。void{QRectshotR=if(shotR.intersects(Rect())emit注意,可以在這個點上創(chuàng)建一個新的目標,但是因為CannonField是一個組件,所以要把這樣的決定留給組件的使用者。}elseif(shotR.x()>width()||shotR.y()>height()emit}elseCannonField::paintEvent()isasbefore,exceptthatthishasbeenif(updateR.intersects(Rect())paint(&p{p->setPen(black}{QRectr(0,0,20,10return}這個私有函數(shù)返回封裝目標的矩形。從new()中所得的點使用0點在窗口部件的下邊界的y。在調用QRect::moveCenter()之前在窗口坐標中計算這個點。在MyWidget類中沒有新的成員了,但是稍微改變了一下構造函數(shù)來設置新的LCDRange的文本。 =newLCDRange("ANGLE",this,"angle"設置角度的文本為“ANGLE”LCDRange*force=newLCDRange("FORCE",this,"force"設置力量的文本為“FORCE”行LCDRange窗口部件看起來有一點奇怪——QVBox中內置的管理給了太多的空間而其它的練創(chuàng)建一個的按鈕,當按下它的時候,讓CannonField畫出彈在五秒中的軌如果你在上一章做了“圓形彈”的練習,試著改變shotRect()為可以返回一個QRegiontQ一——第十三章:結t在這個例子中開始研究一個帶有記分的真正可玩的。給MyWidget把定義放在gamebrd.h并把實現(xiàn)放在gamebrd.cppCannonField現(xiàn)在有了一個結束狀態(tài)。在LCDRange t13/lcdrange.h包含LCDRange類定義。t13/lcdrange.cpp包含LCDRange類實現(xiàn)。t13/cannonh包含CannonField類定義。t13/cannon.cpp包含CannonField類實現(xiàn)。t13/gamebrdh包含Gam t13/gamebrd.cpp包含Gam t13/main.cpp包含MyWidget和main。一行一行地classclassLCDRange:public繼承了QWidget而不是QVBox。QVBox是非常容易使用的,但是它也顯示了它的局域性,所以選擇使用更加強大和稍微有一些難的QVBoxLayout。(和你中的一樣,QVBoxLayout不是一個窗口部件,它管理窗口部件。)現(xiàn)在qlayout.h來獲得其它布局管理API:QWidget(parent,name使用一種平常的方式繼承QWidgetQVBoxLayout*l=newQVBoxLayout(thisAtthetopweaddtheQLCDNumberwithanon-zerostretch.l->addWidget(slider);這個伸展控制是QVBoxLayout(和QHBoxLayout,和QGridLayout)所提供的,而像QVBox這樣的類卻不提供。在這種情況下讓QLCDNumber可以伸展,而其它的不可以。CannonField現(xiàn)在有一個結束狀態(tài)和一些新的函數(shù)boolgameOver()const{returngameEnded;如果結束了,這個函數(shù)返回TRUE,或者如果還在繼續(xù),返FALSE 這里是兩個新槽:setGameOver()和restartGame()。 canShoot(bool);這個新的信號表明CannonField使shoot()槽生效的狀態(tài)。在下面使用它用來使Shoot按鈕生效或失效。boolgameEnded=幸運的:-)。void{if(isShooting())timerCount=0;shoot_f=f;}樣,shoot告訴世界CannonField現(xiàn)在不可以射擊。void{if(gameEnded)if(isShooting()gameEnded=} 。它必須被CannonField外面的調用,因為這個窗口部件不知道 版本可能使用不變的CannonField) void{if(isShooting()gameEnded=emitcanShoot(TRUE}這個槽開始一個新。如果彈還在空中,停止設計。然后重置gameEnded變量并就像hit()miss()一樣,moveShot()同時也發(fā)射新的canShoot(TRUE)信號。{QRectupdateR=e->rect();QPainterp(this);if(gameEnded)p.setPen(blackp.setFont(QFont("Courier",48,QFont::Bold));p.drawText(rect(),AlignCenter,"GameOver"}繪畫事件已經(jīng)通過如果結束,比如gameEnded是TRUE,就顯示文本“GameOver”而被增強到。接下來選擇Courier字體中的48號加粗字體。最后在窗口部件的矩形繪制文本。不幸的是,在一些系統(tǒng)中(特別是使用Unicode的X服務器)它會用一小段時間來載入如此大的字體。因為Qt緩存字體,只有第一次使paintCannon(&pif(isShooting()&&updateR.intersects(shotRect())paintShot(&pif(!gameEnded&&updateR.intersects(Rect())paint(&p}這個文件是新的。它包含最后被用來作為MyWidget的Gam類的定義classQPushButton;classLCDRange;classCannonField;#include"cannon.h"class :public{ protectedslots: QLCDNumber*hits;QLCDNumber*shotsLeft;CannonField*cannonField;這個文件是新的。它包含最后被用來作為MyWidget的Gam類的實現(xiàn),已經(jīng)在Gam的構造函數(shù)中做了一些修改。cannonField=newCannonField(this,"cannonField"this,SLOT(hit())this,SLOT(missed())這次當彈射中或者射失目標的時候,想做些事情。所以CannonField的hit()和missed()信號連接到這個類的兩個被保護的以前直接把Shoot按鈕的clicked()信號連接到CannonField的shoot()槽。這次想射擊的次數(shù),所以把它改為連接到這個類里面一個被保護的注意當你用獨立的組件工作的時候,改變程序的行為是容易shoot,SLOT(setEnabled(bool)));也使用cannonField的canShoot()信號來適當?shù)厥筍hoot按鈕生效和失效QPushButtonrestart->setFont(QFont("Times",18,QFont::Bold)創(chuàng)建、設置并且連接這個NewGame按鈕就像對其它按鈕所做的一hits=newQLCDNumber(2,this,"hits"shotsLeft=newQLCDNumber(2,this,"shotsleft");QLabel*hitsL=newQLabel("HITS",this,"hitsLabel");QLabel*shotsLeftL 類中是因為不想再對它們做什么了。當Gam QHBoxLayout*topBox=newQHBoxLayout;grid->addLayout(topBox,0,1);topBox->addWidget(shoot);topBox->addWidget(hits);topBox->addWidget(hitsL);topBox->addWidget(shotsLeft);topBox->addStretch(1);的,把它們放到布局中來更好的看到它們。注意讓所有的窗口部件獲得它們更喜歡的大小,改為在NewGame按鈕的 }已經(jīng)做完了所有關于Gam的構造,所以使用newGame()來開voidGam{if(cannonField->gameOver()||cannonField->isShooting())cannonField-}回。減少彈的數(shù)量并告訴加農(nóng)進行射擊。{hits->display(hits->intValue()+1);if(shotsLeft->intValue()==0)cannonField-}

cannonField->new了,就結束了。否則,會讓CannonField生成新的目標。voidGam{cannonField-}當彈射失目標的時候這個槽被激活,如果沒有彈了,就結束了voidGam{}當用戶點擊Restart按鈕的時候這個槽被激活。它也會被構造函數(shù)調用。首先它把彈的數(shù)量設置為15。注意這里是在程序中唯一設置彈數(shù)量的地方。把它改變?yōu)槟闼胍囊?guī)則。接下來重置射中的數(shù)量,重新開始游行且還有一個按鈕可以開始一個新。練當彈目標的時候做一些飛濺的效果。tQ一——第十四章:面對墻t這是最后的例子:一個完整的添加鍵盤快捷鍵并引入鼠標事件到CannonField。在CannonField周圍 t14/lcdrange.h包含LCDRange

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論