嵌入式系統設計與開發-基于ARM Cortex-A9和Linux 課件 第11章 Qt編程及嵌入式Qt開發_第1頁
嵌入式系統設計與開發-基于ARM Cortex-A9和Linux 課件 第11章 Qt編程及嵌入式Qt開發_第2頁
嵌入式系統設計與開發-基于ARM Cortex-A9和Linux 課件 第11章 Qt編程及嵌入式Qt開發_第3頁
嵌入式系統設計與開發-基于ARM Cortex-A9和Linux 課件 第11章 Qt編程及嵌入式Qt開發_第4頁
嵌入式系統設計與開發-基于ARM Cortex-A9和Linux 課件 第11章 Qt編程及嵌入式Qt開發_第5頁
已閱讀5頁,還剩115頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

第十一章Qt編程及嵌入式Qt開發北京航空航天大學電工電子中心2025年6月提綱Qt編程基礎圖形界面設計信號和槽機制Qt程序綜合實驗—電子鐘設計Qt開發環境的搭建Qt是一個1991年由QtCompany開發的跨平臺C++圖形用戶界面應用程序開發框架。它既可以開發GUI程序,也可用于開發非GUI程序,比如控制臺工具和服務器。Qt是面向對象的框架,使用特殊的代碼生成擴展(稱為元對象編譯器(MetaObjectCompiler,moc))以及一些宏,Qt很容易擴展,并且允許真正地組件編程。2008年,QtCompany科技被諾基亞公司收購,Qt也因此成為諾基亞旗下的編程語言工具。2012年,Qt被Digia收購。2014年4月,跨平臺集成開發環境QtCreator3.1.0正式發布,實現了對于iOS的完全支持,新增WinRT、Beautifier等插件,廢棄了無Python接口的GDB調試支持,集成了基于Clang的C/C++代碼模塊,并對Android支持做出了調整,至此實現了全面支持iOS、Android、WP,它提供給應用程序開發者建立藝術級的圖形用戶界面所需的所有功能。基本上,Qt同XWindow上的Motif,Openwin,GTK等圖形界面庫和Windows平臺上的MFC,OWL,VCL,ATL是同類型的東西。QT和QTCreatorQt是跨平臺的應用程序和UI框架。它包括跨平臺類庫、集成開發工具和跨平臺IDE。使用Qt只需一次性開發應用程序,無須重新編寫源代碼,便可跨不同桌面和嵌入式操作系統部署這些應用程序。QTQt的用途Qt支持的平臺QT簡介QT簡介QtCreator是專為滿足Qt開發人員需求而量身定制的跨平臺集成開發環境(IDE)。QtCreator可在Windows、Linux/X11和MacOSX桌面操作系統上運行,供開發人員針對多個桌面和移動設備平臺創建應用程序。QtCreator簡介QtCreator包括:高級C++和JavaScript代碼編輯器集成用戶界面設計器項目和構建管理工具gdb和CDB調試程序的支持版本控制的支持移動用戶界面模擬器為桌面和移動目標平臺提供支持QTCreator簡介

除此之外,還有一個開發套件叫QtSDK,包括Qt庫、QtCreatorIDE和Qt工具,全部都集成在一個易于安裝的文件包里。QT數據類型QString類如有下特點:采用Unicode編碼,所以一個QString類對象占用兩個字節。采用隱式共享技術來節省內存和減少不必要的數據備份。跨平臺使用,不用考慮字符串的平臺兼容性。QString類直接支持字符串和數字之間的相互轉換。QString類直接支持字符串之間的大小比較(按照字典順序)。QString類直接支持不同編碼下的字符串轉換。QString類直接支持std::string和std::wstring之間的相互轉換。QString類直接支持正則表達式的使用。QT字符串QT字符串--數字和QString互相轉換使用static的函數number()可以把數字轉換成字符串。例如:QStringstr=QString::number(123.4);也可以使用非static函數setNum()來實現相同的目的:QStringstr;str.setNum(123.4);QString轉為int;QStringstr=“123”;intd=str.toInt();QT字符串--

char*和QString互相轉換將char*類型的C語言風格的字符串轉換成QString類的對象也很常見。char*c_str=“HelloWords!”; //QStringstr(c_str); //char*轉換為QStringQString轉換為char*分為兩步,首先調用toAscii()獲得一個QByteArray類的對象,然后調用它的data()或者constData()函數,為了方便起見,Qt提供了一個宏qPrintable(),等價于toAscii().ConstData()。例如:printf(“ΜSer:%s/n”,str.toAscii().data());printf(“ΜSer:%s/n”,qPrintable(str));QT字符串--截斷字符串voidtruncate(intposition);

//從位置position處截斷,位置從索引值0開始voidchop(intposition); //截掉最后的n個字符QT字符串--清空voidclear();//清空QString類對象的內容,使之成為空字符串QT字符串--字符串的比較intcompare(constQString&s1,constQString&s2);inta=QString::compare(“def”,“abc”); //a>0intb=QString::compare(“abc”,“def”); //b<0intc=QString::compare(“abc”,“abc”); //c=0QT字符串--判斷是否以某個字符串開頭或結尾函數startsWith()用于判斷是否以某個字符串開頭,函數endsWith()用于判斷是否以某個字符串結束。比如:QStringstr1=“d:\zcbBook\QT5.12Study\qw.cpp”;boolN=str1.endsWith(“.cpp”,Qt::CaseInsensitive);//N=trueN=str1.endsWith(“.cpp”,Qt::Casesensitive);

//N=falseN=str1.startsWith(“D”);

//N=true,默認為不區分大小寫又比如,以下兩句話等效:if(ur1.startsWith(“http:”)&&ur1.endsWith(“.png”)){}if(ur1.left(5)==“http:”&&ur1.right(4)==“.png”){}QT字符串--判斷是否包含某個字符串QStringstr1=“D:\北航云盤\07879\教材相關2020_0602\main.cpp”;N=str1.contains(“.CPP”,Qt::Casesensitive); //N=falseQT字符串--判斷字符串是否為空QStringstr1,str2=“”;

