我想使用自动连接功能。我正在使用这个例子:
http://www.eurion.net/python-snippets/snippet/Connecting%20signals%20and%20slots.html
它可以工作,但我想创建自己的信号和自己的插槽,这个例子使用内置信号。
例如,这是一个带有自定义插槽的自定义信号,但不起作用:
import sys
from PyQt4 import QtGui, QtCore
class SignalsAndSlots(QtGui.QWidget):
testSignal = QtCore.pyqtSignal(str,name='testSignal')
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setObjectName('testObject')
self.label = QtGui.QLabel(self)
QtCore.QMetaObject.connectSlotsByName(self)
self.emitSignal()
def emitSignal(self):
self.testSignal.emit('message')
@QtCore.pyqtSlot(str,name='on_testObject_testSignal')
def autoSlot(self,msg):
self.label.setText(msg)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
gui = SignalsAndSlots()
gui.show()
app.exec_()
非常感谢
答案 0 :(得分:2)
Ber是对的。这就是pyqt documentation所说的:
QMetaObject.connectSlotsByName 以递归方式搜索给定对象的所有子对象 [...]
以下是自定义信号的简单示例:
import sys
from PyQt4 import QtGui, QtCore
class CustomButton(QtGui.QPushButton):
custom_clicked = QtCore.pyqtSignal(str, name='customClicked')
def mousePressEvent(self, event):
self.custom_clicked.emit("Clicked!")
class SignalsAndSlots(QtGui.QWidget):
def __init__(self):
QtGui.QMainWindow.__init__(self)
layout = QtGui.QHBoxLayout(self)
self.custom_button = CustomButton("Press Me", self)
self.custom_button.setObjectName('customButton')
self.label = QtGui.QLabel("Nothing...", parent=self)
layout.addWidget(self.custom_button)
layout.addWidget(self.label)
QtCore.QMetaObject.connectSlotsByName(self)
@QtCore.pyqtSlot(str, name='on_customButton_customClicked')
def autoSlot(self, msg):
self.label.setText(msg)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
gui = SignalsAndSlots()
gui.show()
app.exec_()
但我认为你应该考虑不使用对象名称。新式信号连接更简洁。这是相同的应用程序:
import sys
from PyQt4 import QtGui, QtCore
class CustomButton(QtGui.QPushButton):
custom_clicked = QtCore.pyqtSignal(str)
def mousePressEvent(self, event):
self.custom_clicked.emit("Clicked!")
class SignalsAndSlots(QtGui.QWidget):
def __init__(self):
QtGui.QMainWindow.__init__(self)
layout = QtGui.QHBoxLayout(self)
self.custom_button = CustomButton("Press Me", self)
self.custom_button.setObjectName('customButton')
self.label = QtGui.QLabel("Nothing...", parent=self)
layout.addWidget(self.custom_button)
layout.addWidget(self.label)
self.custom_button.custom_clicked.connect(self.on_clicked)
def on_clicked(self, msg):
self.label.setText(msg)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
gui = SignalsAndSlots()
gui.show()
app.exec_()
答案 1 :(得分:0)
我对文档进行了一些调查。的 QtCore.QMetaObject.connectSlotsByName()
。
为此,我制作了一个MCVE来收集无法正常运行和正常运行的东西:
#!/usr/bin/python3
import sys
from PyQt5.QtCore import QT_VERSION_STR
from PyQt5.QtCore import QMetaObject, pyqtSlot
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QWidget
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
# build GUI
qMain = QWidget()
qVBox = QVBoxLayout()
qBtnPreview1 = QPushButton("Preview 1")
qBtnPreview1.setObjectName("preview1")
qVBox.addWidget(qBtnPreview1)
qBtnPreview2 = QPushButton("Preview 2")
qBtnPreview2.setObjectName("preview2")
qVBox.addWidget(qBtnPreview2)
qBtnPreview3 = QPushButton("Preview 3")
qBtnPreview3.setObjectName("preview3")
qVBox.addWidget(qBtnPreview3)
qBtnPreview4 = QPushButton("Preview 4")
qBtnPreview4.setObjectName("preview4")
qVBox.addWidget(qBtnPreview4)
qBtnPreview5 = QPushButton("Preview 5")
qBtnPreview5.setObjectName("preview5")
qVBox.addWidget(qBtnPreview5)
qBtnPreview6 = QPushButton("Preview 6")
qBtnPreview6.setObjectName("preview6")
qVBox.addWidget(qBtnPreview6)
qMain.setLayout(qVBox)
self.setCentralWidget(qMain)
# install signal handlers
qBtnPreview1.clicked.connect(lambda: print("preview1 clicked."))
qBtnPreview2.clicked.connect(lambda: print("preview2 clicked."))
qBtnPreview3.clicked.connect(lambda: print("preview3 clicked."))
qBtnPreview4.clicked.connect(lambda: print("preview4 clicked."))
qBtnPreview5.clicked.connect(lambda: print("preview5 clicked."))
qBtnPreview6.clicked.connect(lambda: print("preview6 clicked."))
QMetaObject.connectSlotsByName(self)
@pyqtSlot()
def preview1(self):
print("MainWindow.preview1() called.")
@pyqtSlot()
def preview2_clicked(self):
print("MainWindow.preview2_clicked() called.")
@pyqtSlot()
def on_preview3(self):
print("MainWindow.on_preview3() called.")
@pyqtSlot()
def on_preview4_clicked(self):
print("MainWindow.on_preview4_clicked() called.")
@pyqtSlot(name='on_preview5_clicked')
def preview5_clicked(self):
print("MainWindow.preview5_clicked() called.")
def on_preview6_clicked(self):
print("MainWindow.on_preview6_clicked() called.")
if __name__ == '__main__':
print("Qt Version: {}".format(QT_VERSION_STR))
app = QApplication(sys.argv)
# build GUI
qWinMain = MainWindow()
qWinMain.show()
# runtime loop
sys.exit(app.exec_())
输出:
$ ./testQMetaObjectConnectSlotsByName.py
Qt Version: 5.9.3
单击六个按钮中的每个按钮后,我得到:
preview1 clicked.
preview2 clicked.
preview3 clicked.
preview4 clicked.
MainWindow.on_preview4_clicked() called.
preview5 clicked.
MainWindow.preview5_clicked() called.
preview6 clicked.
MainWindow.on_preview6_clicked() called.
MainWindow.on_preview6_clicked() called.
观察:
MainWindow.preview1()
,MainWindow.preview2_clicked()
,MainWindow.on_preview3()
未连接。它们不遵循QtCore.QMetaObject.connectSlotsByName()
的必需约定。
MainWindow.on_preview4_clicked()
通过名称连接-正确遵循所需的名称约定。
MainWindow.preview5_clicked()
也已连接–通过@pyqtSlot(name='on_preview5_clicked')
给出所需的名称。
MainWindow.on_preview6_clicked()
也已连接-即使未明确将其标记为插槽。 (但是,由于某种原因,它可能会被两次调用。)
显式连接在任何情况下都可以工作,并且对我来说更可靠。
更多读数:
实际上,这是我对另一个问题(SO: How to display two images in each Qlabel PyQt5)的回答,直到我意识到QtCore.QMetaObject.connectSlotsByName()
不太可能在该问题中起作用。
因此,我将其移至此处,即使问题有些陈旧,也可能更合适。