學習目標
- 了解 qt 的基本信息
- 了解 qt 的下載及安裝
- 了解創建一個基本 qt 項目的流程
- 了解信號與槽
- 通過示例了解信號與槽的設置與編寫
- 了解控件添加的方式
- 了解控件如何使用代碼獲取其文本
- 了解控件如何使用代碼設置其文本
- 使用 connect 自定義信號與槽
- 了解使用樣式修飾控件外觀
- 了解使用代碼清空控件文本
- 學習使用Qt 編寫一個四則算術計算器
注:本章中使用的一些方法方法是為了簡單的了解一下概念性質,例如在多個槽函數時使用的方法并不是簡便的,簡便的方法在之后的學習中將會進行講解。
一、簡單了解 Qt 及下載安裝
1.1 簡單了解 Qt
qt 是 C++ 的圖形用戶工具,是一個跨平臺的用戶界面解決方案;Qt 幾乎支持所有的系統平臺,并且是面向對象的。
Qt 的跨平臺是非常強大的,例如可支持 win下的 XP、Vista、Win7/8/10 等 Windows 系統,并且對于Linux 下 X11、HP-UX、BSD/OS 又或是 嵌入式 Linux 平臺 等都是支持的,甚至是 Mac 平臺也支持。
1.2 Qt 下載及安裝
Qt 分為商業版以及開源版,在此我們使用開源版本,開源版本是免費的。
Qt 開源版本的下載鏈接為 https://www.qt.io/download,打開鏈接中,往下滑動頁面,找到開源版本下載板塊:
點擊后,將會跳轉到一個頁面,往下拉頁面,點擊下載 qt 二進制在線安裝:
之后將會跳轉到一個頁面,并且會根據你的系統推薦你使用某個版本:
最后點擊 Download 即可下載,安裝步驟操作簡單不再贅述,以上介紹開源版下載方式是因為部分同學認為Qt 是收費的,所以在此介紹開源版的下載方法(可能由于時間問題網頁更新會導致下載“路徑”不同)。
1.3 項目示例
Qt 作為一款優秀的 GUI 解決方案許多經典流行的應用使用了 Qt 進行開發,例如 WPS:
谷歌地球:
VirtualBox 虛擬機:
Linux 桌面系統等。
二、Qt Creator 界面介紹 及 第一個Qt 程序創建
2.1 簡單的第一個 qt 程序
Qt 界面中自帶了很多項目示例,可以通過 查看 Qt 示例學習經典項目的開發:
Qt 自帶了教程,查看教程可以觀看資料,不過是英文的,有英文能力的同學推薦閱讀:
點擊創建項目將會彈出一個窗口,選擇對應的模板將會可以創建不同的項目:
在以上所選擇的模板中最右側是對應的模板介紹:
該模板是創建一個桌面 Qt 程序,以及包含了一個用于設計的 Qt 窗口。
點擊選擇可以進入下一步,在下一步窗口中選擇項目名稱以及對應項目存放的位置:
在此需要注意,名稱和路徑不能有中文,接著一直下一步,知道出現語言選擇時在此你可以選擇中文:
接著一直下一步進行操作即可,完成后將會彈出所創建的項目的基本內容:
接著,點擊運行將會出現一個 空窗口:
三、信號與槽
3.1 信號與槽的基本示例
信號在 Qt 中指的是一個事件,例如當你點擊一個按鈕時會觸發點擊的事件,也就是信號,觸發完畢后你需要某一個“動作”對其作出響應,或者說當收到信號后將會執行一些動作,而這個動作則是槽,又或者說是一個對信號響應的代碼塊。
此時我們可以通過一個例子來簡單的理解一下信號與槽的概念,點擊創建項目,最后創建一個 Qt Widgets 的 App 應用:
隨后指定文件目錄后一直點擊下一步即可:
接下來點擊 mainwindow.ui 文件:
點擊之后將會出現一個設計窗口:
這個窗口如圖所示,左側是對應的基本空間區域,右側是對應的設計窗口。我們可以通過拖拽左側的控件到右側的設計窗口之上,使當前 window 添加對應的控件,例如:
此時可以點擊整個 Qt creator 左下角的運行按鈕對整個項目編譯運行:
運行之后,將會出現一個窗體程序,這個窗體程序在界面之上有一個 pushbutton:
為了實現信號與槽這個概念,我們可以再拖拽一個 edit 控件到窗體之上,由于一個 edit 是一個可編輯的控件,那么必然是輸入 input Widgets,我們在 input Widgets 控件之下可以找到對應的 line Edit:
此時拖拽這個控件到窗體之上:
接著我們開始試驗信號與槽。我們右鍵 PushButton,將會出現跳轉到槽的選擇項:
此時將會出現一個信號選擇框,我們可以選擇在什么情況下觸發這個槽函數:
在這里選擇 clicked 指在點擊時觸發這個槽函數。選擇完畢后, qt creator 將會跳轉窗口到一個編輯頁,此時編輯頁中出現的 on_pushButton_clicked 則是點擊 pushButton 按鈕后將會跳轉到的槽函數:
那此時我們該在這里編寫什么代碼呢?此時我們可以編寫一些動作,例如直接將當前按鈕的文本改變成 lineEdit 空間所輸入的文本,那么就可以很好的演示當點擊按鈕后執行代碼后界面所產生的反應。
此時我們可以編寫代碼:
void MainWindow::on_pushButton_clicked(){QString inputText=ui->lineEdit->text();ui->pushButton->setText(inputText);
}
其中 QString inputText=ui->lineEdit->text();
表示新建一個 QString 類型的 inputText 變量用來獲取對應輸入框所輸入的內容;獲取輸入框需要指定到窗口上的某個空間,我們需要通過 ui 進行獲取,ui-> 指 ui 上的某個空間,由于在窗體上的輸入框名稱默認為 lineEdit 所以直接寫成 lineEdit 即可,查看 控件名稱 直接點擊控件后可在 Qt creator 右上角進行查看:
此時代碼為 ui->lineEdit
表示指定到了某個元素,而最后的 ->text()
則表示獲取當前控件的文本內容,獲取到文本內容后存儲到 QString 類型的 inputText 變量即可。
此時已經獲取到了對應的輸入框內容,那么接下來需要把對應輸入框的文本設置到 pushButton 之上即可,設置一個控件的文本也需要使用 ui 指定到某一個控件,那么獲取 PushButton 控件代碼則是 ui->pushButton
,那么設置文本則是 setText 方法,在 setText 方法中傳入對應的文本值即可,所以最終代碼寫成 ui->pushButton->setText(inputText);
,當然你可以直接寫成 ui->pushButton->setText(ui->lineEdit->text());
。
此時完成了代碼編寫后,我們可以運行程序,運行成功將會出現一個窗體界面,此時在窗體界面中輸入 233:
接著點擊 PushButton 按鈕,點擊后 PushButton 按鈕的文本將會改變成你所輸入的值:
3.2 自定義信號與槽
信號與槽不止可以通過默認方式進行生成和編寫,還可以通過自定義的方式自定義信號與指定處理的槽函數。
我們自定義的信號與槽是通過 connect 函數進行設置,例如如下代碼:
connect(ui->lineEdit,SIGNAL(returnPressed()),this,SLOT(on_pushButton_clicked()));
以上代碼中 connect 函數接收的第一參數為你需要指定信號與槽的控件,第二個參數則是表示發送什么信號,就像我們在設計窗口中右鍵某一個控件,隨后通過鼠標點擊指定對應的信號;在這里 SIGNAL(returnPressed())
中 SIGNAL 表示是一個宏函數,需要傳入對應的事件,其 returnPressed 則表示是 enter 按下確認的事件,接下來的 this 則是表示當前類處理這個信號,最后一個則是槽,SLOT 需要傳入對應處理信號的函數即可。
由于自定義信號與槽的方式有很多種,在這里先簡單講解一種,之后其他的處理方式將會補充講解。
最后我們點擊運行,隨后在 lineEdit 中輸入對應的文本,enter 鍵后按鈕也會發生其文本的改變:
四、實現簡單四則計算器
4.1 界面設計
在這一節中,我們使用 qt 制作一個簡單的四則運算器,學習一下界面創建與修飾。
首先創建好項目,其次打開 ui 文件,進入到設計窗口之中:
在一個計算機中,數字的按鍵是必不可少的,我們拖動對應的按鈕到設計窗口之上,最后點擊按鈕,在右下角的屬性設置之上改變其寬高:
接著我們更改文本后,按住鍵盤 ctrl 拖動控件,將會直接復制出一個新的控件:
接著我們拖動出多個對應的按鈕,并且更改其文本:
此時我們發現這些按鈕的排列并不整齊,我們可以選中所有的按鈕,接著點擊設計窗口頂部的柵格布局:
點擊之后整個按鈕將會自動進行規整的排列。
接著,我們點擊右上角,給每一個按鈕起名,方便我們接下來的調用:
接著我們添加兩個 eidt 到窗口之上,并且設置號大小和位置:
當然也要更好對應的控件名,一個用于顯示公式,還有一個用于顯示最終的計算結果:
接著設置整個窗體大小的寬高:
設置完畢后我們可以給這些控件對應的樣式。
4.2 添加樣式
首先我們可以給這些控件設置邊框為 none 去掉對應的邊框,主要是把 edit 的邊框去掉使其較為美觀。右鍵在右上角的對象樹上,選擇改變樣式:
接著在彈出來的樣式表上添加樣式修飾:
*{border:none;background-color: rgb(234, 234, 234);
}
其中 * 表示給所有的對象設置樣式,其樣式編寫在 * 之后的花括號之中,border 設置為 none 表示邊框為 none 則表示不需要邊框,background-color 表示設置對應的背景色,用 rgb 色進行設置。輸入完畢后點擊應用,當前的窗體如下:
接著我們可以設置對應的 按鈕樣式,例如設置 QPushButton 的背景色以及對應的字體大小、是否加粗以及字體,可以使用以下樣式:
QPushButton{background-color: rgb(255, 255, 255);font:bold 11pt '微軟雅黑';
}
其 font:bold 11pt '微軟雅黑';
表示設置字體,bold 表示字體加粗,11pt 表示字體的大小、最后則是對應的字體。
若此時我想對應的設置乘號、除號、加號、減號這些運算符號的不同,則可以通過樣式指定控件設置不一樣的樣式,例如:
QPushButton#add,#subtraction,#division,#multiplication{background-color: rgb(56, 208, 203);
}
此時設置樣式則需要先指定某個類型的組件,隨后使用 # 在末尾街上控件名稱,隨后逗號分隔即可指定某個控件設置樣式。
此時運行程序,我們發現鼠標移動到某個按鈕上時沒有任何反應,若想使按鈕有反應則需要對應的設置 hover 時按鈕的樣式,hover 則是指對應的鼠標懸浮上去后,按鈕發生的改變,設置這個樣式很簡單,只需要指定某個類型的控件后,在其后使用一個冒號 :hover 即可指定一個樣式,例如:
QPushButton:hover{background-color: rgb(221, 221, 221);border:1px solid rgb(185, 185, 185);
}
此樣式表示當鼠標移動上去后改變其對應的背景色以及邊框顏色,此時鼠標移動上去將會使按鈕有反應,并不會過于死板。
此時效果如下:
但此時我們發現,設置過指定控件的樣式例如加減乘除并沒有移動上去后發生樣式改變,這時需要再針對這些控件設置一下 hover 樣式:
QPushButton#add:hover,#subtraction:hover,#division:hover,#multiplication:hover{background-color: rgb(221, 221, 221);border:1px solid rgb(185, 185, 185);
}
效果如下:
4.3 功能設計
設計功能我們需要設置一個全局變量用于記錄通過按鈕生成的四則運算公式,在此我們設置在頭文件之中:
接著我們給每個按鈕手動設置一個槽函數:
首先我們設置數字 7 按鈕的槽函數:
void MainWindow::on_btn7_clicked()
{expression+="7";ui->show->setText(expression);
}
在這個槽函數中設置 expression 全局變量記錄用戶輸入了7,隨后設置 show edit 的文本為 expression;既然 expression 是用于對應的記錄公式,那么我們就可以把所有的數字都設置類似于數字 7 的形式往 expression 中添加對應的拼接,并且加減乘除法按鈕也要完成該操作:
最后運行一下程序,發現輸入點擊對應按鈕后將會出現對應的公式:
但是我們發現由于是 eidt 對象,可以用戶輸入,我們可以設置其 edit 的屬性 readonly 為 true 即可:
也可以設置對應的水平對齊為右:
最后我們得到了這個公式,我們只需要通過計算器代碼即可求出對應值,由于這是 C/C++ 的內容在此就不再贅述,我們此時直接右鍵等于號,設置其槽函數,并且賦值以下代碼即可(代碼來源于網絡):
QStack <int> OPND; // Operand stackQStack <char> OPTR; // Operator stackOPTR.push('#');//char ss[2]="#";//尾部有\0char s[maxn];char path[50];QString str = expression;QByteArray ba = str.toLocal8Bit();memcpy(s,ba.data(),ba.size()+1);//加1是為了最后的終結符,否則轉換回來的時候不知道什么時候截止QString str2;str2 = QString::fromLocal8Bit(s);strcat(s,ss);// 運算式尾部加 "#"--結束運算符char c=s[0];int k=1;while(c!='#'||OPTR.top()!='#'){ //表達式未讀完或者運算未完int y=0;if(c>='0'&&c<='9'){while(c>='0'&&c<='9'){ // 讀入連續的數字y=y*10+(c-'0');c=s[k++];}OPND.push(y); // 把讀進的數字入數字棧}else{switch(Procede(OPTR.top(),c)){case'<': //棧頂元素優先權低OPTR.push(c);c=s[k++];break;case'=':OPTR.pop(); // 脫括號c=s[k++]; // 讀入下一個字符break;case'>': //退棧并將運算結果入棧char x=OPTR.top();OPTR.pop();int m=OPND.top();OPND.pop();int n=OPND.top();OPND.pop();OPND.push(Operate(m,n,x));break;}}}ui->res->setText(QString::number(OPND.top()));
當然,你直接復制這個代碼將會報錯,此時需要再復制幾個函數以及添加頭文件,先復制幾個函數:
const int maxn=110;
char priority[7][7]={{'>','>','<','<','<','>','>'},{'>','>','<','<','<','>','>'},{'>','>','>','>','<','>','>'},{'>','>','>','>','<','>','>'},{'<','<','<','<','<','=','0'}, // 此行"("=")"表示左右括號相遇,括號內運算已完成{'>','>','>','>','0','>','>'},{'<','<','<','<','<','0','='} // "=" 表示整個表達式求值完畢}; // "0"表示不可能出現這種情況 ( 語法錯誤 )//Precede 用于判斷運算符棧棧頂運算符 a1 與讀入運算符 a2 之間的優先關系函數
char Procede(char a,char b){ // 建立 pre[][] 到 運算符間的映射關系int i,j;switch(a){case'+':i=0;break;case'-':i=1;break;case'*':i=2;break;case'/':i=3;break;case'(':i=4;break;case')':i=5;break;case'#':i=6;break; // # 是表達式的結束符}switch(b){case'+':j=0;break;case'-':j=1;break;case'*':j=2;break;case'/':j=3;break;case'(':j=4;break;case')':j=5;break;case'#':j=6;break;}return priority[i][j];
}int Operate(int m,int n,char x){if(x=='+')return m+n;if(x=='-')return n-m;if(x=='*')return m*n;if(x=='/')return n/m;
}
隨后需要對應的添加一個頭文件 QStack:
#include <QStack>
最后若你的命名跟我的不符,你需要修改字符串轉字符數組時的公式變量命名:
以及最后顯示值時指定改變某個控件:
最終結果如下:
總結
本章節主要介紹了 qt 的一些基本信息,并且使用 qt 創建一個基本的項目,了解 qt 項目創建的基本流程;在此基礎上學習了信號與槽,并且使用了對應的小示例改變了按鈕的文本,在基礎信號與槽的基礎上,通過 connect 實現了自定義的信號與槽指定,完成了使用鍵盤響應對應的槽函數;最后通過學習如何制作一個簡單的四則運算程序,在其中了解了 UI 界面的布局制作、限制其大小、以及設置對應的樣式,最終也實現了對應的按鈕及計算。