I couldn't understand the connectSlotsByName() method which is predominently used by pyuic4.. As far the class is single in a PyQt file it's ok since we can use self which will be associated with a single object throughout.. But when we try to use various classes from different files the problem and the need to use connectSlotsByName() arises.. Here's what i encountered which is weird..
I created a stacked widget..
I placed my first widget on it.. It has a button called "Next >".
On clicking next it hides the current widget and adds another widget which has the "click me" button..
The problem here is the click event for "click me" button in second is not captured.. It's a minimal example that i can give for my original problem.. Please help me..
This is file No.1..(which has the parent stacked widget and it's first page). On clicking next it adds the second page which has "clickme" button in file2..
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_())
Here's 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")
Though in both the widgets(i mean pages)
QtCore.QMetaObject.connectSlotsByName(self.page)
the clicked signal in second dialog isn't getting processed. Thanks in advance.. Might be a beginner question..
A better question is "Why not just use new-style signals and slots?". They're much simpler and don't require any weird naming conventions:
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_())
At first, here is the minimal working example:
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_())
When you trying to connect slots by name, you must give proper names to the slots and then someone (moc, uic, or you by calling connectSlotsByName) must connect them. Proper name for such a slot is: "on_PyQtObjectName_PyQtSignalName".
Note, that, if I'd omitted @QtCore.pyqtSlot() in the example, slot would be executed once for every appropriate overload (twice in this case).
You DO need to call connectSlotsByNames directly, cause there is no moc, which do it for you when you use QT in C++, and you do not use uic and .ui file. If you want to connect slots implicitly (I'm always doing so, except slots, connected directly in .ui), you'd better use more pytonish syntaxe: button.clicked.connect(self._mySlot).
And take a look at https://riverbankcomputing.com/static/Docs/PyQt5/signals_slots.html#connecting-slots-by-name
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With