1. 程式人生 > 其它 >QT學習筆記和踩坑記錄(第一天)

QT學習筆記和踩坑記錄(第一天)

技術標籤:QTqt

文章目錄

QT學習筆記:

0001 註釋的快捷鍵

​ Ctrl+/ 可以多行註釋或者取消註釋。

0002 檢視幫助文件

​ F1跳轉到要檢視的程式碼的幫助文件,在按一次F1,展開幫助文件。

0003 Q_UNUSED

​ Q_UNUSED(變數)可以讓沒被使用的變數不報令人討厭的警告。

0004 Q_OBJECT

​ 只有繼承了QObject類的類,才具有訊號槽的能力。所以,為了使用訊號槽,必須繼承QObject。凡是QObject類(不管是直接子類還 是間接子類),都應該在第一行程式碼寫上Q_OBJECT。

0005 setParent()

​ 如果不指定父物件,物件和物件(視窗和視窗)沒有關係,獨立

​ a指定b為它的父物件,a就會放在b的上面,即a成為b的子控制元件。

​ 指定父物件,有兩種方式:

​ 1)a.setParent(b)

​ 2)通過建構函式傳參,即在例項a的時候將b做為它的引數傳進去

​ 只需要父物件b顯示,上面的子物件a自動顯示。

0006 QPainter繪圖

​ QPainter繪圖的時候,原點在左上角,向右下方繪圖,可以通過painter.translate()和painter.rotate()函式改變原點位置和旋轉圖形。

0007 qDebug

​ 標頭檔案QDebug,qDebug函式可用於列印某些變數的值,與cout的用法一樣,一般用於除錯。

0008 connect函式詳解

​ connect函式用於將一個訊號和槽函式相關聯,當訊號觸發時呼叫該槽函式,兩者可以位於不同的類。

QT4的connect函式詳解:

​ 函式定義:connect(Sender,SIGNAL(signal),Receiver,SLOT(slot));

Sender是訊號的傳送者,如當一個按鈕被點選時要發射點擊的訊號,那麼傳送者就是這個按鈕本身。

​ **SIGNAL(signal)**是訊號名,可以是自定義的訊號,也可以是QT自帶的訊號。

Receiver是訊號的接收者、槽函式的擁有者。

​ **SLOT(slot)**是需要呼叫的槽函式,即使是在當前類中,也需要加類名限定該函式。

​ 可能出現的問題

QT4的connect函式實際上利用SIGNALSLOT這兩個巨集,把其後的函式名轉換成一個字串。隨後,moc 將會掃描 全部檔案,將所有的 signal 和 slot 提取出來做成一個對映表。QObject::connect()函式則會從這個對映表裡面找到該·· 字串,從 signal 的名字就可以找到 slot 的名字,因此也就知道了在 signal emit 的時候,該去呼叫哪一個 slot 函式。

​ 1)沒有編譯期檢查:因為函式名被處理成字串,所有的檢查都是在執行時完成的。這就是為什麼有時會發生編譯通過 了,但 slot 並沒有被呼叫。此時,你就應該去檢查 console 的輸出,看看有沒有什麼 warning 說明 connect 並沒有成功。

​ 2)因為處理的是字串,所以 slot 中的型別名字必須用 signal 的完全一致,而且在標頭檔案中的和實際 connect 語句中的 也必須一致。也就是說,如果你使用了 typedef 或者 namespace,connect 就可能不成功(在 Qt 5 之前的版本中,我們當 然也可以使用namespace,但是必須保證標頭檔案中的和 connect 語句中的文字完全一致)。

QT5的connect函式詳解:

​ 函式定義:connect(sender, &Sender::valueChanged, receiver, &Receiver::updateValue);

​ 各個引數與之前的類似,優點是可以連線到任意函式,缺點是在使用過載的訊號和函式的時候得定義函式指標

​ 例子:

connect(&sm->clicked_big_window,&QPushButton::pressed,this,&MainWidget::toBigWindow);

​ sm是前面的一個例項,將sm中的clicked_big_window按鈕作為訊號的傳送者,當發射QPushButton::pressed訊號, 即按鈕被點選的訊號時,呼叫當前物件的(this)的,&MainWidget::toBigWindow函式。

0009 signals訊號詳解

​ signals訊號詳解:

​ 1)訊號必須有signals關鍵字來宣告

​ 2)訊號沒有返回值,但可以有引數

​ 3)訊號就是函式的宣告,只需宣告,無需定義

​ 4)使用:emit mySiganal()

​ 5)訊號可以過載

​ 例子:

signals:
	void mySignal();
	void mySignal(int,QString);

​ 6)訊號過載的時候,為了QT5的connect函式不產生二義性(報錯),需在connect之前定義該訊號的函式指標,用該函式指標代替 connect的第二個引數

​ 如:

//無參的mySignal
void (XXXX::*funSignal)()=&XXXX::mySignal;
connect(&XXXX,funSignal,XXXX,&XXXX::XXXX);
//有參的mySignal
void (XXXX::*testSignal)(int ,QString)=&XXXX::mySignal;
connect(&xxxx,funSignal,XXXX,&XXXX::XXXX);

0010 QT中的Lambda表示式

​ Lambda表示式是C++11新增的新特性,想在QT中使用的話,得在專案檔案(.pro)中加入 CONFIG += C++11

QPushButton *b= new QPushButton(this);
b->setTest("Lambda表示式");
connect(b,&QPushButton::released,
		[b]()//匿名內部類
		{
			//此處相當於槽函式
            b->setTest("Lambda表示式2");
		}
		)
/*
  []的作用是將外部的變數,以值傳遞的方式傳遞進這個匿名內部類
  [=]表示把外部所有區域性變數、勒種所有成員傳進去
  []() mutable 表示對外部變數不僅可讀還可寫
*/

0011 座標系統

​ 主視窗相對於螢幕、子控制元件相對於父視窗,座標系統的原點在左上角。

0012 記憶體回收機制

​ 1)指定父物件後

​ 2)直接或間接繼承於QObject

​ 子物件如果是動態分配空間(new)的話,不需要手動釋放(delete),系統會自動釋放,即該子物件的解構函式會被自動呼叫。

QT踩坑記錄:

0001

​ QT任何路徑下都不能出現中文、空格 。

0002

​ 註釋只能用//,/**/會報錯。

0003

​ error: LNK2001: 無法解析的外部符號 “public: virtual struct QMetaObject const * __cdecl

​ 解決辦法:

​ 編譯出錯是因為沒有生成moc_mainwindowprivate.cpp檔案造成的。

​ 如果新新增QObject派生類到您的專案,則必須再次執行qmake,即
1、清理專案(非必須)
​ 2、執行qmake(必須)
3、構建專案(必須)
​ 否則,如果在QObject繼承的類上進行增量構建,那麼您將擁有過時的moc檔案,或者乾脆沒有moc檔案。