N=str1.isNull(); //N=true 未賦值字符串變量N=str2.isNull(); //N=false 只有“\0”的字符串也不是NullN=str1.isEmpty(); //N=trueN=str2.isEmpty(); //N=true上述例子給出了isNull()和isEmpty()的區別。對于“\0”,isNull()返回假,而isEmpty()返回真。QT字符串--移除字符成員函數remove()可以移除字符串中一個或者多個字符,函數原型聲明如下:QString&remove(intposition,intn);其中,參數position表示要被移除字符的起始索引位置;n表示要移除字符的個數。函數返回移除字符后字符串的引用。QStringtest=“Hi,Beihang!”; //字符串賦初值QStringtmp=test.remove(2,4); //從索引值為2的字符開始,移除4個字符qDebug()<<“test”<<test; //輸出HihangqDebug()<<“tmp”<<tmp; //輸出HihangQT字符串--字母大小寫的轉換使用成員函數toUpper()和toLower(),將字符串內的字母全部轉換為大寫形式和小寫形式。QStringstr1=“Hi,Beihang!”,str2;str2=str1.toUpper(); //str1=“HI,BEIHANG”str2=str1.toLower(); //str1=“hi,beihang”QT字符串--獲取長度共有三個成員函數count()、size()、length()返回字符串中字符的個數。示例如下:QStringstr1=“Hello北航”;N=str1.count(); //N=7N=str1.size(); //N=7N=str1.length(); //N=7QT字符串--復制運算賦值運算符是=,比如:QStringstr=“abcde”;QT字符串--訪問某個元素QString元素的訪問共有4種方式,兩種可讀可寫方式([]、data[])和兩種可讀方式(at()、constData[])。QStringstr=“World”; //intn=str.size(); //n=5str.data()[0]; //返回Wstr.data()[4]; //返回d提綱Qt編程基礎圖形界面設計信號和槽機制Qt程序綜合實驗—電子鐘設計Qt開發環境的搭建界面是嵌入式系統的重要組成部分,其地位和作用也越來越重要。這得益于嵌入式系統硬件的發展和軟件技術的發展。雖然能夠設計界面的軟件有很多種,但Qt是嵌入式系統最為常用的圖形界面開發軟件。即便Qt具有網絡編程、多媒體應用、數據庫編程功能,Qt最大的作用還是在圖形用戶界面設計上,它有大量的用于圖形設計的類庫,便于使用、易于擴展。圖形界面設計Qt的窗口類WidgetQt的窗口類Widget本書例程中使用的QMainWindow是QWidget的直接繼承子類;QLineEdit是QWidget的直接繼承子類;QLabel繼承于QFrame,QFrame是QWidget的直接繼承子類;QPushButton繼承于QAbstractButton,QAbstractButton是QWidget的直接繼承子類。Qt的窗口類WidgetQt里有個概念叫窗口,窗口又稱為頂層部件,Qt把沒有嵌入到其他部件的部件叫窗口,很顯然,窗口是沒有父部件的部件。在Qt類庫中,就界面而言,QWidget、QMainWindow和QDialog是常見的三種窗口,其中尤以QWidget為最多。可視化窗口界面設計Qt里有一個概念叫控件,控件又叫部件,有時也稱組件,是完成一段特定功能的程序代碼。比如,用于發送信息的QPushButton按鈕。很顯然這些控件被加入到某一窗口,以完成更加復雜的工程。這些控件添加到窗口里有幾種方法:使用可視化控件。通過拖拽控件,例如,添加按鈕。在Buttons下面找到PushButton按鈕,將鼠標放在控件上,單擊鼠標左鍵,就可將按鈕拖拽到窗口里,這種設計方法簡單,同時,控件可以放在你希望的任何位置,字體可大可小。代碼化設計。界面的底層既然是由C++實現的,底層實現的功能比可視化設計更加強大和靈活。某些界面效果是可視化界面設計無法完成的。特別復雜的邏輯功能,語言表達的能力遠遠超過可視化界面。

Qt中常用的控件常見的工具條上面的幾個工具條分別是:EditWidgetF3、EditSignals/SlotsF4、EditBuddies、EditTabOrder、水平布局(H)Ctrl+H、垂直布局(V)Ctrl+H、使用分裂器水平布局(P)、使用分裂器垂直布局(L)、在窗體布局中布局(F)、柵格布局器(G)Ctrl+G、打破布局(B)、調整大小(S)Ctrl+J。Qt控件--QPushButtonQPushButton類是QAbstractButton類的子類,通常用于執行命令或觸發事件。單擊該按鈕通常是通知程序進行一個操作,比如彈出框、下一步、狀態機事件遷移、確認、退出等,大多數對話框程序中幾乎都有這種按鈕。⑴

按鈕的主要屬性有:name:該控件對應源代碼中的名字。text:該控件對應圖形界面中顯示的名字。font:設置text的字體。enable:該控件是否可用。⑵

按鈕常用的信號有:voidpressed();當按下該按鈕時發射信號。voidclicked();當單擊該按鈕時發射信號。voidreleased();當發射按鈕時發射信號。Qt控件--QPushButton⑶

按鈕常用的成員函數有:構造函數QPushButton():QPushButton(constQString&text,QWidget*parent,const*name=0);構造一個名稱為name、父對象為parent并且文本為text的按鈕。比如:QPushButton*button=newQPushButton(tr(“確定”),this);setText()函數:voidsetText(constQString&);設置該按鈕上顯示的文本。text()函數:QStringtext()const;返回該按鈕上顯示的文本。Qt控件--QlabelQLabel類是QFrame類的子類,用于簡單的界面顯示。QLabel共66個屬性:6個繼承自QFrame,59個繼承自QWidget,1個繼承自QObject。19個公共槽函數繼承自QWidget,1個公共槽函數繼承自QObject。⑴QLabel的主要屬性有:text:QString文本內容。pixmap:加載圖片。scaledContents:bool默認為false,當設為true時,自動填滿空間。openExternalLinks:bool指定是否使用QDesktopServicesQlabel。hasSelectedText:constbool默認為false,當有內容被選中時為true。margin:int邊緣的寬度。indent:int縮進,以像素為單位,默認為-1。Qt控件--Qlabel⑵PublicSlots:voidclear(); //清零QLAbelvoidsetMovie(QMovie*movie); //在QLabel上播放沒有聲音的動畫voidsetNum(intnum); //顯示整型數voidsetNum(doublenum); //顯示double型的數voidsetPixmap(constQPixmap&);

