使用QtDesigner创建pyQt信号/槽

4
我正在尝试编写一个与QGraphicsView交互的程序。我想在QGraphicsView中发生鼠标和键盘事件时收集它们。例如,如果用户单击QGraphicsView小部件,则会获取鼠标位置之类的内容。我可以很容易地硬编码实现它,但我想使用QtDesigner,因为UI将经常更改。
这是gui.py的代码。其中包含一个简单的小部件,其中有一个QGraphicsView。
from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_graphicsViewWidget(object):
    def setupUi(self, graphicsViewWidget):
        graphicsViewWidget.setObjectName(_fromUtf8("graphicsViewWidget"))
        graphicsViewWidget.resize(400, 300)
        graphicsViewWidget.setMouseTracking(True)
        self.graphicsView = QtGui.QGraphicsView(graphicsViewWidget)
        self.graphicsView.setGeometry(QtCore.QRect(70, 40, 256, 192))
        self.graphicsView.setObjectName(_fromUtf8("graphicsView"))

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

    def retranslateUi(self, graphicsViewWidget):
        graphicsViewWidget.setWindowTitle(QtGui.QApplication.translate("graphicsViewWidget", "Form", None, QtGui.QApplication.UnicodeUTF8))

程序的代码如下:
#!/usr/bin/python -d

import sys
from PyQt4 import QtCore, QtGui
from gui import Ui_graphicsViewWidget

class MyForm(QtGui.QMainWindow):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_graphicsViewWidget()
        self.ui.setupUi(self)
        QtCore.QObject.connect(self.ui.graphicsView, QtCore.SIGNAL("moved"), self.test)

    def mouseMoveEvent(self, event):
        print "Mouse Pointer is currently hovering at: ", event.pos()
        self.emit(QtCore.SIGNAL("moved"), event)

    def test(self, event):
        print('in test')

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = MyForm()
    myapp.show()
    sys.exit(app.exec_())

当我运行这段代码时,结果与我想要的相反。我得到了鼠标位置,除了在QGraphicsView内部。
我确定这是我的QObject.connect有问题。但每次我回去阅读信号和槽的相关知识时,它都很合理,但我却无法理解。
请帮忙,我已经纠结了几天了。如果以前问过这个问题,我很抱歉,但我已经查看了所有关于此主题的线程,但无济于事。
谢谢

在你的gui.py文件中,self.graphicsView = MyForm(graphicsViewWidget)这一行会抛出异常,因为MyForm未定义。我不确定你的意思是什么。你能修复这一行吗? - Stephen Terry
抱歉,MyForm 应该是 QtGui.QGraphicsView。我在线程中修复了它,并在我的电脑上运行,现在应该可以工作了。 - Jeff
只是一个建议,如果您使用 from PyQt4.QtGui import *from PyQt4.QtCore import * 导入,您可以删除所有 QtCore.QtGui. 的实例,使代码更易读。 - Blender
1个回答

3

信号必须来自于在UI中定义的QGraphicsView对象。

您可以创建一个从QGraphicsView派生的类,如下所示:

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyView(QGraphicsView):
    moved = pyqtSignal(QMouseEvent)

    def __init__(self, parent = None):
        super(MyView, self).__init__(parent)

    def mouseMoveEvent(self, event):
        # call the base method to be sure the events are forwarded to the scene
        super(MyView, self).mouseMoveEvent(event)

        print "Mouse Pointer is currently hovering at: ", event.pos()
        self.moved.emit(event)

然后,在设计器中:

  • 右键单击 QGraphicsView,然后选择提升为
  • 提升类名 字段中输入类名(例如"MyView")
  • 头文件 字段中输入该类所在的文件名,但不包括 .py 扩展名
  • 点击 添加 按钮,然后点击 提升 按钮。

然后,您可以使用 pyuic4 重新生成您的文件 gui.py


非常好的解释,谢谢 :) 我只有一个小问题,是否有可能让QtDesigner知道您在文件中创建了哪些插槽/信号(或者反过来)。不必定义两次似乎是没有意义的。 - Wolph
@WoLpH 我猜你可以创建一个插件(像这样),但如果你只在一个项目中使用该类,那么似乎有些复杂。 - alexisdm
谢谢建议,在这种情况下,插件可能会带来更多麻烦。但是现在很容易集成,所以我会将它们混合使用 :) - Wolph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接