python GUI庫圖形界面開發(fā)之PyQt5結(jié)合Qt Designer創(chuàng)建信號與槽的詳細方法與實例
在下面這3篇文章中我們給出了手工輸入代碼的信號與槽的使用方法,因為采用這種方法介紹時,會簡單一些,如果使用Qt Designer來介紹這些功能,那么任何一個簡單的功能都會使用xxxx.ui xxxx.py call_xxxx.py三個文件 來實現(xiàn),這樣內(nèi)容會顯得很亂
python GUI庫圖形界面開發(fā)之PyQt5信號與槽基礎使用方法與實例
在實戰(zhàn)應用中,由于Qt Designer可以很好的實現(xiàn)界面顯示與業(yè)務邏輯分離,所有能保住我們解決大量的代碼,如果能夠使用Qt Designer自動創(chuàng)建一些信號與槽機制,那就更好了。
本例要實現(xiàn)的功能是:通過一個模擬打印的界面來詳細說明信號的使用,在打印時,可以設置打印的份數(shù),紙張類型,觸發(fā)打印按鈕后,將執(zhí)行結(jié)果顯示在右側(cè),通過QCheckBox(全屏預覽 復選框)來選擇是否通過全屏模式進行預覽,將執(zhí)行結(jié)果顯示在右側(cè)
按F1鍵可以顯示helpmessage幫助信息
第一步:Qt Designer
首先,使用Qt Designer新建一個模板名為widget的簡單窗口,通過將widget box區(qū)域的控件拖曳到窗口中,實現(xiàn)如圖的界面效果