//顯示圖畫voidsetText(constQString&); //顯示字符串Qt控件--Qlabel⑶QLabel常用信號有:voidlinkActivated(constQString&link); //當用戶單擊一個鏈接時發出這個信號voidlinkHovered(constQString&link); //當用戶將鼠標懸停于一個鏈接時,發出這個信號。Qt控件--Qlabel⑷QLabel常用公有函數有:QStringtext()const; //讀取文本QMovie*movie()const; //返回Move的指針,沒有返回0voidsetSelection(intstart,intlength);//設置選中的文本,開始位和長度pixmap()const; //返回pixmap的指針,沒有返回0QWidget*buddy()const; //返回交互的控件指針,單擊一個控件另一

個控件也會單擊voidsetTextFormat(Qt::TextFormat);//設置文本格式QLineEdit類是QWidget類的子類,通常用于簡單文本輸入,例如鍵盤上輸入文本或數據到QLabel上。QLineEdit共60個屬性:59個繼承自QWidget,1個繼承自QObject。

行編輯框(QLineEdit)的主要屬性有:inputMask //掩碼(默認格式)text //文本maxLength //最大長度echoMode //回響模式(輸入的文字的樣子)cursorPosition //鼠標位置aligment //對齊方式dragEnabled //拖拽使能readOnly //只讀placeHolderText //提示信息cursorMoveStyle //鼠標移動形式clearButtonEnabled //清零按鈕使能Qt控件--QLineEdit⑵

行編輯框常用信號有:voidcursorPositionChanged(intold,intnew);//當光標位置改變時,發射信號。old表示舊位置,new表示新位置。voideditingFinished(); //當編輯完成時按回車鍵,發射信號voidreturnFinished(); //光標在行編輯框內按回車鍵,發射信號voidselectionChanged(); //選擇的文本發生改變時,發射信號voidtextChanged(constQString&text);//當內容改變后,發射信號。通過text,可以在槽函數中獲取編輯框中的內容voidtextEdited(constQString&text);//當文本被編輯時,發射信號。當調用setText()函數改變文本時,textEdited()也會發射信號Qt控件--QLineEdit⑶行編輯框常用的成員函數有:voidsetText(QString); //設置編輯框內的文本voidsetReadOnly(bool); //設置編輯框為只讀模式,無法進行編輯voidsetEnabel(bool); //設置是否激活行編輯框boolisModified(); //判斷文本是否被修改voidselectAll(); //選中框內所有文本QStringdisplayText(); //返回顯示的文本QStringselectedText(); //返回被選中的文本QStringtext()const; //返回輸入框的當前文本voidsetMaxLength(int); //設置文本的最大允許長度voidsetPlaceholderText(QString); //設置占位符voidsetEchoMode(QLineEdit::EchoMode);//設置輸入方式,比如參數是QLineEdit::PassWord的時候,則輸入的內容以星號表示,即密碼輸入方式Qt控件--QLineEditQt控件--QTimerQTimer繼承自QObject,它不是嚴格意義上的控件,它是Qt的類。它是一個定時器,通過設置定時時間,產生溢出,發出信號,執行對應的周期時間處理函數。⑴

QTimer的主要屬性有:active:constbool //如果定時器正在運行為true,其他為falsesingleShot:bool //發射一次信號設為true,定時器只運行一次interval:int //用來設置定時器間隔remainingTime:int //剩余時間,初始化為-1,啟動后直到為0timerType:Qt::TimerType //定時器準確性設置,默認屬性為粗

糙定時器(%5誤差)Qt控件--QTimer⑵

QTimer常用的信號:voidtimeout();//定時溢出信號,通過信號和槽的關聯,執行相關操作。⑶

QTimer的公共槽函數voidstart(intmsec);

//周期性啟動,時間間隔的單位是毫秒voidstart(); //定時器啟動voidstop(); //定時器停止⑷

