Qt5.9.2+VS2017入門例項——透徹解析
前言:
由於現在書上介紹的大部分都是Qt Creator,並沒有介紹Qt+VS的教程,雖然說很相似,但是也有很多地方不同,對於初學者特別是那些槽和訊號的連線非常的亂,而且幾種檔案也傻傻分不清,這個例項就帶你理清Qt+VS的創作過程,保證你可以舉一反三,會用一些簡單控制元件的新增與事件的觸發。
不知道讀者是否寫過C#的WinForm或者Android介面的開發,在我看來,無論是Qt還是WinForm或者是Android介面的開發,核心都是一樣的,拿個最簡單的例子來說,比如一個Button(按鈕)和一個Label(標籤),最簡單的例子莫過於,點選Button之後,Label上顯示“HelloWorld!”
這是最簡單的,也是最有精華的地方,為什麼點選一個Button,label上面的字就會發生變化,自然會想到,在程式裡面是這樣實現的,當我點選Button的時候,下面會執行某件事,這個事就是Label的字發生改變,這裡需要注意的是“當我點選Button的時候”這句話,這句話實現的時候是一個動作,是一個很具體的動作,這個動作在C#的桌面開發中叫做“事件”,當事件發生時,會執行某件事。C#裡面是這樣實現的:
private void button1_Click(object sender, EventArgs e) { label1.Text = "HelloWorld!"; }
剛才所說的“當我點選Button的時候”這句話,就是通過private void button1_Click(object sender, EventArgs e)這一行程式碼實現的,是不是很簡單,你想在點選Button後發生什麼事,就在大括號裡面寫什麼事就好了,更簡單的事也是和Qt還有Android最有區別的事就是——
private void button1_Click(object sender, EventArgs e)
{
}
上面的這幾行在C#中是不需要自己寫的,只要雙擊佈局上面的Button,就會在程式碼區域生成這一行程式碼,但是Qt裡面都需要我們手動完成這個方法的實現
簡單來說就是Qt要完成這樣一個簡單的private void button1_Click(object sender, EventArgs e)方法,需要自己手動補全,補全的方式也有點不同,需要兩個步驟,一是需要定義button1_Click()函式(Qt裡面叫槽——實現動作的函式),二是需要連線訊號與槽的關係(Button發出Click訊號,button_Click()函式完成click之後的任務)——紅的是訊號,綠的是槽。
如果你還不懂的話,接下來就是一個Qt簡單的例子,你做完之後,再與我上面所寫的對應一下就懂了。
______________________________________________________________________________________________________________________________________
正文:
在完成例子之前我先說一下,本例子是用Qt設計師設計介面,不像其他地方直接用程式碼實現介面的設計。
案例說明:
1.勾選CheckBox可以改變LineEdit裡面的文字屬性,是隻讀還是加密顯示。
2.點選輸入按鈕可以將LinEdit裡面的文字顯示在TextLabel裡面。
1.建立新的專案如下圖:
2.解決方案中的檔案簡單介紹:
(1),是Qt設計師檔案,雙擊可以開啟Qt視覺化設計
(2),Qt介面的程式碼檔案,Qt設計師設計的介面以程式碼的形式儲存在這裡,比如Button的位置,大小,名字
(3),Widget類的標頭檔案,定義一些欄位和函式宣告,包括最重要的slots(槽)函式的宣告,以及介面ui控制代碼,以便通過“ui.***”的方式訪問到介面的各個控制元件,比如訪問介面的Label控制元件裡的文字可以這樣:ui.label->text();就是字面意思,很容易理解。
(4),資原始檔,相當於AndroidStudio裡面的rcs資料夾,裡面存放需要用到的.ico圖示或者圖片。
(5),主函式檔案,程式的入口,不必解釋,其實一般不會在這個裡面修改什麼。
(6),Widget類完成的主要檔案,在widget.h裡面定義之後的欄位以及函式宣告,以及槽的實現,都是在這裡,Qt的邏輯功能設計主要是修改這個檔案。
3.設計介面——拖放控制元件
雙擊步驟2中的檔案1(widget.h檔案),開啟Qt設計師,在設計師的左邊控制元件區域找到下面幾個控制元件:
1. Check Box(2個)
2.PushButon
3. LineEdit
4.TextLabel
左鍵按下拖動到介面上,佈局如圖所示,雙擊介面上的控制元件,改變他們顯示的名字,(控制元件有兩個名字:1,顯示時的名字(text),2,設計時需要呼叫它時的名字(objectName),一般是英文和數字組合),同時注意他們的objectName(在右邊屬性一欄)。
4.按照前言所敘述的,1,新增事件發現的函式——槽函式。2.連線訊號與槽.
(4.1)新增事件發現的函式——槽函式
解析:因為我們有三個動作(事件),其中有一個是按鈕按下的動作(事件),還有兩個分別是兩個CheckBox勾選後的動作(事件),這些動作發生之後都要執行相對應的任務。所以先新增這些事件函式,slots是槽的意思,在widget.h檔案中新增。
#pragma once
#include <QtWidgets/QWidget>
#include "ui_widget.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = Q_NULLPTR);
private:
Ui::WidgetClass ui;
private slots:
void on_checkBox_clicked();
void on_checkBox_2_clicked();
void on_pushButton_clicked();//這些如果是這種形式的訊號定義,則不需要寫connect函式,其實也不用在設計師中連線訊號與槽
//如果不是這樣定義的就必須寫connect,可以通過在設計師中連線訊號與槽自動生成connect
}
粗體是新增的部分,需要注意的是這些函式是有命名規則的,"on_"後面是控制元件的設計名字(objectName,步驟三中,紅色字型部分),然後後面是“_clicked()”,你在設計的時候最好遵循這種命名格式,這樣你就可以省掉4.2的步驟(2.連線訊號與槽.),也就是說,你如果遵循這個命名格式的話你就不用寫connect()函數了,因為這種定義讓系統能夠自動識別訊號與槽的連線,不用再寫connect()函式,一箭雙鵰。可以直接到第5步,但是如果系統比較複雜,並不是所有的都可以這樣命名的時候,你就要用到4.2的步驟了。
(4.2)連線訊號與槽
如果你在4.1中沒有按照命名規則來命名槽函式,那麼就要進行訊號與槽的連線,所謂訊號與槽的連線就是,一個訊號send出來,要有一個槽接收這個訊號,然後執行相應任務,這個過程需要連線的,如果不設計這個連線,即使Button send出一個click訊號,也沒有什麼東西去執行click後的任務(其實這個和C#中的事件註冊是一樣的,只不過C#中的事件註冊系統在我們雙擊Button的時候幫我們自動完成了)。怎麼進行連線呢,在widget.cpp裡新增:
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
connect(ui.checkBox,SIGNAL(clicked()),this,SLOT(on_checkBox_clicked()));
connect(ui.checkBox_2, SIGNAL(clicked()), this, SLOT(on_checkBox_2_clicked()));
connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(on_pushButton_clicked()));
}
可以很容易看出,ui中的checkBox發出一個clicked()的訊號,on_checkBox_clicked()槽函式去接收它,在這裡我用的是正規的命名規則,其實是不需要寫connect()函式的。
必殺技:
必殺技終於來了,有沒有感覺這樣手動寫connect()函式很蛋疼,寫完一個槽函式也就算了,還要我自己寫訊號與槽的連線,如果多的話,我豈不一個個寫要累死,所有用到了Qt設計師的時候到了:
(4.2.1),雙擊widget.ui檔案開啟設計師,如下步驟進行:
如上圖,點選1處的訊號與槽按鈕,然後先為“只讀”checkbox新增訊號與槽的連線,方法就是滑鼠左鍵拖動“只讀”按鈕到空白區域,鬆開滑鼠會彈出訊號與槽的對話方塊,如下圖:
如上圖:首先選擇2處的訊號(clicked(),對應步驟4.2的手動寫connect()就可以明白),然後點選3處的編輯以便新增槽,如下圖:
如上圖:點選1處的加號,會在2處出現slot1(),這個是預設的讓你新增槽的,所以把slot1(),改成你自己需要的槽,“只讀”check Box對應的槽應該是on_checkBox_clicked(),(注意這裡我用的也是正規命名規則,正規命名規則是不需要新增槽和訊號的連線的,我這裡只是做師範用),新增之後點選下面的ok,然後進行下一步:
如上圖:你就可以按鈕新增的訊號與槽的連線了,clicked()是訊號,on_checkBox_clicked()是槽,接下來按照步驟4.2的程式碼進行其他兩個的訊號與槽的連線就可以了。
5.widegt.cpp的修改——槽函式的任務執行
如果你是從4.1還是4.2過來的,都需要看這一步,這一步也是最重要的一步,也就是點選按鈕之後,功能的實現,現在只剩下如何完成點選之後的功能了,所以要補全槽函式的內部,你要知道,我們在4.1中新增的槽函式是在widget.h這個標頭檔案中新增的,這個叫做宣告,所有我們要補全它,當然是在其對應的widget.cpp檔案中補全,可能會遇到一些問題,請參考下面的“補充”解決,程式碼如下:
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
void Widget::on_checkBox_clicked()
{
if (ui.checkBox->isChecked())
{
ui.lineEdit->setReadOnly(true);
}
else
{
ui.lineEdit->setReadOnly(false);
}
}
void Widget::on_checkBox_2_clicked()
{
if (ui.checkBox_2->isChecked())
{
ui.lineEdit->setEchoMode(QLineEdit::Password);
}
else
{
ui.lineEdit->setEchoMode(QLineEdit::Normal);
}
}
void Widget::on_pushButton_clicked()
{
ui.label->setText(ui.lineEdit->text());
}
粗體部分是新增的程式碼,這些程式碼根據字面意思都很好理解,我就解釋一個吧:
首先要包括widget.h這個標頭檔案,因為這裡用到的函式與控制代碼都是在widget.h裡定義的,其中有一個ui控制代碼,就是在指整個介面,你可以通過則個ui訪問介面上的控制元件(可能會出現ui_widget.h找不到或打不開問題,看下面的補充),解釋一下第一個槽函式裡的內容:
ui.checkBox->isChecked():指的是ui介面上的checkBox控制元件被勾選,返回的是一個bool型,很容易理解,被勾選就是true,否則就是false.
然後看裡面的ui.lineEdit->setReadOnly(true):ui介面上的lineEdit控制元件設定成只讀屬性,或者不是隻讀屬性。就這麼簡單。
6,驗證設計師為我們完成的訊號與槽的連線
其實設計師中完成的訊號與槽的連線也是通過程式碼實現的,只是我們通過對話方塊自己新增的時候,程式碼已經默默的生成connect()函數了,不行的話你可以到ui_widget.h檔案裡面找到 retranslateUi(WidgetClass);下面的程式碼是不是connect()函式,哈哈,是的!本例程全部程式碼在這裡。
總結:
通過這麼長的部落格不知道你明白了沒有,就是這麼簡單,可能你覺得我說的過於簡單,那是因為我在學之前真的希望有這樣的一個教程,但是沒有找到,找到的都是QtCreator,還有各種檔案改程式碼,由於剛接觸真的不知道各個檔案的關係,所有很亂。通過這個教程你就能完成基本的控制元件操作了,其實我說的這些步驟你如果懂得的話,其他的一些控制元件就不在話下,無非是功能的變相實現,用到哪個查哪個功能就行,不必再糾結哪個檔案該不該改程式碼,哪個槽該不該連線訊號。
謝謝大家!我的表演結束!
補充:
可能在你修改widget.cpp檔案時就會發現ui_widget.h檔案打不開,無法用到輸入提示(比如你在widget.cpp檔案中輸出“ui.”的時候後面不會出現提示的單詞,那是因為你的ui_widget.h檔案沒有被識別),你可以將ui_widget.h檔案右鍵->移除,然後重新新增就可以了!