這里對窗口控件進行簡要說明
| 控件類型 | 控件名稱 | 作用 |
|---|---|---|
| QSpinBox | numberSpinBox | 顯示打印的分數(shù) |
| QComboBox | styleCombo | 顯示打印的紙張類型,紙張類型包括A3,A4等 |
| QPushButton | printButton | 連接emitPrintSiagnal函數(shù)的綁定,觸發(fā)自定義信號printSignal的發(fā)射 |
| QCheckBox | prievewState | 是否全屏預覽 |
| QPushButton | priviewButton | 連接emitPreviewSignal函數(shù)的綁定,觸發(fā)自定義信號previewSignal的發(fā)射 |
| QLabel | resultLabel | 顯示執(zhí)行結(jié)果 |
第二步:將界面文件ui轉(zhuǎn)換為py文件
pyuic5 -o xxxxx.py xxxxx.ui
會在界面文件同級目錄下生成一個py文件
查看所生成的.py文件,完整代碼如下
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MainWinSignalSlog02.ui'
#
# Created by: PyQt5 UI code generator 5.8.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(715, 225)
self.controlsGroup = QtWidgets.QGroupBox(Form)
self.controlsGroup.setGeometry(QtCore.QRect(10, 20, 451, 151))
self.controlsGroup.setObjectName("controlsGroup")
self.widget = QtWidgets.QWidget(self.controlsGroup)
self.widget.setGeometry(QtCore.QRect(10, 40, 411, 30))
self.widget.setObjectName("widget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.numberSpinBox = QtWidgets.QSpinBox(self.widget)
self.numberSpinBox.setObjectName("numberSpinBox")
self.horizontalLayout.addWidget(self.numberSpinBox)
self.styleCombo = QtWidgets.QComboBox(self.widget)
self.styleCombo.setObjectName("styleCombo")
self.styleCombo.addItem("")
self.styleCombo.addItem("")
self.styleCombo.addItem("")
self.horizontalLayout.addWidget(self.styleCombo)
self.label_2 = QtWidgets.QLabel(self.widget)
self.label_2.setObjectName("label_2")
self.horizontalLayout.addWidget(self.label_2)
self.printButton = QtWidgets.QPushButton(self.widget)
self.printButton.setObjectName("printButton")
self.horizontalLayout.addWidget(self.printButton)
self.widget1 = QtWidgets.QWidget(self.controlsGroup)
self.widget1.setGeometry(QtCore.QRect(10, 100, 201, 30))
self.widget1.setObjectName("widget1")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget1)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.previewStatus = QtWidgets.QCheckBox(self.widget1)
self.previewStatus.setObjectName("previewStatus")
self.horizontalLayout_2.addWidget(self.previewStatus)
self.previewButton = QtWidgets.QPushButton(self.widget1)
self.previewButton.setObjectName("previewButton")
self.horizontalLayout_2.addWidget(self.previewButton)
self.resultGroup = QtWidgets.QGroupBox(Form)
self.resultGroup.setGeometry(QtCore.QRect(470, 20, 231, 151))
self.resultGroup.setObjectName("resultGroup")
self.resultLabel = QtWidgets.QLabel(self.resultGroup)
self.resultLabel.setGeometry(QtCore.QRect(20, 30, 191, 101))
self.resultLabel.setObjectName("resultLabel")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "打印控件"))
self.controlsGroup.setTitle(_translate("Form", "打印控制"))
self.label.setText(_translate("Form", "打印份數(shù):"))
self.styleCombo.setItemText(0, _translate("Form", "A3"))
self.styleCombo.setItemText(1, _translate("Form", "A4"))
self.styleCombo.setItemText(2, _translate("Form", "A5"))
self.label_2.setText(_translate("Form", "紙張類型:"))
self.printButton.setText(_translate("Form", "打印"))
self.previewStatus.setText(_translate("Form", "全屏預覽"))
self.previewButton.setText(_translate("Form", "預覽"))
self.resultGroup.setTitle(_translate("Form", "操作結(jié)果"))
self.resultLabel.setText(_translate("Form", "<html><head/><body><p><br/></p></body></html>"))
第三步:新建調(diào)用窗口
為了使窗口的顯示與業(yè)務邏輯分離,在建一個調(diào)用窗口顯示的文件,在調(diào)用類中添加多個自定義信號,并與槽函數(shù)進行綁定,其完整代碼如下
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from jia_07 import Ui_Form
from PyQt5.QtCore import pyqtSignal, Qt
class MyMainWindow(QMainWindow, Ui_Form):
helpSignal = pyqtSignal(str)
printSignal = pyqtSignal(list)
# 聲明一個多重載版本的信號,包括了一個帶int和str類型參數(shù)的信號,以及帶str參數(shù)的信號
previewSignal = pyqtSignal([ int, str ], [ str ])
def __init__( self, parent=None ):
super(MyMainWindow, self).__init__(parent)
self.setupUi(self)
self.initUI()
def initUI( self ):
self.helpSignal.connect(self.showHelpMessage)
self.printSignal.connect(self.printPaper)
self.previewSignal[ str ].connect(self.previewPaper)
self.previewSignal[ int, str ].connect(self.previewPaperWithArgs)
self.printButton.clicked.connect(self.emitPrintSignal)
self.previewButton.clicked.connect(self.emitPreviewSignal)
# 發(fā)射預覽信號
def emitPreviewSignal( self ):
if self.previewStatus.isChecked() == True:
self.previewSignal[ int, str ].emit(1080, " Full Screen")
elif self.previewStatus.isChecked() == False:
self.previewSignal[ str ].emit("Preview")
# 發(fā)射打印信號
def emitPrintSignal( self ):
pList = [ ]
pList.append(self.numberSpinBox.value())
pList.append(self.styleCombo.currentText())
self.printSignal.emit(pList)
def printPaper( self, list ):
self.resultLabel.setText("打印: " + "份數(shù):" + str(list[ 0 ]) + " 紙張:" + str(list[ 1 ]))
def previewPaperWithArgs( self, style, text ):
self.resultLabel.setText(str(style) + text)
def previewPaper( self, text ):
self.resultLabel.setText(text)
# 重載點擊鍵盤事件
def keyPressEvent( self, event ):
if event.key() == Qt.Key_F1:
self.helpSignal.emit("help message")
# 顯示幫助消息
def showHelpMessage( self, message ):
self.resultLabel.setText(message)
self.statusBar().showMessage(message)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MyMainWindow()
win.show()
sys.exit(app.exec_())
運行程序,顯示效果如圖