公有函數QTimer(QObject*parent=0);//構造函數inttimerId()const; //返回id,如果正在運行返回-1提綱Qt編程基礎圖形界面設計信號和槽機制Qt程序綜合實驗—電子鐘設計Qt開發環境的搭建信號和槽機制—基本概念信號和槽機制是Qt的核心機制。它是Qt的核心特性,也是Qt區別于其他工作包的重要地方。信號和槽是一種高級接口,應用于對象之間的通信,信號和槽是Qt自定義的一種通信機制,獨立于標準的C/C++語言。因此要正確地處理信號和槽,必須借助一個稱為moc(metaobjectcompiler)的Qt工具,該工具是一個C++預處理程序,它為高層次的事件處理自動生成所需要的附加代碼。從計算機程序的角度看,對象之間必須進行某種關聯。比如,敲擊鍵盤,顯示對象必須做出響應。Qt對它們的描述是信號和槽,擊打鍵盤發出的信號,信號的本質也是函數,信號可以由widget發出,widget所發信號是由Qt的事件產生。如果使用系統預定義的控件,那么我們關心的是信號;如果使用的是自定義控件,那么我們關心的是事件。信號和槽機制—基本概念事件信號槽元對象編譯器基本概念—事件事件是由程序內部或外部產生的事情或某種操作的總稱。Qt常見的事件有:定時器事件(QTimerEvent)滾動事件(QScrollEvent)窗口尺寸改變事件(QResizeEvent)鍵盤事件(QKeyEvent)鼠標事件(QMouseEvent)等Qt中的事件循環是由QApplication.exec()開始的。當該語句執行后,應用程序便建立了一個事件循環機制,該機制不斷地從系統的消息隊列中獲取與應用程序有關的消息,并根據事件攜帶的信息將事件對應到目的窗口或控件。signals是Qt的概念,它的引入是為了方便事件的處理。signals封裝了一些事件操作的標準預處理,使得用戶不必去關心底層事件,只需要處理封裝好的信號就行了。signals的本質也是函數,該函數是void類型,沒有函數體。可以沒有參數,也可以有一個或者多個參數。Qt定義了很多預處理信號,且在某些事件處理函數中會發送預定義的信號。例如,QPushButton類的按鈕按下的時候可以發送clicked()信號,從用戶的角度看,clicked()信號可以直接拿來關聯槽函數,編寫相關的響應槽函數即可。至于clicked()信號的生成過程是由Qt自動完成的,無須用戶關心。在頭文件中聲明信號如下:signals:voidgetText(); voidgetText(constQString&string1);voidgetText(constQString&string1,constQString&string2);上述的三個信號量同名,第一個信號量不帶參數,第二個信號量帶一個參數,第三個信號量帶兩個參數。從形式上講信號的聲明與普通的C++函數是一樣的,但是信號卻沒有函數體定義,另外,信號的返回類型都是void,不要指望能從信號返回什么有用信息。基本概念—信號基本概念—槽槽的本質是類的成員函數,可以是public、private、protected中的任意一種。一個信號可以關聯一個槽,一個信號關聯多個槽,多個信號可以關聯同一個槽,一個信號甚至能夠和另一個信號相關聯。槽函數功能的定義相當靈活,可大可小。對多個信號的處理,當然可以在多個槽函數中進行,也可以在一個槽函數中進行。槽的聲明也是在頭文件中進行的。例如,下面聲明了兩個槽:privateslots:voidQlabel_response(); voidWriteTextToLabel(constQString&string);privateslots:在這個區內聲明的槽意味著只有類自己可以將信號與之相連接。這適用于

