Qt4與Qt5的訊號差異

2021-10-05 22:04:10 字數 2301 閱讀 1819

新舊語法對比

舉例介紹。某個類在值變化時傳送valuechanged(qstring,qstring)訊號,需要在槽showvalue(qstring)中對改變的值做相應的處理。在qt4中一般這樣來關聯訊號和槽:

connect(sender,signal(valuechanged(qstring,qstring)),receiver,slot(showvalue(qstring)));

qt4的signal和slot兩個巨集,實際是將其引數轉換成相應的字串。在編譯之前,qt的moc工具從源**中提取出所需要的元資料,形成一張由使用了signals和slots修飾的所有函式組成的字串表。connect函式將與訊號關聯起來的槽的字串,同這張字串中的資訊進行匹配,也就能夠在發出訊號時知道需要呼叫哪個槽函式。

這種實現有下面兩個問題

1、沒有編譯期檢查。由於訊號和槽都會被signal和slot巨集處理成字串,字串的對比是在執行時完成的,並且失去了型別資訊。所以,我們在編寫qt4程式時,有時會出現編譯通過但是執行時原本應該呼叫的槽函式卻沒有執行。此時,編譯器不能給出任何錯誤資訊,只能在執行時看有沒有警告

2、無法使用相容型別的引數。由於connect函式使用的是字串對比,所以槽函式引數型別的名稱必須和訊號的完全一致,也必須與標頭檔案中的型別一致。這裡的」一致「是嚴格的字串意義上的相同,因此,那些使用了tyoedef或者namespace的型別,即便實際型別是相同的,依然可能由於字串名字不一樣而不能正常工作。

為了解決這兩個問題,qt提供了一套全新的訊號槽語法。前面在qt4中的關聯可以使用下面的方式代替:

connect(sender,&sender::valuechanged,receiver,&receive::showvalue);

其中,sender是發出訊號的sender物件的型別,receive是接收訊號的receiver物件的型別。需要說明,qt4中的關聯方式在qt5程式中依然可用,不過新的語法有下面幾個優點:

1、支援編譯期檢查。qt5新的關聯語法可以在編譯時進行檢查,訊號或槽的拼寫錯誤、槽函式引數數目多於訊號的引數數目且等錯誤在編譯時能夠被發現。

2、支援相容引數型別的自動轉換。使用心得語法不僅支援使用tyoedef或者命名空間,還支援使用隱式型別轉換。例如,當我們的訊號引數型別時qstring,而槽函式對應的引數型別時qvariant,那麼,在進行訊號槽的連線時,qstring將被自動轉換成qvariant。這是因為qvariant有乙個可以使用qstring的隱式建構函式。

3、允許連線到任意函式:在qt4中,槽函式只能是使用slots關鍵字修飾的成員函式,而新的語法通過函式指標直接呼叫函式,任意成員函式、靜態函式或者c++11lambda表示式都可以作為槽進行關聯。(以前的訊號槽語法不受private限制的。槽函式雖然可以被宣告為private,但僅作為普通函式呼叫時起作用,作為槽連線時,slot無視private,修飾,因為僅作為字串連線。而新語法無法取私有函式指標,在編譯時就會有警報,因而更安全。)

新的語法例項

connect(sender,&sender::***,receive,&receive::yyy);

注意:當訊號有過載的情況下,使用qt5的新語法可能會有一些不便。例如,qspinbox有兩個過載的訊號:

void valuechanged(int);

void valuechanged(const qstring &);

當我們使用下面的語句連線時connect(spinbox,&qspinbox::valuechanged,this,&widget::valuechanged);編譯器會發出乙個錯誤,因為訊號valuechanged有過載,所以使用有歧義。這裡我們可以使用qt4的訊號槽連線語法,是可以的。但這樣做又失去了編譯期檢查的優點。為了繼續使用qt5的新語法,需要增加乙個顯示型別轉換:

connect(spinbox,static_cast(&qspinbox::valuechanged),this,&widget::yyy);

同樣,若槽函式有引數不同的過載函式。也可按照轉換:

connect(spinbox,static_cast(&qspinbox::valuechanged),this,static_cast(&widget::valuechanged));

關注

筆者 - jxd

Qt5 與 Qt4 的點點差異 事件

qt5相對於qt4 增加對事件accept 和ignore 函式。qt 中有很多種事件 滑鼠事件 鍵盤事件 大小改變的事件 位置移動的事件等等。對於事件的處理,我們qt 中使用相對應的機制。event 函式 1.event 函式是乙個 protected 的函式,這意味著我們要想重寫event 必須...

Qt中 Qt5與Qt4語法的微小區別

ifndef mainwindow h define mainwindow h include class mainwindow public qmainwindow endif mainwindow h include include include include include include...

QT5 訊號與槽

前言 訊號與槽是qt的精華所在,也是他區分於其他軟體的關鍵地方,所以我們學習qt肯定無法繞過這一核心 當物件內部狀態發生改變,訊號就被反射,只有定義了這個訊號的類和他的子類才能發射這個訊號 訊號的宣告是在標頭檔案中進行的,qt的signals關鍵字指出進入了訊號宣告區,隨後即可宣告自己的訊號。訊號由...