我无法理解pyuic4主要使用的connectSlotsByName()方法。到目前为止,这个类在PyQt文件中是单一的,因为我们可以使用self,它将与整个单个对象相关联。但是当我们尝试使用来自不同文件的各种类时,问题和使用connectSlotsByName()的需要出现了..这就是我遇到的奇怪的事情。
我创建了一个堆叠小部件..
我把第一个小部件放在上面..它 有一个名为“下一步>”的按钮。
点击下一步,它会隐藏当前 小部件并添加另一个具有“单击我”按钮的小部件..
这里的问题是没有捕获第二个“点击我”按钮的点击事件..这是我可以为我的原始问题提供的最小例子..请帮助我..
这是文件No.1 ..(具有父级堆叠小部件,它是第一页)。点击下一步,它会添加第二页,其中包含file2中的“clickme”按钮。
from PyQt4 import QtCore, QtGui
import file2
class Ui_StackedWidget(QtGui.QStackedWidget):
def __init__(self,parent=None):
QtGui.QStackedWidget.__init__(self,parent)
self.setObjectName("self")
self.resize(484, 370)
self.setWindowTitle(QtGui.QApplication.translate("self", "stacked widget", None, QtGui.QApplication.UnicodeUTF8))
self.createWidget1()
def createWidget1(self):
self.page=QtGui.QWidget()
self.page.setObjectName("widget1")
self.pushButton=QtGui.QPushButton(self.page)
self.pushButton.setGeometry(QtCore.QRect(150, 230, 91, 31))
self.pushButton.setText(QtGui.QApplication.translate("self", "Next >", None, QtGui.QApplication.UnicodeUTF8))
self.addWidget(self.page)
QtCore.QMetaObject.connectSlotsByName(self.page)
QtCore.QObject.connect(self.pushButton,QtCore.SIGNAL('clicked()'),self.showWidget2)
def showWidget2(self):
self.page.hide()
obj=file2.widget2()
obj.createWidget2(self)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
ui = Ui_StackedWidget()
ui.show()
sys.exit(app.exec_())
这是file2
from PyQt4 import QtGui,QtCore
class widget2():
def createWidget2(self,parent):
self.page = QtGui.QWidget()
self.page.setObjectName("page")
self.parent=parent
self.groupBox = QtGui.QGroupBox(self.page)
self.groupBox.setGeometry(QtCore.QRect(30, 20, 421, 311))
self.groupBox.setObjectName("groupBox")
self.groupBox.setTitle(QtGui.QApplication.translate("self", "TestGroupBox", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton = QtGui.QPushButton(self.groupBox)
self.pushButton.setGeometry(QtCore.QRect(150, 120, 92, 28))
self.pushButton.setObjectName("pushButton")
self.pushButton.setText(QtGui.QApplication.translate("self", "Click Me", None, QtGui.QApplication.UnicodeUTF8))
self.parent.addWidget(self.page)
self.parent.setCurrentWidget(self.page)
QtCore.QMetaObject.connectSlotsByName(self.page)
QtCore.QObject.connect(self.pushButton,QtCore.SIGNAL('clicked()'),self.printMessage)
def printMessage(self):
print("Hai")
虽然在两个小部件中(我的意思是页面)
QtCore.QMetaObject.connectSlotsByName(self.page)
第二个对话框中的单击信号未得到处理。在此先感谢..可能是一个初学者问题..
答案 0 :(得分:4)
首先,这是最小的工作示例:
from sys import argv, exit
from PyQt4 import QtCore, QtGui
class widget2(QtGui.QWidget):
def __init__(self, args):
self.app = MainApp(args)
QtGui.QWidget.__init__(self)
self.setObjectName('I')
self._layout = QtGui.QVBoxLayout(self)
self.setLayout(self._layout)
self.pushButtoninWidget2 = QtGui.QPushButton(self)
self.pushButtoninWidget2.setObjectName("pushButtoninWidget2")
self.pushButtoninWidget2.setText('Click NOW!')
self._layout.addWidget(self.pushButtoninWidget2)
QtCore.QMetaObject.connectSlotsByName(self)
@QtCore.pyqtSlot()
def on_pushButtoninWidget2_clicked(self):
print("Hai")
class MainApp(QtGui.QApplication):
def __init__(self, args):
QtGui.QApplication.__init__(self, args)
if __name__ == "__main__":
main = widget2(argv)
main.show()
exit(main.app.exec_())
当您尝试按名称连接插槽时,必须为插槽指定正确的名称,然后某人(moc,uic或您通过调用connectSlotsByName)必须连接它们。这样一个插槽的正确名称是:“on_PyQtObjectName_PyQtSignalName”。
注意,如果我在示例中省略了@ QtCore.pyqtSlot(),则每次适当的重载都会执行一次插槽(在这种情况下为两次)。
您需要直接调用connectSlotsByNames,因为没有moc,当您在C ++中使用QT时,它会为您执行此操作,并且您不使用uic和.ui文件。如果你想隐式连接插槽(我总是这样做,除了插槽,直接连接在.ui中),你最好使用更多的pytonish语法:button.clicked.connect(self._mySlot)。
并查看http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/pyqt4ref.html#connecting-slots-by-name
答案 1 :(得分:2)
您无需致电connectSlotsByName()
,只需删除这些行。
在file2
中,调用QtCore.QMetaObject.connectSlotsByName(self.page)
会尝试执行此操作:
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL('clicked()'), self.on_pushButton_clicked())
由于未定义self.on_pushBotton_clicked()
插槽,因此无法使用。
我发现在PyQt中创建自己的连接是最简单的...我建议从这两个类中删除对connectSlotsByName
的调用...你不需要它。
另外,你的wdiget1
类应设置它的pushButton名称(最好是“pushButton”之外的其他名称,以避免与widget2
中的按钮混淆。)
答案 2 :(得分:2)
更好的问题是“为什么不使用新式信号和插槽?”。它们更简单,不需要任何奇怪的命名约定:
from sys import argv, exit
from PyQt4 import QtCore, QtGui
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
self._layout = QtGui.QVBoxLayout()
self.setLayout(self._layout)
self._button = QtGui.QPushButton()
self._button.setText('Click NOW!')
self._layout.addWidget(self._button)
self._button.clicked.connect(self._printMessage)
@QtCore.pyqtSlot()
def _printMessage(self):
print("Hai")
if __name__ == "__main__":
app = QtGui.QApplication(argv)
main = MyWidget()
main.show()
exit(app.exec_())
答案 3 :(得分:1)
非常感谢jcoon的回复..但是经过很长一段时间,我的头靠在墙上,我找到了解决方案..
问题是......
self.obj=test_reuse_stacked1.widget2()
self.obj.createWidget2(self)
而不是obj ..
答案 4 :(得分:0)
这是@MarkVisser的QT4代码已更新为QT5:
from sys import argv, exit
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget
class MyWidget(QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
self._layout = QtWidgets.QVBoxLayout()
self.setLayout(self._layout)
self._button = QtWidgets.QPushButton()
self._button.setText('Click NOW!')
self._layout.addWidget(self._button)
self._button.clicked.connect(self._print_message)
@QtCore.pyqtSlot()
def _print_message(self):
print("Hai")
if __name__ == "__main__":
app = QApplication(argv)
main = MyWidget()
main.show()
exit(app.exec_())
答案 5 :(得分:0)
另一个最小工作示例,使用 Qt for Python 又名 PySide2/6。
主要成分:
.setObjectName
@QtCore.Slot()
修饰self
)from PySide2 import QtCore, QtWidgets
# or from PySide6 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self):
super(Widget, self).__init__()
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton(self)
self.button.setObjectName('button')
self.button.setText('Click Me!')
layout.addWidget(self.button)
QtCore.QMetaObject.connectSlotsByName(self)
@QtCore.Slot()
def on_button_clicked(self):
print(f'Hai from {self.sender()}')
if __name__ == '__main__':
app = QtWidgets.QApplication([])
main = Widget()
main.show()
app.exec_()
我真的不能再小了?