聯系非常緊密的類。protectedslots:在這個區內聲明的槽意味著當前類及其子類可以將信號與之相連接。這適用于那些槽,它們是類實現的一部分,但是其界面接口卻面向外部。publicslots:在這個區內聲明的槽意味著任何對象都可將信號與其相連接。用戶可以創建彼此互不了解的對象,將它們的信號與槽進行連接以便信息能夠正確的傳遞。基本概念—元對象編譯器Qt中有個重要的概念叫元對象編譯器。它是Qt對C++的發展,元對象包含全部信號和槽的名字以及指向這些函數的指針。當用戶需要使用moc的時候,要在類聲明的使用調用宏Q_OBJECT。調用了Q_OBJECT就能夠使用Qt的信號與槽機制。moc并不擴展#include或者#define宏定義,它只是簡單地跳過所遇到的任何預處理指令,所以宏定義不能用在信號與槽的參數中。信號和槽機制信號和槽機制信號和槽是Qt為解決對象間通信問題的解決方案。信號和槽只能在QObject和QObject派生類中使用。自定義的類,如果基類不是QObject和QObject派生類,就不能使用信號和槽機制。信號和槽是Qt框架的重要特性,它摒棄了傳統回調函數機制,采用簡潔而靈活的連接方式,可以攜帶任意數量和任意參數的數據,是可視化編程界面在發展歷程中的一大成就。當對象改變其狀態時,信號就由該對象發射(emit)出去,信號的發送對象并不知道誰在關聯這個信號。這就給信號發送的設計提供了極大的便利。這是真正的信息封裝,確保對象被當做一個真正的軟件組件來使用。上圖是信號與槽關聯方式結構示意圖。圖中信號和槽關聯方式多樣:一個信號和一個槽關聯,一個信號和多個槽關聯,多個信號和一個槽關聯。完成信號和槽關聯后,該機制隱藏復雜的底層實現。信號和槽的關聯該函數的定義如下:boolQObject::connect(constQOject*sender,constchar*signal,constQObject*receiver,constchar*member)[static]這個函數的作用就是將sender對象中的信號signal與接收者receiver中的member槽函數聯系起來。當指定信號signal時,必須使用Qt的宏SIGNAL();當指定槽函數時,必須使用宏SLOT()。如果發射者與接收者屬于同一個對象,那么在connect調用中接收者參數可以省略。例如,下面定義了兩個對象:標簽對象label和滾動條對象scroll,并將valueChanged()信號與標簽對象的setNum()相關聯,另外信號還攜帶一個整型參數,這樣標簽總是顯示滾動條所處位置的值。QLabel*label =newQLabel;QScrollBar*scroll=newQScrollBar;QObject::connect(scroll,SIGNAL(valueCbanged(int)),label,SLOT(setNum(int)));信號和槽的斷開當信號與槽沒有必要繼續保持關聯時,可以使用disconnect函數來斷開連接。其定義如下:boolQObject::disconnect(constQObject*sender,constchar*signal,constObject*receiver,constchar*member)[static]這個函數斷開發射者中的信號與接收者中的槽函數之間的關聯。取消一個連接不是很常用,因為Qt會在一個對象被刪除后自動取消這個對象所包含的所有連接。有三種情況必須使用disconnect()函數。(1)斷開與某個對象相關聯的任何對象。這似乎有點不可理解,事實上,當在某個對象中定義了一個或者多個信號時,這些信號與另外若干個對象中的槽相關聯,如果要切斷這些關聯的話,就可以利用這個方法,非常簡潔。disconnect(myObject,0,0,0);或者myObject→disconnect();信號和槽的斷開(2)斷開與某個特定信號的任何關聯。disconnect(myObject,SIGNAL(mySignal()),0,0);或者myObject→disconnect(SIGNAL(mySignal()));(3)斷開兩個對象之間的關聯。disconnect(myObject,SIGNAL0,myReceiver(),0);或者myObject→disconnectmyReceiver();在disconnect函數中0可以用作一個通配符,分別表示任何信號、任何接收對象和接收對象中的任何槽函數。但是發射者sender不能為0,其他三個參數的值都可以等于0。信號和槽示例--頭文件(.h)信號和槽示例--源文件(.cpp)示例給出了完整的頭文件和源文件。文件中定義了一個信號量和一個槽函數,對信號和槽進行了關聯,槽函數在調試區打印了一句話。信號和槽的聲明在頭文件里進行,頭文件的開始部分加上Q_OBJECT宏定義語句,告訴編譯器在編譯之前必須要應用moc工具進行擴展,否則無法使用信號與槽。關鍵字signals指出了隨后開始信號的聲明,不存在單數形式的signal,屬性沒有public、private和protected。信號量的本質是函數,它的聲明左邊是void類型(必須是void類型),右邊是括號,括號內可以有一個或多個參數,也可以不帶參數,如文中的signals:voidmy_signal()。信號也可以使用C++中虛函數的形式進行聲明,即同名參數不同。信號和槽示例關鍵字slots指出隨后開始槽的聲明,和普通的成員函數一樣,槽函數可以是public、private和protected中的一種。槽函數不同于普通成員函數有兩點:一是它必須是void類型,沒有返回值;二是它可以關聯信號。signals和slots是Qt的關鍵字,不是C++的關鍵字。斷開信號和槽連接時可以使用disconnect函數,讀者可以參考有關文獻。有時,disconnect函數不是顯性表示出來的,它可以在析構類的時候被調用。信號和槽示例示例使用三個connect語句,connect(this,SIGNAL(test_signal()),this,SLOT(test_slot()))是使用最多的形式,SIGNAL、SLOT形式的信號和槽能夠清楚表達參數的個數和類型,因此支持同名不同參數的信號(比如信號沒有參數或者有一個參數或者有多個參數)。connect(this,&MainWindow::test_signal,this,&MainWindow::test_slot)是指針形式,信號和槽都是由指針指向。需要注意,兩者相比,指針指向信號和槽的時候要加上類名。connect(this,&MainWindow::test_signal,[&](){doEverything();});這是lambda表達式形式的匿名函數,也經常出現在各種設計中。大家對以上幾種connect對比學習,體會各種設計的優缺點。信號和槽示例信號和槽小結--信號和槽機制的優點信號和槽的機制是類型安全的:一個信號的簽名必須與它的接收槽的簽名相匹配(實際上一個槽的簽名可以比它接收的信號的簽名少,因為它可以忽略額外的簽名)。因為簽名是一致的,編譯器就可以幫助用戶檢測類型不匹配。信號和槽是寬松地聯系在一起的。一個發射信號的類不用知道也不用注意哪個槽要接收這個信號,Qt的信號和槽的機制可以保證如果把一個信號和一個槽連接起來,槽會在正確的時間使用信號的參數而被調用,信號和槽可以使用任何數量和任何類型的參數。它們是完全類型安全的:不會再有回調核心轉儲(coredump)。信號和槽小結--信號和槽使用時注意事項信號與槽機制是比較靈活的,但有些局限性必須了解,這樣在實際的使用過程中可以做到有的放矢,避免產生一些錯誤。下面就介紹一下這方面的情況。信號與槽的效率是非常高的,但是與真正的回調函數比較起來,由于增加了靈活性,因此在速度上還是有所損失,當然這種損失相對來說是比較小的,通過在一臺i586-133的機器上測試完成一個信號傳輸的時間是10μS(運行Linux),可見這種機制所提供的簡潔性、靈活性還是值得的,但如果要追求高效率的話,如在實時系統中就要盡量少用這種機制。信號與槽機制與普通函數的調用一樣,如果使用不當的話,在程序執行時也有可能產生死循環。因此,在定義槽函數時一定要注意避免間接形成無限循環,即在槽中再次發射所接收到的同樣信號。例如,在前面給出的例子中如果在mySlot()槽函數中加上語句emitmySignal()即可形成死循環。如果一個信號與多個槽相聯系的話,那么,當這個信號被發射時,與之相關的槽被激活的順序將是隨機的。宏定義不能用在signal和slot的參數中,信號和槽小結--信號和槽的四種實現方式信號和槽是Qt連接信號和槽函數的樞紐,connect只是連接信號和槽的一種方式。下面補充說明一下。(1)以QPushButton按鈕為例,在左側的工具欄里拖拽一個按鈕,對象名改為“PushButton”,鼠標放在按鈕上,單擊右鍵,選擇“轉到槽…”,在轉到槽選擇面板上,選擇需要進行的操作,比如單擊clicked()。(2)操作同上,將按鈕拖拽到ui頁面,選擇菜單“編輯”,找到EditSignals/Slots(或者按快捷鍵F4),或者在工具欄里找到EditSignals/Slots,然后拖拽按鈕并釋放,彈出配置連接。QPushButton(QPushButton)下選clicked(bool),Mainwindow(QMainwindow)下選setAnimated(bool)。信號和槽小結--信號和槽的四種實現方式(3)自定義方式。這種方式編程時比較自由,特別是當程序很大或者信號和槽間的連接關系特別復雜的時候,常常采用connect函數連接的方式。在頭文件的私有槽函數(privatedslots)中添加:voidon_button1_clicked();在cpp文件下面的構造函數里添加connect(ui->PushButton,SIGNAL(clicked(),this,SLOT(on_button1_clicked()));接著實現槽函數即可。(4)不用寫connect。Qt信號和槽的命名是有規則的。槽函數名組成為:on_對象名_信號,以按鈕為例,如果對象名為PushButton,在你寫槽函數時按此規則,在頭文件中添加:privateslots:voidon_PushButton_clicked();在cpp文件的構造函數里就不要寫構造函數了。不難看出,方法⑷和方法⑴有異曲同工之妙。從信號與槽關聯效果上看,兩種完全同效。方法⑴簡單,是系統自動完成的;方法⑷有點復雜,是程序員手工完成的。提綱Qt編程基礎圖形界面設計信號和槽機制Qt程序綜合實驗—電子鐘設計Qt開發環境的搭建Qt程序電子鐘設計綜合實驗—需求說明本實驗虛擬機的版本是VMwareWorkstation15pro,Ubantu的版本是18.04,Qt的版本是5.12.8。通過設計一個圖形化的用戶界面實現電子鐘來說明Qt程序設計與實現的過程。這個應用程序應該具如下基本功能:設計電子鐘的用戶界面。界面包括顯示時間的時、分、秒、毫秒,毫秒顯示的單位是10mS,便于顯示的直觀。具有啟動/停止、暫停、復位功能。通過啟動/停止按鈕,實現電子鐘的啟停,暫停后可以繼續計時,復位鍵可實現清零。當秒表使用。可手動設置電子鐘的時間。可手動設置時間,通過界面的功能鍵,切換為計時狀態和設置狀態,用一個Qlabel顯示電子鐘的工作狀態。Qt程序電子鐘設計綜合實驗—界面設計界面使用8個QLabel。該類對象包括dot1~dot3,分別是“時”“分”“秒”之間的“:”以及“秒”與“毫秒”之間的“.”;label_hour、label_minus、label_second、label_ms,用于顯示電子鐘的“時”“分”“秒”“毫秒”;label_status是電子鐘的功能顯示,用于指示電子鐘(包括秒表)工作狀態以及時間調整狀態。這8個QLabel的.text屬性,即編程界面顯示的字符分別是hour:minus:second.ms、Status。類對象(objectName)用于編程,.text用于靜態顯示。界面使用4個QPushButton。該類對象包括Start_Button、Reset_Button、Pause_Button、FUN_Button,對應的.text是Start、Reset、Pause和FUNKey。FUN_Button共有四種模態,每按下一次,由Status顯示,依次切換“電子鐘狀態”“設置時”“設置分”“設置秒”。“電子鐘狀態”可啟停、暫停、復位電子鐘。設置時間時對應的指示對象在閃爍。FUN_Button開機默認值是“電子鐘狀態”。Qt程序電子鐘設計綜合實驗—界面設計界面使用一個QLineEdit。類對象是LineEditButton,用于QString數據類型數據的輸入。將鼠標放在該控件上,即可由鍵盤輸入“時”、“分”、“秒”數據,相關代碼將進行對應的限幅處理,即“時”的最大值是23,“分”“秒”的最大值是59。輸入的數據由鍵盤上的“Enter”結束。同時“Enter”鍵清空LineEditButton,便于下一次數據的輸入。界面使用了控件QLabel、QPushButton和QLineEdit,同時在程序里使用了QTimer定時器,通過編寫對應的程序,完成電子鐘運行時的各種操作。Qt程序電子鐘設計綜合實驗—界面設計Qt程序電子鐘設計綜合實驗—文件結構電子鐘是通過一個項目來完成的,這個項目的名字叫ClockW,項目內的文件結構如上圖所示。除了這個.pro文件,還包括一個.h的頭文件,兩個.cpp的源文件,一個.ui的界面文件。Qt程序電子鐘設計綜合實驗—

