Reputation: 1047
I'm trying to port a small Qt C++ app to Python using PyQt5 but I am having trouble with the most basic stuff right now.
I've used the pyuic utility to transform a .ui file to its corresponding .py file representing the dialog's statically defined UI and exactly two signal/slot pairs (two buttons). The exact error is "'QDialog' object has no attribute 'pushButtonStartClick'" and while I understand what it is describing I don't know how exactly to fix it. I'm not even sure custom slots can be defined in the Ui class. If that is true, it represents a pretty huge limitation. I'm using PyQt 5.4 and Python 2.7 on a Windows machine.
Additional info - simple tutorial I've been reading and trying to emulate.
Thank you in advance.
Generated .py file containing the UI class (part of it, source .ui file is here):
class Ui_NewGameDialog(object):
def setupUi(self, NewGameDialog):
NewGameDialog.setObjectName("NewGameDialog")
NewGameDialog.setWindowModality(QtCore.Qt.ApplicationModal)
NewGameDialog.resize(265, 200)
#
# ...
#
self.retranslateUi(NewGameDialog)
# part where it breaks apart
self.pushButtonStart.clicked.connect(NewGameDialog.pushButtonStartClick)
self.pushButtonCancel.clicked.connect(NewGameDialog.pushButtonCancelClick)
QtCore.QMetaObject.connectSlotsByName(NewGameDialog)
Class that inherits it:
class NewGameDialog(Ui_NewGameDialog):
def __init__(self, dialog):
Ui_NewGameDialog.__init__(self)
self.setupUi(dialog)
dialog.setFixedSize(dialog.size())
dialog.setWindowFlags(
dialog.windowFlags() ^ QtCore.Qt.WindowContextHelpButtonHint
)
@pyqtSlot(name="pushButtonStartClick")
def pushButtonStartClick(self):
pass
@pyqtSlot(name="pushButtonCancelClick")
def pushButtonCancelClick(self):
pass
Initialization:
if __name__ == "__main__":
app = QApplication(sys.argv)
dialog = QtWidgets.QDialog()
ui = NewGameDialog(dialog)
dialog.show()
sys.exit(app.exec_())
Upvotes: 1
Views: 326
Reputation: 6214
I think setupUi method was getting a wrong kind of object, since QDialog doesn't have those pushButtonStartClick
and pushButtonCancelClick
.
class NewGameDialog(QtGui.QDialog, Ui_NewGameDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
Ui_NewGameDialog.__init__(self)
self.setupUi(self)
self.setFixedSize(self.size())
self.setWindowFlags(
self.windowFlags() ^ QtCore.Qt.WindowContextHelpButtonHint
)
@pyqtSlot(name="pushButtonStartClick")
def pushButtonStartClick(self):
pass
@pyqtSlot(name="pushButtonCancelClick")
def pushButtonCancelClick(self):
pass
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
dialog = NewGameDialog()
dialog.show()
sys.exit(app.exec_())
Without multiple inheritance:
class NewGameDialog(QtGui.QDialog):
def __init__(self):
super(NewGameDialog, self).__init__()
self.ui = Ui_NewGameDialog()
self.ui.setupUi(self)
...
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
dialog = NewGameDialog()
Upvotes: 1
Reputation: 11869
The answer by @JJHakala (that uses multiple inheritance) is option 3 in the PyQt documentation. Option 2 also suits your situation (this is a slightly more elegant version of the "without multiple inheritance" option presented in J. J. Hakala's edit, based on the example in the PyQt docs):
class NewGameDialog(QtWidgets.QDialog):
def __init__(self):
QtWidgets.QDialog.__init__(self)
self.ui = Ui_NewGameDialog()
self.ui.setupUi(self)
self.setFixedSize(self.size())
self.setWindowFlags(
self.windowFlags() ^ QtCore.Qt.WindowContextHelpButtonHint
)
@pyqtSlot(name="pushButtonStartClick")
def pushButtonStartClick(self):
pass
@pyqtSlot(name="pushButtonCancelClick")
def pushButtonCancelClick(self):
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
dialog = NewGameDialog()
dialog.show()
sys.exit(app.exec_())
Upvotes: 1