1. 程式人生 > >PyQt GUI程式設計——訊號與槽

PyQt GUI程式設計——訊號與槽

PyQt中使用訊號與槽的機制實現物件之間的通訊。

訊號

當物件改變其狀態時,訊號就由該物件發射出去,並且物件只負責傳送訊號,它不知道另一端是誰在接收這個訊號。這樣就做到了真正的資訊封裝,能確保物件被當作一個真正的軟體元件來使用。

用於接收訊號,並且槽只是普通的物件成員函式。一個槽並不知道是否有其他訊號自己相連線,而且物件並不瞭解具體的通訊機制。

訊號和槽的繫結

 通過呼叫QObject物件的connect()函式將某個物件的訊號與另外一個物件的槽函式相關聯。這樣當發射者發射訊號時,接受者的槽函式將被呼叫。

一個訊號可以連線到多個槽,當訊號發出後,槽函式都會被呼叫,但是呼叫的順序是隨機的,不確定的。

多個訊號可以連線到同一個槽,其中任何一個訊號發出,槽函式都會被執行。

訊號和槽的連線可以被移除,PyQt5提供了disconnect()成員函式來進行解綁。

訊號可以和另外一個訊號進行關聯;第一個訊號發出後,第二個訊號也同時傳送。

 

一個演示訊號和槽的關係的樣例

# -*- coding: utf-8 -*-

import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


class SignalSlot(QWidget):
   def __init__(self):
      super(SignalSlot, self).__init__()
      self.initUI()

   def initUI(self):
      self.controlsGroup = QGroupBox('訊號和槽')
      self.lcdNumber = QLCDNumber(self)  # 建立lcdNumber控制元件
      self.slider = QSlider(Qt.Horizontal, self)   # 建立slider控制元件
      self.pBar = QProgressBar(self)  # 建立ProgressBar控制元件
      vbox = QVBoxLayout()  # 建立垂直佈局
      vbox.addWidget(self.pBar)  # 將pBar 控制元件加入佈局中
      vbox.addWidget(self.lcdNumber)
      vbox.addWidget(self.slider)
      self.controlsGroup.setLayout(vbox)
      controlsLayout = QGridLayout()  # 常見網格佈局
      self.label1 = QLabel('儲存狀態:')  # 新增標籤
      self.saveLabel = QLabel()
      self.label2 = QLabel('執行狀態:')
      self.runLabel = QLabel()
      self.buttonSave = QPushButton('儲存')  # 新增按鈕
      self.buttonRun = QPushButton('執行')
      self.buttonStop = QPushButton('停止')
      self.buttonDisconnect = QPushButton('解除關聯')
      self.buttonConnect = QPushButton('繫結關聯')
      controlsLayout.addWidget(self.label1, 0, 0)  # 在網格佈局中1行1列新增控制元件
      controlsLayout.addWidget(self.saveLabel, 0, 1)
      controlsLayout.addWidget(self.label2, 1, 0)
      controlsLayout.addWidget(self.runLabel, 1, 1)
      controlsLayout.addWidget(self.buttonSave, 2, 0)
      controlsLayout.addWidget(self.buttonRun, 2, 1)
      controlsLayout.addWidget(self.buttonStop, 2, 2)
      controlsLayout.addWidget(self.buttonDisconnect, 3, 0)
      controlsLayout.addWidget(self.buttonConnect, 3, 1)
      layout = QHBoxLayout()
      layout.addWidget(self.controlsGroup)
      layout.addLayout(controlsLayout)
      self.setLayout(layout)
      self.slider.valueChanged.connect(self.pBar.setValue)
      self.slider.valueChanged.connect(self.lcdNumber.display)
      self.buttonRun.clicked.connect(self.buttonSave.clicked)
      self.buttonSave.clicked.connect(self.showMessage)
      self.buttonRun.clicked.connect(self.showMessage)
      self.buttonDisconnect.clicked.connect(self.unbindConnection)
      self.buttonConnect.clicked.connect(self.bindConnection)
      self.buttonStop.clicked.connect(self.stop)
      self.setGeometry(300, 500, 500, 180)
      self.setWindowTitle('訊號和槽')

   def showMessage(self):
      if self.sender().text() == "儲存":
         self.saveLabel.setText("Saved")
      elif self.sender().text() == "執行":
         self.saveLabel.setText("Saved")
         self.runLabel.setText("Running")

   def unbindConnection(self):
      self.slider.valueChanged.disconnect()

   def bindConnection(self):
      self.slider.valueChanged.connect(self.pBar.setValue)
      self.slider.valueChanged.connect(self.lcdNumber.display)

   def stop(self):
      self.saveLabel.setText('')
      self.runLabel.setText('')


if __name__ == '__main__':
   app = QApplication(sys.argv)
   ex = SignalSlot()
   ex.show()
   sys.exit(app.exec_())
-------------------------------------------------------------程式碼分割線--------------------------------------------

1-47行生成使用者介面

 

47-54行連線了訊號與槽。

self.slider.valueChanged.connect(self.pBar.setValue)   

連線滑動條的改變(訊號) 到進度條顯示(槽)

self.slider.valueChanged.connect(self.lcdNumber.display)

連線滑動條的改變(訊號) 到LCD面板顯示(槽)

self.buttonRun.clicked.connect(self.buttonSave.clicked)

連線執行按鈕點選操作(訊號) 到儲存按鈕點選操作(訊號)

self.buttonSave.clicked.connect(self.showMessage)

連線儲存按鈕點選操作(訊號) 到標籤內容顯示(槽)

self.buttonRun.clicked.connect(self.showMessage)

連線執行按鈕點選操作(訊號) 到標籤內容顯示(槽)

self.buttonDisconnect.clicked.connect(self.unbindConnection)

連線解除關聯按鈕點選操作(訊號) 到解除繫結操作(槽)

self.buttonConnect.clicked.connect(self.bindConnection) 

連線繫結關聯按鈕點選操作(訊號) 到繫結操作(槽)

self.buttonStop.clicked.connect(self.stop)

連線停止按鈕點選操作(訊號)到停止操作(槽)

 

66-67行解除了訊號和槽的關聯

def unbindConnection(self): self.slider.valueChanged.disconnect()

解除滑動條的改變(訊號)的一切關聯。

--------------------------------------------------------------------------------------

本文例項來源:《Python程式設計》人民郵電出版社 王學軍 胡暢霞 韓豔峰 主編

That's All .Thankyou!