項目文件這個文件是創建項目時候由軟件自動生成的。第一行表明這個項目使用的模塊。core模塊包含了Qt的核心模塊,gui模塊包含了窗口系統集成、事件處理、OpenGL和OpenGLES集成、2D圖形、基本圖像、字體和文本等功能。第二行添加了widgets模塊,Qtwidgets模塊提供了經典的桌面用戶界面的Ui元素集合,所有Qt界面部件都應該在這個模塊中。第三行表明使用c++11的標準進行編譯。第四行定義編譯選項。第五行是源文件。第六行是頭文件。第七行是界面文件。第八行~第十行指定目標路徑。Qt程序電子鐘設計綜合實驗—頭文件Qt程序電子鐘設計綜合實驗—頭文件Qt程序電子鐘設計綜合實驗—頭文件這個頭文件名字和頭文件的框架可以在新建項目時自動生成,上述代碼非斜體部分語句均為創建項目時自動生成。常量、變量、槽函數以及信號量為用戶自己定義。Qt程序電子鐘設計綜合實驗—頭文件namespace是C++保留字,是一個由程序設計者命名的內存區域。為避免產生命名沖突,將Ui的MainWindow實體放在命名空間里,從而與其他全局實體分割開來。例如,ui->label_mS->setText("00"),該行代碼中的label_mS是QLabel的類對象,前面加上的“ui->”稱為被限定名(qualifiedname)。細心的讀者會發現這個ui不是上文中的Ui。是的,它們之間的關系是:Ui是類,ui是它的對象指針,指向Ui的成員函數MainWindow。本實驗中,所有的拖拽的控件都可由ui指針指向。例如,復位按鍵,它在程序中出現的表示方法是ui->Reset_Button。Qt程序電子鐘設計綜合實驗—頭文件#include<QMainWindow>是包含QMainWindow類的頭文件。#include<QTimer>添加了控件QTimer的頭文件。#include<QDebug>包含QDebug頭文件,為了使用QDebug功能,打印調試語句用。Q_OBJECT是宏定義,程序需要使用信號和槽的時候,必須有這個宏定義,否則不支持信號與槽機制。頭文件定義了四個槽函數和兩個私有成員函數。用signals定義了一個信號量,特別需要說明,signals不屬于public、private和protected中的任何一種,他們之間是平行關系。Qt程序電子鐘設計綜合實驗—main.cppmain函數包含兩個頭文件。main函數開始的部分執行QApplicationa(argc,argv[]),argc是命令行變量的數量,argv是命令行變量的數組,當該語句執行后,應用程序便建立了一個事件循環機制,該機制不斷地從系統的消息隊列中獲取與應用程序有關的消息,并根據事件攜帶的信息將事件發送到目的的窗口或控件。main程序里定義了一個窗口控件w,并引用了w的顯示函數,顯示電子鐘的時間和操作的控件。通過調用QApplication.exec()啟動事件主循環。Qt程序電子鐘設計綜合實驗—mainwindow.cppQt程序電子鐘設計綜合實驗—mainwindow.cppmainWindow的構造器函數,用于項目的初始化。ui->setupUi(this)用于初始化界面。this->setWindowTitle(“可設置電子鐘”)設置窗口的標題欄。flashtimer=newQTimer;是創建的閃爍定時器,這種動態創建定時器的方法要明顯好于靜態定義QTimerflashtimer,因為動態創建的定時器在執行析構函數的時候資源就釋放了。Qt程序電子鐘設計綜合實驗—mainwindow.cppui->label_status->setText("…”)設置電子鐘工作狀態的初始值,大的狀態分,電子鐘可工作在運行狀態和參數修改狀態(參數修改狀態分為修改時、修改分、修改秒),運行狀態分為啟動(停止)、暫停和復位狀態。程序運行后初始處于運行狀態的暫停態。相關的初始變量和輔助變量清零,電子鐘顯示狀態清零。flashtimer->setInterval(500),時間設定時閃爍定時器設為500mS。每500mS定時器產生一次溢出,溢出信號觸發關聯的槽函數,槽函數里閃爍被修改參數。clocktimer->setInterval(Interval)設定為定時時間,最小定時時間可設為1mS;最大是4字節整型數乘以1mS的整數倍,認為是無窮大。Interval被設定為10,意味著顯示器每0.01秒刷新一次。

