5

我开始学习 Python 和 PyQt。目前,我正在解决一个关于连接信号和插槽的非常基本的问题,使用从 QDesigner 生成的对话框表单。我想从 QDialog 连接一个按钮。该代码不会产生错误。对话框按预期显示。但是点击按钮没有任何反应。

或者,我尝试将代码表单Ui_Dialog直接包含在我的目标类Testdialog中。然后连接正常。似乎我在从Ui_DialogtoTestdialog和/或以我想要执行对话框的方式继承属性时出错了。

我的主程序如下所示:

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_())

当我点击按钮时,什么也没有发生。似乎连接不起作用。

我做错了什么?怎么修呢?还有什么需要改进的?

该表单UI_Test.py没有什么特别之处,因为它是使用 QtDesigner 和 pyuic 自动生成的。所以基本上应该没问题(虽然我不了解代码的每一个细节)。为了提供一个运行示例,这里是代码:

# 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))
4

2 回答 2

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.

于 2015-01-13T02:54:04.907 回答
1

嘿,这是我的答案。我只是在没有 QtDesigner 的情况下制作了相同的示例(只需复制粘贴并运行它):

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_())

我希望你现在明白我的意思是不要使用 QtDesigner。因为像这个例子一样,它更清晰,代码更少你更好地理解后台发生的事情。希望我的回答对你有所帮助。

于 2015-01-13T01:34:11.450 回答