PySide:容器中 QGraphicsView 的事件过滤器 class

PySide: event-filter for QGraphicsView in container class

我在导入的子小部件和父主要 window 和小部件的类似小部件之间进行通信。但是,当涉及到作为模块和子小部件导入的 QGraphicsScene 小部件时,我感到很困惑。我在下面放了一些简化的文件。因此,QGraphicsView(来自 QGraphicsScene)将是我需要向主 window.

中的其他 QWidget 发出和发出事件信号的实际小部件

如果我将所有 类 都放在一个文件中,它可以工作,但如果我将 类 作为单独的模块,我会收到 "does not have attribute" 错误,特别是在此处的简单版本中QGraphicsScene.viewport

Attribute Error "self.graphicsView.viewport().installEventFilter(self)"

我想复合图形小部件现在实际上是一个 QWidget,我没有为 QGraphicsView 元素初始化导入模块 functions/attributes。事情是,我希望它以这种方式存在,这样我就可以分离不同模块的 GUI 元素和功能。到目前为止我使用的其他方法是从 QObjects 派生的直接 QWidget 到 QWidget 信号,所以工作正常,但我无法使用导入的 QGraphicsScene 到 QWidgets 实现相同的效果,因为它在尝试到达 QGraphicsView 时出错主要window。同样,如果所有 类 都存在于一个大文件中,一切都很好。

有哪位好心人可以指出我的错误吗?我怎样才能将模块脚本分开,使其与单个脚本的行为方式相同?

工作单个脚本:

# QWidgetAll.py
from PySide import QtGui, QtCore

class GraphicsView(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.graphicsView = QtGui.QGraphicsView(self)
        self.graphicsLabel = QtGui.QLabel("Graphics View within QWidget")
        self.graphicsView.setMouseTracking(True)
        self.graphicsView.viewport().installEventFilter(self)
        self.edit = QtGui.QLineEdit(self)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.graphicsLabel)
        layout.addWidget(self.edit)      
        layout.addWidget(self.graphicsView)

    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.MouseMove and
            source is self.graphicsView.viewport()):
            pos = event.pos()
            self.edit.setText('x: %d, y: %d' % (pos.x(), pos.y()))
        return QtGui.QWidget.eventFilter(self, source, event)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = GraphicsView()
    window.show()
    window.resize(200, 100)
    sys.exit(app.exec_())

同一个文件作为单独的模块。 qWidgetView.py 属性错误的错误:

# qWidgetView.py
from PySide import QtGui, QtCore
from qGraphicView import GraphicsView

class WidgetView(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.graphicsView = GraphicsView()
        self.graphicsView.setMouseTracking(True)
        self.graphicsView.viewport().installEventFilter(self)
        self.edit = QtGui.QLineEdit(self)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.edit)      
        layout.addWidget(self.graphicsView)

    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.MouseMove and
            source is self.graphicsView.viewport()):
            pos = event.pos()
            self.edit.setText('x: %d, y: %d' % (pos.x(), pos.y()))
        return QtGui.QWidget.eventFilter(self, source, event)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = WidgetView()
    window.show()
    window.resize(200, 100)
    sys.exit(app.exec_())

使用导入的 qGraphicView.py 模块:

# qGraphicView.py
from PySide import QtGui, QtCore

class GraphicsView(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.graphicsView = QtGui.QGraphicsView(self)
        self.graphicsLabel = QtGui.QLabel("Graphics View within QWidget")
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.graphicsLabel) 
        layout.addWidget(self.graphicsView)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = GraphicsView()
    window.show()
    window.resize(200, 100)
    sys.exit(app.exec_())

您需要过滤 QGraphicsView 的事件,它是 GraphicsView class 的子窗口小部件,因为您只想在图形视图本身上移动鼠标,而不是整个容器小部件。所以我会建议这样的事情:

qGraphicView.py模块:

class GraphicsView(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.graphicsView = QtGui.QGraphicsView(self)
        self.graphicsView.setMouseTracking(True)
        self.graphicsLabel = QtGui.QLabel("Graphics View within QWidget")
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.graphicsLabel)
        layout.addWidget(self.graphicsView)

    def viewport(self):
        return self.graphicsView.viewport()

qWidgetView.py模块:

class WidgetView(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.graphicsView = GraphicsView()
        self.graphicsView.viewport().installEventFilter(self)
        self.edit = QtGui.QLineEdit(self)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.edit)
        layout.addWidget(self.graphicsView)