Qt for Python 信号和槽的使用详解
前言
如果要說 Qt 里面的最常聽到的詞,那么 “信號”(signals)和“槽”(slots)絕對是其中之一了,其功能簡單強大,想必每個 Qt 程序員最能理解的啦,那么,想要用PySide2來寫 Qt 程序,首先要接觸的就是這兩貨的寫法。
正文
傳統的寫法
先通過一個示例來看看傳統的信號和槽的寫法:
import sys from PySide2.QtWidgets import QApplication,QPushButton,QWidget from PySide2.QtCore import SIGNAL,QObjectdef slotBtnClicked():print("btn clicked..")app = QApplication(sys.argv) widget = QWidget() widget.resize(300,200) widget.show()btn = QPushButton("Click me",widget) btn.move(widget.width()/2. - btn.width()/2.,widget.height()/2. - btn.height()/2.) QObject.connect(btn,SIGNAL('clicked()'),slotBtnClicked) btn.show()sys.exit(app.exec_())這里定義了一個簡單的按鈕,通過將按鈕的點擊信號連接到槽來實現其效果,注意這里的連接方法,是通過QObject.connect來實現的,其寫法比較麻煩。而這里的槽,可以不用像在 C++中那樣特意聲明為 SLOTS 類型。
來看看效果圖:
點擊按鈕后終端輸出:
btn clicked.. btn clicked..基本效果已達成。
新的寫法
剛剛說到,上面那種連接方法有些復雜,有沒有更簡單的寫法呢,答案是肯定的。
接下來看看新的寫法,會比之前的更簡單。
同樣是上面的示例,修改如下:
這里將連接方式改成了
btn.clicked.connect(slotBtnClicked)這種寫法當然更簡單明了,其效果是一樣的。
帶參數的信號和槽
上面的兩個示例都是介紹如何沒有帶參數的信號和槽的連接方式和用法,那么,如果信號中帶參數又會有什么不同呢,接著看一個示例:
import sys from PySide2.QtWidgets import QApplication from PySide2.QtCore import QObject, Signal, Slotapp = QApplication(sys.argv) #定義一個接受字符串類型的槽 @Slot(str) def say_some_words(words):print(words)class Communicate(QObject):#定義一個信號speak = Signal(str)someone = Communicate() someone.speak.connect(say_some_words) #連接信號和槽 someone.speak.emit("hello world.") #發送信號運行,輸出:
hello world.接下來在上面示例的基礎上,新加載一個裝飾器,將槽定義為可以接收 int 類型。
import sys from PySide2.QtWidgets import QApplication from PySide2.QtCore import QObject, Signal, Slotapp = QApplication(sys.argv)@Slot(int) @Slot(str) def say_some_words(words):print(words)class Communicate(QObject):#定義一個信號speak_words = Signal(str)speak_number = Signal(int)someone = Communicate() someone.speak_words.connect(say_some_words) someone.speak_words.emit("hello world.") someone.speak_number.connect(say_some_words) someone.speak_number.emit(1234)這個示例中,定義了兩個信號,分別用來發送數字和字符串,并且這兩個信號都連接到同一個槽中,并且這個槽有兩個裝飾器,分別接收 int 類型和字符串類型。
運行結果:
更高級的寫法
對于上面的示例,分別將兩個信號連接到同一個槽,兩個信號傳入的參數類型不一致,其實還有更高級的一種寫法來替代這種方式,直接看示例吧。
import sys from PySide2.QtWidgets import QApplication from PySide2.QtCore import QObject, Signal, Slotapp = QApplication(sys.argv)@Slot(int) @Slot(str) def say_something(stuff):print(stuff)class Communicate(QObject):#定義一個信號,可用來接收字符串類型或者 int 類型參數speak = Signal((str,),(int,))someone = Communicate() someone.speak.connect(say_something) someone.speak[int].connect(say_something) someone.speak.emit("hello world.") someone.speak[int].emit(1234)上面的示例,定義了一個接收兩個類型參數的信號,注意這里的連接方式和發送信號的方式:
someone.speak.connect(say_something) someone.speak[int].connect(say_something) someone.speak.emit("hello world.") someone.speak[int].emit(1234)只選擇了其中一個參數來連接和發送信號,這種寫法在 C++中是沒有的。
這里的
someone.speak.connect(say_something)
等同于
someone.speak[str].connect(say_something)
someone.speak.emit(“hello world.”)
等同于
someone.speak[str].emit(“hello world.”)
也就是說第一個參數的類型聲明可以在連接和發送信號的時候省略。
而信號的定義
speak = Signal((str,),(int,))
這種寫法的意思是,既可以接收字符串類型,也可以接收 int類型,二者選其一,千萬要注意的是,這個定義類型,并不是說可以同時接收兩個參數,而是只能選擇其中一種類型。
那么如果要定義能接受兩個參數的信號又怎么寫呢,很簡單,看下面的示例:
如上示例,如果要接收一個以上的參數,那么直接添加參數類型即可,speak = Signal(str,int)。
又或者,如果要像之前的示例一樣,做一個可選擇類型的參數,并且其中一個參數可以傳入兩個值,可以像下面這樣定義信號和連接信號:
代碼很簡單,就不再贅述了。
優化代碼
上面的代碼寫得有些亂,不方面擴展和管理,其實可以將信號和槽以及連接方式都封裝到類中去,這樣一來,代碼的可閱讀性以及代碼結構就會更清晰,如下示例。
import sys from PySide2.QtCore import QObject, Signal class Communicate(QObject): speak = Signal() def __init__(self): super(Communicate, self).__init__() self.speak.connect(self.say_hello) def speaking_method(self): self.speak.emit() def say_hello(self):print("Hello world") someone = Communicate() someone.speaking_method()關于 Qt for Python 中信號和槽的用法就介紹到這里,上述代碼都很簡單,就不再一一贅述。
總結
以上是生活随笔為你收集整理的Qt for Python 信号和槽的使用详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt for Python之 PySid
- 下一篇: Python 之列表的常用方法