提示:本博客作為學習筆記,有錯誤的地方希望指正,此文可能會比較長,作為學習筆記的積累,希望對來著有幫助。
緒論:筆者這里使用的是和C++來實現一個簡單的串口上位機的開發的簡單過程,使用到C++,主要是為了后面使用開發上位機打下基礎。這里主要分為初識C++的一些基本知識,其次是QT 的使用。特別聲明感謝【北京迅為】嵌入式學習之QT學習篇的學習視頻,這里的學習筆記就是根據視頻中的內容實戰記錄下來的。B站演示視頻
文章目錄
一、C++知識 1、初識C++
什么是C++,C++就是C語言的升級版本,C++面向對象,而C是面向過程的一種語言,是一種高級語言。
2、C++輸入輸出控制
C++中使用cout 作為輸出控制,使用cin作為輸入控制,相比C語言更加靈活和方便。
2.1、C++的輸出控制cout
在C++中使用的是cout來控制輸出的,與c中的不同的是cout可以實現數據類型的相應調整行為,使用的輸出需要時候需要使用輸出控制符%d,%c,%u等等的方式,但是C++中使用cout不需要使用輸出控制符。需要包含# 的頭文件
因為cout是std庫中的一個類的對象,所以使用的方法是 std::cout ,如下
例如:cout << "Hello World!" << endl;
2.2、C++的輸入控制cin
cin是C++編程語言中的標準輸入流對象,即類的對象。cin主要用于從標準輸入讀取數據,這里的標準輸入,指的是終端的鍵盤。此外,cout是流的對象,即類的對象,cerr是標準錯誤輸出流的對象,也是 類的對象。這里的標準輸出指的是終端鍵盤,標準錯誤輸出指的是終端的屏幕。
在理解cin功能時,不得不提標準輸入緩沖區。當我們從鍵盤輸入字符串的時候需要敲一下回車鍵才能夠將這個字符串送入到緩沖區中,那么敲入的這個回車鍵(\r)會被轉換為一個換行符\n,這個換行符\n也會被存儲在cin的緩沖區中并且被當成一個字符來計算!比如我們在鍵盤上敲下了這個字符串,然后敲一下回車鍵(\r)將這個字符串送入了緩沖區中,那么此時緩沖區中的字節個數是7 ,而不是6。
cin讀取數據也是從緩沖區中獲取數據,緩沖區為空時,cin的成員函數會阻塞等待數據的到來,一旦緩沖區中有數據,就觸發cin的成員函數去讀取數據。
使用cin從標準輸入讀取數據時,通常用到的方法有cin>>,cin.get,cin.。
3、C++對象和類
其中C++的靈魂在于C++的類,類的關鍵字是使用class處理,在類中包含的是成員變量, C++的類和C語言中的結構體有點相像,類中的成員變量就有點類似C中結構體的成員變量,類中的成員變量不僅是變量還可以是函數,對象就是類的實例化。類似于定義結構體變量。
一個簡單的C++類例子:
class student
{
public: //類的公共變量
student(); //構造函數,對象實例化(創建)的時候調用
student(int a); //構造函數的重載函數
~student(); //析構函數,對象刪除的時候調用
char name[10];
int age; //類的成員變量
void Test1(void){ //在類中聲明和實現函數
cout<<"My name is Test1"<<endl;
};
void Test1(int a); //類函數的重載特性
void Test2(); //在外部實現類的函數
virtual void Test_Virtual(); //虛函數
virtual void Test_VirtualA(){}; //純虛函數
private: //私有變量
char name_haha = 'W';
};
3.1、定義一個對象: 直接定義, stu;在堆里面定義, *stu = new ;刪除對象, stu;
student My_student; //實例化類 My_student(對象)
student * My_student1 = new student; //實例化類 指針
delete My_student1; //刪除對象
注意:這樣只可以刪除在堆里面定義的對象,不能刪除直接定義的。目的釋放堆里面的內存。
3.2、使用一個對象: 直接定義的使用 stu.name;在堆里面定義的使用 stu->age;使用指針訪問。
C++訪問對象方法和C語言訪問結構體的方法一樣的,直接定義使用“.”來訪問,在堆里面定義的指針話使用“->”來訪問。
student My_student; //實例化類 My_student(對象)
student * My_student1 = new student; //實例化類 指針
student * My_student2 = new student(168); //實例化類(定義一個對象)調用構造函數的重載函數
My_student.name[0] = 'w'; //使用對象對類中的成員變量設置值
My_student.age = 24; //使用對象對類中的成員變量設置值
My_student.Test2(); //使用類中的函數,使用函數和只用變量一樣的
My_student.Test1(); //調用函數
My_student.Test1(168); //調用重載函數
My_student.Test_Virtual(); //調用虛函數
My_student1->age = 24;
My_student1->name[1] = 'w';
3.3、類中的函數 再類里面聲明實現函數,實現函數可以在類中寫,也可以在函數外面寫,寫在類中會比較長,顯得臃腫。在函數外面實現函數的話需要加入函數的類名。需要加入“::”,不加入的話就會默認為普通函數。
class Peple
{
public: //類的公共變量
void Test(void){ //在類中聲明和實現函數
cout<<"My name is Test1"<<endl;
};
void Test1();
};
//類外實現函數
void Peple::Test1(void)
{
cout<<"My name is Test1"<<endl;
}
3.4、類的訪問修飾符 : 表示函數和變量都是公開的,任何人都可以訪問。:標志函數的變量只能在自己的類里面自己訪問自己,不能通過對象來訪問。可以通過類中的函數來實現強行訪問私有變量。:表示函數和變量只能在自己的類里面訪問自己,但是可以通過派生類來訪問的。
class People
{
public:
char People_name = 168;
private:
char People_name1 = 66;
protected:
char People_name2 = 99;
};
4、C++類屬性 4.1、類函數的重載特性
類函數的重載特性就是我們可以在類中定義的函數可以同名,但是參數不同的函數。重載函數的調用的時候會根據參數的個數自動調用哪一個函數。
class People
{
public:
void Test_People_Number(int day);
void Test_People_Number(int day,int time);
};
4.2、構造函數和析構函數
構造函數:假如定義了構造函數,當對象被創建的時候,就會出發這個函數。
析構函數:假如定義了析構函數,當對象被刪除或者生命周期結束的時候就會觸發析構函數
定義析構函數和構造函數:
構造函數和析構函數的名字必須于類名一樣的。析構函數要在前面加上一個“~”。
使用new創建的對象是在堆中創建的,函數執行結束后不會自動釋放,使用就可以實現對象的釋放,這個時候就會觸發類的析構函數。
構造函數是可以被重載的,析構函數是不會被重載的。當使用構造函數的重載特性的時候,類的實例化(定義一個對象)只能通過堆的方式來實例化一個對象。 * = new (168);
class student
{
public: //類的公共變量
student(); //構造函數,對象實例化(創建)的時候調用
student(int a); //構造函數的重載函數
~student(); //析構函數,對象刪除的時候調用
};
student::student() //構造函數
{
cout<<"This is a Create Function"<<endl;
}
student::student(int a) //構造函數的重載函數
{
cout<<"This is a Create Function Data:"<<a<<endl;
}
student::~student() //析構函數
{
cout<<"This is a Delete Function"<<endl;
}
4.3、類的繼承
類的繼承可以的繼承父類中的和的部分,的部分不能被繼承。
當我們覺得這個類不好的時候,可以使用類的繼承來添加我們想要的功能。
class 子類: public 父類{
public :
……
protected:
……
}
例如:
class My_new_student:public student{ //類的繼承
public:
int grade;
void Test_Virtual(){ //覆蓋父類的虛函數
age = 24;
cout<<"This is a Virtual Function Data:"<<age<<endl;
}
};
//類的繼承的對象操作
My_new_student my_new_student; //定義一個對象 實例化對象
my_new_student.grade = 99; //設置對象的成員變量的值
my_new_student.age = 20;
在子類去訪問父類的成員變量,也是使用“.”和“->”來訪問。繼承的類同樣會調用父類的析構函數和構造函數。
4.4、虛函數和純虛函數
虛函數:有實際代碼定義的,允許派生類對其進行覆蓋式的替換,用來修飾。
純虛函數:沒有代碼實際定義的虛函數就是純虛函數。
使用來修飾的,虛函數就是用在類的繼承上的,父類的函數可以被子類來修改掉。
class student
{
public: //類的公共變量
virtual void Test_Virtual(); //虛函數
virtual void Test_VirtualA(){}; //純虛函數
};
怎樣定義一個虛函數?
我們可以在類中寫函數,也可以在類外寫函數,此時在類外實現函數的話就要繼承類。相當于子類可以重新定義這個同名函數,這樣就會實現子類的內容覆蓋父類中同名的虛函數。
class My_new_student:public student{ //類的繼承
public:
int grade;
void Test_Virtual(){ //覆蓋父類的虛函數
age = 24;
cout<<"This is a Virtual Function Data:"<<age<<endl;
}
};
此外虛函數的主要作用可以預留接口實現分工合作。
二、QT知識 2.1、初識QT
Qt的跨平臺特性非常的強,一套代碼不用修改太多,直接通用所有的平臺。
可運用于MCU上,QT的三駕馬車,QT下的串口串口編程、QT下的網絡編程、QT下操作GPIO。
2.2、QT界面基礎認知
基本顯示界面。
可以在菜單欄中的控件顯示左右便編輯框。
2.3、創建QT工程
1、打開軟件
2、新建工程
操作步驟New –>–>Qt –>
實現工程名和工程路徑的設置和選擇。
選擇默認的編譯器–>選擇基類
2.4、創建QT工程的文件
1、工程文件
2、UI文件
2.5、制作一個簡單QQ登錄界面
1、設置編輯UI
使用到的組件:圖片、文本、gif圖的組件式
放置賬號和密碼的對話框我們用的組件式
按鈕我們使用的是
實現步驟,先實現頁面布局的布置,需要注意的是密碼的輸入類型我們設置為密碼就行了。設置(回顯模式)
2、修改控件的名稱
修改控件的名稱方便我們在對控件使用代碼操作的時候直觀的理解。只需要我們在右側菜單欄中選擇對應的子控件雙擊即可實現修改控件的名稱。
三:QT信號于槽 3.1、信號于槽基本概念
信號:信號是指控件發出特定的信號,例如中的信號如下所示。
槽:槽就是槽函數,我們可以把槽綁定在某一個控件的信號上。
信號和槽的概念就類似于單片機中的中斷一樣的,中斷外面有一個事件觸發c語言上位機軟件開發,然后執行對應的中斷處理函數。
3.2、信號和槽的關聯
自動關聯:選中要綁定的控件,右鍵選擇轉到槽,選擇對應槽事件。對應有觸發界面的操作可以用自動關聯。
當使用自動關聯的時候c語言上位機軟件開發,這個時候就會在C++的類中添加私有槽函數,同時也在.cpp中添加對應的槽函數,我們可以通過這個槽函數實現我們想要的交互。
private slots:
void on_pushButton_3_clicked();
槽函數只能聲明在 slots或者 slots下面,注意這個只是QT下面才有的slots,標準的C++中沒有。
手動關聯:適用于無界面操作的環境。使用函數連接,
(ui->,(()),this,SLOT(()));
(A, (B),C,SLOT(D));解釋就是當事件A發出B信號時,就會觸發對象C的槽函數D
手動生成關聯函數:
四:QT控件介紹 4.1、添加圖圖片
1、給工程添加源文件,點擊工程右鍵,添加新文件。
2、選中QT,QT File,選擇
添加資源文件以后QT會自動給我們添加好所包含的資源文件以及自動創建資源文件。
3、在工程文件夾中點擊 文件夾下的qrc,右鍵嗲選中Open With 資源編輯器
這里我們需要先添加前綴,目的是資源文件的索引是按照相對路徑索引的。只有先添加前綴之后,才可以實現添加文件,不然添加文件是灰色的。
添加文件,這里的前綴就默認/,可以根據文件夾來索引不同文件夾下面的資源文件。例如我不希望圖片和我的工程放在同一個目錄下,這樣顯得比較雜亂,因此我新建一個的文件夾,將所有用到的文件放置在里面的話,就可以添加前綴為 /即可。一定要保存了,才可以顯示添加文件。
4、代碼中引用源文件
這里我們可以添加不同類型的圖片給控件,其中包括背景圖片,邊框圖片以及普通圖片,添加背景圖片會根據控件的大小自動添加好多陣列的圖片,邊框圖片的話就只有一個,并且隨著控件大小變化壓縮等,普通圖片的話控件比原始圖片小的話就等比縮放,控件比原始圖片大的時候就保持原始圖片大小不變。
5、QT中多種布局文件,存在水平布局、垂直布局、柵格布局,打破布局幾種布局方式。
注意:當使用幾種布局的時候要可以根據窗格大小開變大小的時候要加入彈簧,在加入彈簧的時候會出現圖片不存在的情況的時候,這時候選中要進行布局的幾個控件,然后點擊右側的屬性欄中的最小尺寸修改大小即可。
4.2、QT輸入框 4.2.1、使用控件,使用Line Edit 控件
4.2.2、檢測輸入信息獲取
void Widget::on_LoginButton_clicked()
{
QString Account = ui->AccountEdit->text(); //獲取輸入框的信息
QString Passworld = ui->PasswordEdit->text(); //獲取密碼輸入
if(Account == "123" && Passworld == "123"){
MainScreen * mainscreen = new MainScreen; //實例化對象
mainscreen->setGeometry(this->geometry()); //獲取當前窗口xy的數值,設置窗口
mainscreen->show(); //顯示窗口
}
}
4.3、QT按鍵控件
這里按鍵使用的是push 作為按鍵的顯示,按鍵可以添加信號與槽,此外按鍵還可以添加圖片,和前面的圖片添加也是一樣的。
五:QT添加新的界面 5.1、添加新文件
1、在工程文件名右鍵添加新文件,選擇QT,QT 設計師界面
5.2、布局界面
和上述步驟一樣可以自定義布局文字和圖片按鍵。這里設置的布局如下所示。其中圖標可以在這個圖標庫下載
5.3、實現按鈕點擊界面跳轉
首先在槽函數對應的.cpp 文件中包含對應跳轉界面的頭文件,# “.h”,添加對應的窗口適應函數。這里在.cpp中的槽函數中添加如下的代碼,意思就是當輸入框內有輸入信息的時候,并且輸入正確,當點擊登錄的時候會跳轉到對應的界面中去。
void Widget::on_LoginButton_clicked()
{
QString Account = ui->AccountEdit->text(); //獲取輸入框的信息
QString Passworld = ui->PasswordEdit->text(); //獲取密碼輸入
if(Account == "123" && Passworld == "123"){
MainScreen * mainscreen = new MainScreen; //實例化對象
mainscreen->setGeometry(this->geometry()); //獲取當前窗口xy的數值,設置窗口
mainscreen->show(); //顯示窗口
}
}
5.4、實現界面的關閉
而咋對應的.cpp中文件中我們也先設置好設置的圖標的信號與槽,在槽函數中添加界面關閉,當點擊圖片的時候就會關閉當前的界面。
void MainScreen::on_BUtton_Set_clicked()
{
this->close();
}