5

I'm starting to learn Python and PyQt. Currently I am fighting with a very basic problem about connecting signals and Slots, with Dialog forms generated form QDesigner. I want to connect a pushbutton from a QDialog. The code does not generate an error. The Dialog is show, as expected. But with clicking on the pushbuttons nothing happens.

Alternatively I have tried included the code form Ui_Dialog directly in my target class Testdialog. Then the connection was working. It seems like i made an error in inheriting the properties from Ui_Dialog to Testdialog and/or in the way I want to execute the Dialog.

My main program looks like:

from __future__ import unicode_literals
import sys

from PyQt4 import *
from PyQt4 import QtGui
from PyQt4.QtCore import SIGNAL, QObject

import UI_Test



class Testdialog(QtGui.QDialog, UI_Test.Ui_Dialog):
    def __init__(self,parent=None):
        super(Testdialog, self).__init__(parent)
        self.setupUi(self)
        print("Connect buttons") # gives the expected output

        self.connect(self.pushButton_Ok, SIGNAL("clicked()"), self.clickedOk)
        self.connect(self.pushButton_Cancel, SIGNAL("clicked()"), self.clickedCancel)

        # Alternativly I have tríed the following without improvement:
        # self.pushButton_Ok.clicked.connect(self.clickedOk)
        # QObject.connect(self.pushButton_Cancel, SIGNAL("clicked()"), self.clickedCancel)


    def clickedCancel(self):
        print ("Cancel")  # Question: Why is nothing happening here?


    def clickedOk(self):
        print ("Ok")       # Question: Why is nothing happening here?



if True:
    qApp = QtGui.QApplication(sys.argv)
    Dialog = QtGui.QDialog()
    u = Testdialog()
    u.setupUi(Dialog)
    Dialog.exec_()
    sys.exit(qApp.exec_())

When I click on the bushbuttons nothing happens. It seems like the connection is not working.

What did i do wrong? How tho fix it? What else should be improved?

The form UI_Test.py is nothing special, since it is automatically generated with QtDesigner and pyuic. So basically it should be ok (although I don't understand every detail about the code). In order to provide to a running example, here is the code:

# File: UI_Test.py
from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(271, 70)
        self.pushButton_Ok = QtGui.QPushButton(Dialog)
        self.pushButton_Ok.setGeometry(QtCore.QRect(20, 20, 93, 28))
        self.pushButton_Ok.setObjectName(_fromUtf8("pushButton_Ok"))
        self.pushButton_Cancel = QtGui.QPushButton(Dialog)
        self.pushButton_Cancel.setGeometry(QtCore.QRect(130, 20, 93, 28))
        self.pushButton_Cancel.setObjectName(_fromUtf8("pushButton_Cancel"))

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
        self.pushButton_Ok.setText(_translate("Dialog", "OK", None))
        self.pushButton_Cancel.setText(_translate("Dialog", "Cancel", None))
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
BerndGit
  • 1,530
  • 3
  • 18
  • 47
  • 1
    You should try to create a smaller example to identify exactly where the issue is. There is a lot of code that is not related to your problem in the example. Good luck! – Plouff Jan 11 '15 at 11:50
  • Thank you for your comment Plouff. The file 'UI_Test.py' is gernerated automatically with 'pyuic'. So basically there should be no issue here. It is just added for providing a running example. I tried to include the code from class 'Ui_Dialog' in the 'Testdialog'. In this case the programm is working. So I expect that the issue arises from the way I the class 'Testdialog' is inherited from 'Ui_Dialog'. Or the way the Dialog is executed in the main class. So unfortunatly I couldn find a way to reduce the example and keeping the same behavour. – BerndGit Jan 11 '15 at 22:46
  • Ok, I could solve it with the help form [link](http://pyqt.sourceforge.net/Docs/PyQt4/designer.html), (example 2). Anyhow, I still don't understand why the initial Version was not working. – BerndGit Jan 12 '15 at 22:06
  • I just wanted to say, for starting it's ok to use the QtDesigner. But I would not recommend it. Better learn it from the basics and understand all ;) – ProgrammingIsAwsome Jan 13 '15 at 01:05
  • @BerndGit: I made a new example, to show you that it can be accomplised much easier. The generated code by pyuic is not really readable and understable. That's my opinion. I've also tried to start with the QtDesigner, but then I learnt all from the scratch. – ProgrammingIsAwsome Jan 13 '15 at 01:38

2 Answers2

5

The problem in the original code is in this section:

if True:
    qApp = QtGui.QApplication(sys.argv)
    Dialog = QtGui.QDialog()
    u = Testdialog()
    u.setupUi(Dialog)
    Dialog.exec_()
    sys.exit(qApp.exec_())

What you want instead is something like this:

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    u = Testdialog()
    u.show()
    sys.exit(app.exec_())

The reason why the original code doesn't work, is because the signal connections are only made in the __init__ of Testdialog. The instance of Testdialog you create has all the ui added to it, and all the signals are connected up correctly, but you never actually show it! Instead, you show the other dialog you created (i.e. Dialog), which gets a new copy of the same ui added to it (via setupUi) - but without the signal connections.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thank you, Ekhumoro. That explains a lot. The bub was caused because I just copied code from the net without complete understanding. Now I see it much clearer. – BerndGit Jan 13 '15 at 08:11
1

Hey so here is my answer. I just made the same example without the QtDesigner (just copy paste and runt it):

import sys
from PyQt4 import QtGui, QtCore
from PyQt4.Qt import pyqtSlot

class MyDialog(QtGui.QDialog):
    def __init__(self):
        super(MyDialog, self).__init__()
        self.resize(271, 70)
        self.pushButton_Ok = QtGui.QPushButton(self)
        self.pushButton_Ok.setGeometry(QtCore.QRect(20, 20, 93, 28))
        self.pushButton_Ok.setText("Ok")

        self.pushButton_Cancel = QtGui.QPushButton(self)
        self.pushButton_Cancel.setGeometry(QtCore.QRect(130, 20, 93, 28))
        self.pushButton_Cancel.setText("Cancel")

        # HERE the slots are connected
        self.pushButton_Ok.clicked.connect(self.clickedOk) # new style signal/slot
        self.pushButton_Cancel.clicked.connect(self.clickedCancel) # new style signal/slot

    @pyqtSlot()
    def clickedCancel(self):
        print ("Cancel pressed")

    @pyqtSlot()
    def clickedOk(self):
        print ("Ok pressed")

qApp = QtGui.QApplication(sys.argv)
dial = MyDialog()
dial.show()
sys.exit(qApp.exec_())

I hope you see now what I meant with don't use the QtDesigner. Because like this example it's much more clear and less code and you understand the better what's going on in the background. I hope my answer helped you.

ProgrammingIsAwsome
  • 1,109
  • 7
  • 15
  • Thank you for your comment. As mentioned in my second paragraph of my question, I had already a similar example (without inheriting) working. Because the QtDesinger also offers some comfort I want to use it. Anyhow thank you for the time spend. – BerndGit Jan 13 '15 at 08:17