[英]Creating a custom signal/slot in Qt (PyQt5)
我是使用 Qt 和一般構建 GUI 的完整初學者,所以如果這是一個愚蠢的問題,但我在互聯網上找不到答案,我深表歉意。 我希望你能幫助我解決幾個問題:
首先,我使用 Qt Designer 創建了一個 GUI,我遇到了“接線”的問題。 我有一個帶有多種選項的組合框,我想做的是在框中選擇更改一堆行編輯框中的文本。 問題是,當組合框的textActivated()
信號被發送到行編輯的setText()
槽時,行編輯被組合框中的文本填充。
下面我舉一個小例子來說明我的意思。 此組合框具有值A 、 B和C 。 選擇一個選項后,該字母會出現在框中。 我想要做的是讓組合框的每個條目成為一個值的“鍵” ,所以如果選擇了例如A ,那么行編輯將用選項 1或類似的東西填充。 我想這樣做的原因是因為組合框會根據輸入設置一堆默認參數,然后用戶可以根據需要調整這些值。
我知道我需要修改的線路/負責信號/插槽連接的線路是
self.comboBox.textActivated['QString'].connect(self.lineEdit.setText)
但我真的不明白當.connect 是一個實例 function 時,我將如何傳遞 combobox 的值。
有誰知道如何使用自定義功能/插槽來做到這一點? 完整的代碼在這篇文章的底部。
其次,一個相關的問題,為什么window的__init__()
function中的這些信號/插槽go? app.exec_()
是否連續運行__init__()
? 實例化 object 然后在應用程序循環中運行“更新” function 不是更明智嗎?
提前致謝!
完整代碼:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'practice.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(493, 124)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setObjectName("comboBox")
self.comboBox.addItem("")
self.comboBox.addItem("")
self.comboBox.addItem("")
self.horizontalLayout.addWidget(self.comboBox)
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 493, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.comboBox.textActivated['QString'].connect(self.lineEdit.setText)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.comboBox.setItemText(0, _translate("MainWindow", "A"))
self.comboBox.setItemText(1, _translate("MainWindow", "B"))
self.comboBox.setItemText(2, _translate("MainWindow", "C"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
更新
from PyQt5 import QtCore, QtGui, QtWidgets
#here you make dict in advance.
dic = {'A':'You choose A',
'B':'You choose B',
'C':'You choose C'}
# a list of the dict key. #[*dic] is also ok instead of lis
lis = dic.keys()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(493, 124)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setObjectName("comboBox")
#addItems is for multiple items.
self.comboBox.addItems(lis)
self.horizontalLayout.addWidget(self.comboBox)
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 493, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.comboBox.activated['QString'].connect(self.new_selection)
#I think it is not bothered with .emit of my first answer.
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
# number and value you can use enumerate func.
for num, key in enumerate(lis):
self.comboBox.setItemText(num, _translate("MainWindow", key))
def new_selection(self):
self.lineEdit.setText(dic[self.comboBox.currentText()])
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv) # Whole application
MainWindow = QtWidgets.QMainWindow() # create the actual window
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show() # Actually show the window
sys.exit(app.exec_())
你在某處做一個字典。 你總是參考它。 我不知道您將鍵和值連接擴展了多長時間,但是您現在可以直接在任何地方設置相同的鍵和值。它很冗長,您最好總是盡可能多地從一個 object 獲取密鑰。 如果您這樣做,無論您在字典中添加新的鍵和值,更改都會反映而不會更改其他代碼。 當你想擴展你的key&value時,你所要做的就是只重寫一次dic
的數據。 幸運的是,dict 可以保存鍵的順序... python3.6
您可以像列表一樣使用鍵。 請 append 'D': 'You choose D' 或其他數據並嘗試一下。 我很高興我的回答是你想要的。
簡單地說,你能通過這段代碼達到你的目的嗎?
我從你的問題中了解到的是第一次在 lineedit 上設置第一項。
我不知道你實際上想要設置什么,但是,從 (PyQt5.14) 開始的 textActivated() (我可以激活它,因為我的版本是 5.9.x)...
`signal.connect(somthing slot)` means that make a connection between signal & slot.
`signal.emit(object)` means that to emit the connected signal.
因為您已經將textActivated
(信號)與lineEdit.setText
(插槽)連接起來,所以,如果您在 object 發出時設置 currentText(),setText 會捕獲 object。如果您將信號連接到三個lineedit.setText
,所有的 lineedits 通過相同的信息設置文本。
發射前,除了默認設置外,您必須建立連接。
如果我的答案是您想要的,我認為您不需要制作自定義信號和插槽。
二、一個相關的問題,為什么這些signal/slots go在init () function的window中? app.exec_() 是否連續運行init ()? 實例化 object 然后在應用程序循環中運行“更新” function 不是更明智嗎?
您可以從init () 連接信號/插槽。 但是在那個地方建立連接通常非常方便。 在大多數情況下,沒有機會斷開連接。如果您不想連接,您可以使用blockSignals()
方法阻止連接。
因此,為了證明這一點,您可以嘗試在某處編寫測試代碼以在__init__
之后建立連接。 例如,用於制作信號&槽的信號&槽。
app.exec_()
運行一個循環,但不會一遍又一遍地運行__init__()
。 app.exec_()
正在等待用戶輸入,eventHandler,例如keyPressEvent
, mousePressEvent
。 特別是用於顯示 GUI 的paintEvent()
。 init只被調用一次。 它的變量被分配到您的計算機地址 memory 中。
一遍遍地調用init意味着memory被一遍遍地重寫。Memory主要是為了避免這種浪費。
如果您在使用您的應用程序后通過keyPressEvent
或mousePressEvent
或 signal&slot 機制更改變量的內容,則將 memory 的分配地址改寫為其他內容。
我認為更新是在更改之后調用的。 這是為了根據新變量更新 GUI 表面信息。
感謝@Haru的幫助,我想通了:
這是相關代碼:
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
...
...
...
self.comboBox.textActivated['QString'].connect(self.new_selection)
def new_selection(self):
if self.comboBox.currentText() == 'A':
self.lineEdit.setText('You chose B')
elif self.comboBox.currentText() == 'B':
self.lineEdit.setText('You chose B')
elif self.comboBox.currentText() == 'C':
self.lineEdit.setText('You chose C')
其中,在選擇組合框項目時,一些文本(不是組合框中的選項之一)會顯示在行編輯中。 上述代碼適用於 window 的初始化,但在做出新選擇時無效。
完整代碼在這里:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(493, 124)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setObjectName("comboBox")
self.comboBox.addItem("")
self.comboBox.addItem("")
self.comboBox.addItem("")
self.horizontalLayout.addWidget(self.comboBox)
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 493, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.comboBox.textActivated['QString'].connect(self.new_selection)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.comboBox.setItemText(0, _translate("MainWindow", "A"))
self.comboBox.setItemText(1, _translate("MainWindow", "B"))
self.comboBox.setItemText(2, _translate("MainWindow", "C"))
def new_selection(self):
if self.comboBox.currentText() == 'A':
self.lineEdit.setText('You chose B')
elif self.comboBox.currentText() == 'B':
self.lineEdit.setText('You chose B')
elif self.comboBox.currentText() == 'C':
self.lineEdit.setText('You chose C')
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv) # Whole application
MainWindow = QtWidgets.QMainWindow() # create the actual window
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show() # Actually show the window
sys.exit(app.exec_())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.