Qt程序電子鐘設計綜合實驗—InitSignalSlots()Qt程序電子鐘設計綜合實驗—InitSignalSlots()InitSignalSlots()是槽函數初始化,包括7個connect()函數。對信號和槽關聯的處理是本實驗一大特色,包括多個信號對應一個槽函數以及信號傳送參數給槽函數等,將結合相關的程序代碼做詳細論述。MainWindow:~MainWindow(){deleteui;}本實驗的析構函數,~MainWindow()執行以后,釋放相關資源。實際上,析構函數還可以用來執行“用戶希望的最后一次使用對象之后所執行的任何操作”。InitSignalSlots()不是槽函數,是為槽函數服務的初始化函數,包括7個connect函數。1~8的編號是為了敘述問題的方便,實際的代碼不存在上述標號。將1~3放在一組,三個信號關聯到同一個槽函數。原因是這三個信號都和電子鐘的時間(即“時”“分”“秒”)數據有關。便于顯示器QLabel數據處理。做成三個槽函數也不是不可以,但代碼的維護和可讀性不好。flashtimer信號觸發QLabel顯示器數據顯示,clocktimer是電子鐘時間計數器的計時基準。ui->LineEditButton設置數據以及要接收信號的觸發動作。這三個信號關聯同一個槽看似一個很好的解決方案。這里面還有一個問題,觸發信號的參數應該有統一的形式。不用說,前兩個信號無須傳遞參數,不僅如此timeout()是Qt定義好的,就是沒有參數。但是,LineEditButton不傳遞參數就沒法交代了,因為它是數據輸入控件,就是為了傳送數據的。Qt程序電子鐘設計綜合實驗—InitSignalSlots()Qt程序電子鐘設計綜合實驗—SettingHMS()Qt程序電子鐘設計綜合實驗—SettingHMS()這是一個槽函數,Fun_Button單擊,該函數立即執行。FunctionStatus是一個模4的循環計數器,控制電子鐘的模態。QLabel_status用于顯示電子鐘模態,在模態切換中,啟、停相關的定時器。FunctionStatus是類MainWindow的私有變量,在MainWindow類內,FunctionStatus都可以被使用。縱觀整個程序,其余的成員函數和槽函數都是在讀取這個變量,唯獨SettingHMS()槽函數在更改FunctionStatus的值。究其原因,該槽函數的唯一觸發信號Fun_Button功能鍵的clicked()是電子鐘模態改變的源,每單擊一次Fun_Button,電子鐘的模態改變一次。Qt程序電子鐘設計綜合實驗—WriteTextToLabel()Qt程序電子鐘設計綜合實驗—WriteTextToLabel()Qt程序電子鐘設計綜合實驗—WriteTextToLabel()電子鐘設置時間寫入槽函數。程序中用到了電子鐘模態變量,用以區分是對時、分、秒哪一個對象操作。LineEdit回車鍵發出的數據信號,進入Qlabel_response槽函數后發送getText(QString)信號,觸發WriteTextToLabel(constQString&string)槽函數。函數參數是QString&string。string.toInt()函數是將QString類型的字符串轉換成整型數,進行限幅處理。函數負責對相關變量的修改和狀態顯示的更新。Qlabel_response()Qt程序電子鐘設計綜合實驗—Qlabel_response()Qt程序電子鐘設計綜合實驗—Qlabel_response()Qt程序電子鐘設計綜合實驗—Qlabel_response()槽函數Qlabel_response()是電子鐘核心模塊,也是電子鐘最難的部分。槽函數首先要區分信號源從哪里來?使用QTimer*SignalSource=qobject_cast<QTimer*>sender()對發送信號進行類型轉換,使用QTimer*指針指向它。判斷是不是QTimer類?若是再判斷是哪個定時器發出來的?確定了信號源后再做相應的處理。如若不是定時器發出來的信號,那就執行QLineEdit*LineEdit=qobject_cast<QLineEdit*>sender(),將指針指向QLineEdit,判斷信號是由對象LineEditButton發出。槽函數解決了對相同類型的不同對象以及不同類型控制的甄別,在實際的項目使用中具有應用價值。Qt程序電子鐘設計綜合實驗—Qlabel_response()對10mS定時器的代碼分析如下。每進一次槽函數,執行一次+1的操作,10mS是電子鐘定時計數器的最小計數單位。“時”“分”“秒”和“10mS”各自都有自己的權,+1的操作是整型數的行為,顯示的數據是QSring數據類型。于是,在運算環節,運算量統統轉換為整數,時間的顯示和變量的保存再轉換到QString類型。函數QString:number(total_minute)和函數S_minuteSetting.toInt()完成整型數到字符串以及字符串到整型數數據類型的轉換。總之,相關代碼完成計時操作以及數據類型轉換。Qt程序電子鐘設計綜合實驗—Qlabel_response()Qt程序電子鐘設計綜合實驗—Qlabel_response()對500mS定時器的代碼分析如下。定時時間到切換閃爍flashFlag的標志位。這是一個布爾量,取反即可。標志位為1時,顯示數據。標志位為0時,關顯示(也稱消隱),利用定時器周期性改變標志位,就可見被修改數據在閃爍。變量FunctionStatus控制到底是時、分還是秒被修改,前文已述。用于顯示時、分、秒的幾個QLabel類對象分別是label_hour、label_second和label_minute。setText(…)括號內的值,要么是雙引號內的字符串,要么是QString變量。需要強調的是QString使用unicoder編碼,支持漢字輸入,譬如setText(“顯示秒”)。對于QLineEdit代碼分析如下。發射帶QString類型的參數的信號,清零LineEditButton對話框內的數值。Qt程序電子鐘設計綜合實驗—KeysManagement()Qt程序電子鐘設計綜合實驗—KeysManagement()Qt程序電子鐘設計綜合實驗—KeysManagement()這是一個槽函數,關聯了三個QPushButton類的三個按鈕:啟動(停止)、復位、暫停。槽函數用于響應三個按鈕。設計這三個信號和同一個槽關聯,原因是它們是相關聯操作,由這些操作決定在電子鐘運行的模態下是運行、停止、暫停,還是復位狀態。頭文件中定義了三個constint的常量STOP、RUN和PAUSE,一個int型的變量state用來表示電子鐘在非參數設定模態下的子狀態。啟動按鈕是啟動、停止操作,啟動狀態時按啟動執行停止,停止狀態時按啟動執行啟動。啟動態開始計時,停止態時間自動清零。暫停鈕在停止態不起作用,在啟動態使電子鐘暫停,暫停時保持數據不變。在暫停態再按暫停按鍵,電子鐘繼續計數。不管在何種狀態復位按鍵使電子鐘進入停止態,同時電子鐘的計時時間清零。Qt程序電子鐘設計綜合實驗—KeysManagement()文中出現了對定時器的啟動、停止操作。GTimer是Qt的類,在控制類代碼中定時器是必不可少的控件。前文講過,使用newQTimer創建定時器,本實驗是兩個定時器。在構造函數中使用諸如clocktimer->setInterval(Interval)設置定時器溢出時間,溢出時產生的信號是QTimer::timeout(),常常用connect函數將溢出信號關聯一個槽函數,在槽函數里處理溢出時間。這是Qt的一大貢獻,通過connect,關聯信號和槽函數。GTimer還有兩個重要的函數:start()和stop(),作用是啟動和關閉定時器。例如clocktimer->start()啟動電子鐘定時器。GTimer類是電子鐘的心臟,是時鐘節拍,是不可或缺的控件。Qt程序電子鐘設計綜合實驗—ResetDisplay()為了敘述項目的完整,展示上述代碼。這是一個成員函數。目的是復位QLabel顯示器,包括變量清零以及setText()函數的賦值。Qt程序電子鐘設計綜合實驗—運行結果展示至此,電子鐘工程的全部程序介紹完畢。電子鐘啟動后運行的效果如上圖所示。本實驗看起來并不像一個成熟的現代GUI應用程序,但它使用多種用于更復雜應用程序的基本技術,包括:GTimer類、信號和槽、QPushButton、QLabel和QLineEdit。對剛入門的初學者和以后從事更為復雜的圖形用戶界面應用程序開發的程序員都有一定幫助。提綱Qt編程基礎圖形界面設計信號和槽機制Qt程序綜合實驗—電子鐘設計Qt開發環境的搭建Qt開發環境的搭建隨著嵌入式技術的發展,Qt的使用越來越多。對Qt較為常見的描述是跨平臺C++圖形用戶界面應用程序開發框架。Qt可用于Windows桌面系統,被嵌入在VisualStudio開發環境里。Qt可用于臺式機的桌面Linux,也可以用于嵌入式的Linux。用于Linux開發的環境常常使用QtCreator,這是一個輕量級的QtIDE。針對桌面Linux和嵌入式Linux,QtCreator使用編譯器和交叉編譯器分別對它們進行編譯。本書桌面Linux是宿主機,虛擬機的版本是VMwareWorkstationPro的15.x,虛擬機使用的Linux是Ubuntu18.04,安裝Qt版本是5.12.8,QtCreator的版本是4.11.2。嵌入式平臺實驗箱(以后簡稱平臺)為博創智聯科技有限公司設計制造。平臺內預裝的Qt版本是5.3.2,Qt被封裝在QtCreator內,QtCreator的版本是4.11.2。可以看到,宿主機和平臺使用的QtCreator是同一軟件,這樣在調試的時候可以任意切換在宿主機上操作或是在平臺上操作。QtCreator的IDE是一個編程、配置、調試的集成桌面環境。整個開發的流程大多在可視化界面下進行,有一些命令行操作,但不是太多。設置交叉編譯環境打開VMwareWorkstationPro,在開啟虛擬機之前,在設備一欄,單擊網絡適配器。出現下圖界面選擇橋接模式(B):直接連接網絡網絡。

橋接和NAT模式選擇同時,在復制物理網絡連接狀態前面的方框勾選。手動輸入IP手動選擇IP如圖11.10所示。開啟此虛擬機,虛擬機的右上角有幾個圖標單擊那個三角符號→有線連接→有線設置→IPV4選手動,IP地址設為2,子網掩碼設為,網關為空,DNS為空,路由為空。在終端執行ifconfig命令,查看虛擬機IP地址。可見,IP地址為2。在電腦的開始運行部分輸入\\2,進入Samba共享文件夾。將光盤資料SRC目錄下面的fsl-6dl-source.tar.bz2壓縮包復制到Samba共享目錄如下圖所示。

光盤拷入虛擬機的文件然后在ubun

溫馨提示

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

評論

0/150

提交評論