【问题标题】:PyQt: Wrapping Dialog from QDesigner and Connect pushbuttonPyQt:来自 QDesigner 的包装对话框和连接按钮
【发布时间】:2015-03-04 10:46:31
【问题描述】:

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

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

我的主程序是这样的:

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

【问题讨论】:

  • 您应该尝试创建一个较小的示例来准确确定问题所在。示例中有很多与您的问题无关的代码。祝你好运!
  • 感谢您的评论普洛夫。文件“UI_Test.py”是用“pyuic”自动生成的。所以基本上这里应该没有问题。它只是为了提供一个运行示例而添加的。我试图在“Testdialog”中包含“Ui_Dialog”类的代码。在这种情况下,程序正在运行。所以我希望问题出在我的类“Testdialog”从“Ui_Dialog”继承的方式上。或者Dialog在主类中的执行方式。不幸的是,我找不到一种方法来减少示例并保持相同的行为。
  • 好的,我可以使用帮助表单link 来解决它(示例2)。无论如何,我仍然不明白为什么初始版本不起作用。
  • 我只想说,开始使用QtDesigner就可以了。但我不会推荐它。最好从基础学习并理解所有内容;)
  • @BerndGit:我做了一个新的例子,向你展示它可以更容易实现。 pyuic 生成的代码不是真正可读且不稳定的。这是我的意见。我也尝试从 QtDesigner 开始,但后来我从头开始学习。

标签: python pyqt signals-slots qpushbutton pyuic


【解决方案1】:

原代码中的问题在这一段:

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

你想要的是这样的:

if __name__ == '__main__':

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

原代码不起作用的原因,是因为信号连接只在Testdialog__init__中进行。你创建的Testdialog 的实例已经添加了所有的用户界面,并且所有的信号都正确连接了,但你从来没有真正展示过它!相反,您会显示您创建的 other 对话框(即 Dialog),它会获得一个 new 添加到其中的相同 ui 的副本(通过 setupUi) - 但是没有信号连接。

【讨论】:

  • 谢谢你,Ekhumoro。这解释了很多。出现这个问题是因为我只是从网上复制代码而没有完全理解。现在我看得更清楚了。
【解决方案2】:

嘿,这是我的答案。我只是在没有 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。因为像这个例子一样,它更清晰,代码更少并且你会更好地理解后台发生的事情。希望我的回答对你有所帮助。

【讨论】:

  • 感谢您的评论。正如我在问题的第二段中提到的,我已经有一个类似的例子(没有继承)工作。因为 QtDesinger 也提供了一些我想使用它的舒适性。不管怎样,谢谢你花时间。
猜你喜欢
  • 2015-01-01
  • 1970-01-01
  • 2021-12-11
  • 2012-07-31
  • 2016-05-16
  • 2021-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多