代碼分析
在上面的例子中,通過PyQtSignal()定義了三個信號,一個str參數(shù)類型的信號,一個list類型參數(shù)類型的信號,一個多重載版本的信號,包括一個int和str類型參數(shù)的信號,以及帶str類型參數(shù)的信號
helpSignal = pyqtSignal(str)
printSignal = pyqtSignal(list)
# 聲明一個多重載版本的信號,包括了一個帶int和str類型參數(shù)的信號,以及帶str參數(shù)的信號
previewSignal = pyqtSignal([ int, str ], [ str ])
對于綁定信號與槽,這里著重說明多重版本的信號綁定,prieviewSignal有兩個版本,即previewSignal(str)和prievewSignal(int ,str),由于兩個版本,因此在綁定的時候,需要顯示指定信號與槽的綁定
self.helpSignal.connect(self.showHelpMessage)
self.printSignal.connect(self.printPaper)
self.previewSignal[ str ].connect(self.previewPaper)
self.previewSignal[ int, str ].connect(self.previewPaperWithArgs)
在Qt的機制中,根據(jù)所傳遞信號的參數(shù)類型和個數(shù),連接到不同的槽函數(shù)
def emitPreviewSignal( self ):
if self.previewStatus.isChecked() == True:
self.previewSignal[ int, str ].emit(1080, " Full Screen")
elif self.previewStatus.isChecked() == False:
self.previewSignal[ str ].emit("Preview")
信號發(fā)射可以傳遞python數(shù)據(jù)類型的參數(shù),本例中的printSignal信號可以傳遞list類型的參數(shù)plist
def emitPrintSignal( self ):
pList = [ ]
pList.append(self.numberSpinBox.value())
pList.append(self.styleCombo.currentText())
self.printSignal.emit(pList)
通過復寫KeyPressEvent()方法,對F1鍵進行功能擴展,這里通過復寫keyPressEvent()方法模擬發(fā)射所需的信號,來完成對應的任務
def keyPressEvent( self, event ):
if event.key() == Qt.Key_F1:
self.helpSignal.emit("help message")
本文主要講解了PyQt5結(jié)合Qt Designer創(chuàng)建信號與槽的詳細方法與實例,另外一篇關于PyQt5結(jié)合Qt Designer創(chuàng)建信號與槽的文章 python GUI庫圖形界面開發(fā)之PyQt5信號與槽基本操作 大家也可以結(jié)合閱讀下,更多關于 PyQt5信號與槽的知識請查看下面的相關鏈接
相關文章
利用Python內(nèi)置庫實現(xiàn)創(chuàng)建命令行應用程序
Python?有一個叫做argparse的內(nèi)置庫,可以用它來創(chuàng)建一個命令行界面。本文將詳解如何利用argparse實現(xiàn)創(chuàng)建一個命令行應用程序,需要的可以參考一下2022-06-06
python實現(xiàn)根據(jù)指定字符截取對應的行的內(nèi)容方法
今天小編就為大家分享一篇python實現(xiàn)根據(jù)指定字符截取對應的行的內(nèi)容方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10
Python+tkinter實現(xiàn)音樂下載軟件的制作
平常我們下載的歌曲,都是各種妖魔鬼怪的格式橫行,想下載下來用一下都不行,還只能在它的播放器內(nèi)聽,這誰受得了~本文就來用Python制作個音樂下載軟件,需要的可以參考一下2022-09-09
Python利用PyExecJS庫執(zhí)行JS函數(shù)的案例分析
這篇文章主要介紹了Python利用PyExecJS庫執(zhí)行JS函數(shù),本文通過案例分析給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12
利用python實現(xiàn)xml與數(shù)據(jù)庫讀取轉(zhuǎn)換的方法
這篇文章主要給大家介紹了關于利用python實現(xiàn)xml與數(shù)據(jù)庫讀取轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面來一起看看吧。2017-06-06

