1

我正在使用 Pyside 创建一个交互式子类 QGraphicsView - 包含一些子类 QGraphicsItems。它在自己的模块中运行良好并接收鼠标事件。

但是当用作另一个文件中的模块并合并到另一个布局中时 - 我的鼠标事件没有被触发。但是 .itemChange 正在工作。除了鼠标事件之外的一切。我没有使用悬停等跟踪事件。我正在使用 mousePressEvent 和 mouseReleaseEvent。

我已经看到关于设置“setMouseTracking”的 c++ 响应,但这是针对小部件的,我的 QGraphicsItems 已添加为项目而不是小部件。所以当我调用这个函数时,它告诉我它不存在于项目中。这似乎也适用于悬停类型的事件——我不需要。我相信我正在正确地进行子类化,并将事件传递给父类。正如我在开始时所说的 - 我的代码在独立文件中运行良好。

有什么想法我忘了做什么吗?

这是独立的工作程序:另存为 test_subclass_module.py

import sys
import weakref
import math
from PySide import QtCore, QtGui



###
class Edge(QtGui.QGraphicsItem):
    Type = QtGui.QGraphicsItem.UserType + 2

    def __init__(self, sourceNode, destNode):
        QtGui.QGraphicsItem.__init__(self)
        #
        self.sourcePoint = QtCore.QPointF()
        self.destPoint = QtCore.QPointF()
        self.setAcceptedMouseButtons(QtCore.Qt.NoButton)
        self.source = weakref.ref(sourceNode)
        self.dest = weakref.ref(destNode)
        self.source().addEdge(self)
        self.dest().addEdge(self)
        self.set_index()
        self.adjust()

    def type(self):
        return Edge.Type

    def sourceNode(self):
        return self.source()

    def setSourceNode(self, node):
        self.source = weakref.ref(node)
        self.adjust()

    def destNode(self):
        return self.dest()

    def setDestNode(self, node):
        self.dest = weakref.ref(node)
        self.adjust()

    def set_index(self):
        self.setToolTip(self.source().label)

    def adjust(self):
        # do we have a line to draw ?
        if  self.source() and self.dest():
            line = QtCore.QLineF(self.mapFromItem(self.source(), 0, 0), self.mapFromItem(self.dest(), 0, 0))
            length = line.length()
            if length > 20:
                edgeOffset = QtCore.QPointF((line.dx() * 10) / length, (line.dy() * 10) / length)
                self.prepareGeometryChange()
                self.sourcePoint = line.p1() + edgeOffset
                self.destPoint   = line.p2() - edgeOffset
            else: # want to make sure line not drawn
                self.prepareGeometryChange()
                self.sourcePoint = self.destPoint 

    def boundingRect(self):
        # do we have a line to draw ?
        if not self.source() or not self.dest():
            return QtCore.QRectF()
        else:
            extra = 1
            return QtCore.QRectF(self.sourcePoint,
                                 QtCore.QSizeF(self.destPoint.x() - self.sourcePoint.x(),
                                               self.destPoint.y() - self.sourcePoint.y())).normalized().adjusted(-extra, -extra, extra, extra)

    def paint(self, painter, option, widget):
        if self.source() and self.dest():
            # Draw the line itself.
            line = QtCore.QLineF(self.sourcePoint, self.destPoint)
            if line.length() > 0.0:
                painter.setPen(QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
                painter.drawLine(line)

###
class Node(QtGui.QGraphicsItem):
    Type = QtGui.QGraphicsItem.UserType + 1

    def __init__(self, graphWidget, time, temp, pos):
        QtGui.QGraphicsItem.__init__(self)

        self.graph = weakref.ref(graphWidget)
        self.edgeList = []
        self.set_index(pos)
        self.newPos = QtCore.QPointF()
        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable)
        self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges)
        self.setCacheMode(self.DeviceCoordinateCache)
        self.setZValue(-1)
        #
        self.temp = temp
        self.time = time
        x,y = self.map_temptime_to_pos()
        self.setPos(x,y)
        self.marker = False


    def type(self):
        return Node.Type

    def addEdge(self, edge):
        self.edgeList.append(weakref.ref(edge))

    def set_index(self, index):
        self.index = index
        self.label = "Step %d" % index
        self.setToolTip(self.label)

    def get_prev_edge(self):
        index = 1000
        edge = False
        for e in self.edgeList:
            sn = e().source().index
            dn = e().dest().index
            if sn < index:
                index = sn
                edge = e
            if dn < index:
                index = dn
                edge = e
        return edge

    def get_next_edge(self):
        index = -1
        edge = False
        for e in self.edgeList:
            sn = e().source().index
            dn = e().dest().index
            if sn > index:
                index = sn
                edge = e
            if dn > index:
                index = dn
                edge = e
        return edge

    def map_temptime_to_pos(self):
        x = self.time * self.graph().graph_width_ratio
        y = self.graph().size[3] - self.temp * self.graph().graph_height_ratio
        return (x,y)

    def boundingRect(self):
        adjust = 2.0
        return QtCore.QRectF(-10 - adjust, -10 - adjust,
                             22 + adjust, 23 + adjust)

    def paint(self, painter, option, widget):
        painter.drawLine(QtCore.QLineF(6,-40,6,-2))
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(QtCore.Qt.lightGray)
        painter.drawEllipse(-10, -10, 20, 20)
        gradient = QtGui.QRadialGradient(0, 0, 22)
        if option.state & QtGui.QStyle.State_Sunken: # selected
            gradient.setColorAt(0, QtGui.QColor(QtCore.Qt.darkGreen).lighter(120))
        else:
            gradient.setColorAt(1, QtCore.Qt.blue)
        painter.setBrush(QtGui.QBrush(gradient))
        painter.setPen(QtGui.QPen(QtCore.Qt.black, 0))
        painter.drawEllipse(-6, -6, 12, 12)


    def itemChange(self, change, value):
        if change == QtGui.QGraphicsItem.ItemPositionChange:
            for edge in self.edgeList:
                edge().adjust()
        return QtGui.QGraphicsItem.itemChange(self, change, value)

    def mousePressEvent(self, event):
        if not self.graph().inhibit_edit:
            self.update()
            print "Node pressed"
            QtGui.QGraphicsItem.mousePressEvent(self, event)

    def mouseReleaseEvent(self, event):
        if not self.graph().inhibit_edit:
            self.update()
            print "Node released"
            #
            QtGui.QGraphicsItem.mouseReleaseEvent(self, event)



###
class GraphWidget(QtGui.QGraphicsView):
    def __init__(self):
        QtGui.QGraphicsView.__init__(self)
        self.size = (-30, 30, 600, 400)
        #
        scene = QtGui.QGraphicsScene(self)
        scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
        scene.setSceneRect(self.size[0],self.size[1],self.size[2],self.size[3])
        self.setScene(scene)
        self.setCacheMode(QtGui.QGraphicsView.CacheBackground)
        self.setRenderHint(QtGui.QPainter.Antialiasing)
        self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
        #
        self.maxtemp = 300
        self.maxtime = 160
        self.nodecount = 0
        self.calc_upper_limits()
        #
        self.scale(0.8, 0.8)
        self.setMinimumSize(600, 400)
        self.setWindowTitle(self.tr("Elastic Nodes"))
        self.inhibit_edit = False

    def calc_upper_limits(self):
        self.toptemp = (self.maxtemp / 100 + 1) * 100
        self.toptime = (int(self.maxtime) / 30 + 1) * 30
        self.graph_width_ratio = float(self.size[2]) /self.toptime
        self.graph_height_ratio = float(self.size[3]) / self.toptemp

    def add_node(self, time, temp, marker=False, pos=-1):
        self.nodecount += 1
        scene = self.scene()
        # Insert Node into scene
        node = Node(self, time, temp, self.nodecount)
        scene.addItem(node)
        # Insert new edges
        nodes = self.get_ordered_nodes()
        if len(nodes) > 1:
            e = Edge(nodes[-2], node)
            scene.addItem(e)
        # cleanup edge tooltips
        for n in self.get_ordered_nodes():
            edges = n.edgeList
            for e in edges:
                e().set_index()

    def get_ordered_nodes(self):
        nodes = [item for item in self.scene().items() if isinstance(item, Node)]
        nodes.sort(key=lambda n: n.index)
        return nodes

    def keyPressEvent(self, event):
        key = event.key()
        if key == QtCore.Qt.Key_Plus:
            self.scaleView(1.2)
        elif key == QtCore.Qt.Key_Minus:
            self.scaleView(1 / 1.2)
        else:
            QtGui.QGraphicsView.keyPressEvent(self, event)

    def mousePressEvent(self, event):
        print "GraphWidget mouse"
        QtGui.QGraphicsView.mousePressEvent(self, event)

    def wheelEvent(self, event):
        self.scaleView(math.pow(2.0, -event.delta() / 240.0))

    def scaleView(self, scaleFactor):
        factor = self.matrix().scale(scaleFactor, scaleFactor).mapRect(QtCore.QRectF(0, 0, 1, 1)).width()
        if factor < 0.07 or factor > 100:
            return
        self.scale(scaleFactor, scaleFactor)

    def drawBackground(self, painter, rect):
        sceneRect = self.sceneRect()


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    widget = GraphWidget()
    widget.add_node(0,    25)
    widget.add_node(30,  100)
    widget.add_node(60,  200)
    widget.show()
    sys.exit(app.exec_())

这是父程序 - 它不获取鼠标事件:称为 test_toplevel.py

# import user interface etc
from PySide import QtCore, QtGui
from test_tabs_ui import Ui_Form
from test_subclass_module import *

import sys

Programs = {"Gen13": {"steps": [[0, 0, 0], [0, 30, 30], [0, 60, 60], [0, 77, 77]]
                      }}


###-----------------------------------------------------------
### The dialog
class Nusku_tab_Add_kiln(QtGui.QWidget):
    """ Create dialog to add/delete kilns from controlled kilns """
    def __init__(self, parent=None):
        # Get the UI loaded
        super(Nusku_tab_Add_kiln, self).__init__(parent)
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.current = Programs['Gen13']
        # draw program in graphicsView
        # swap out the standin
        self.ui.graphLayout.removeWidget(self.ui.graphicsView)
        self.ui.graphicsView.setParent(None)
        self.ui.graphicsView.deleteLater()
        self.graph = GraphWidget()
        self.ui.graphLayout.addWidget(self.graph)
        self.draw_graph()

    def choose_program(self):
        pass

    def draw_graph(self):
        graph = self.graph
        graph.inhibit_edit = True
        steps = self.current['steps']
        for s in steps:
            print s
            graph.add_node(s[1],s[2])

###------------------------------------------------

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    prog = Nusku_tab_Add_kiln()
    prog.show()
    sys.exit(app.exec_())

为了完整起见。这是它导入的 ui 文件:test_tabs_ui.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'test_tabs.ui'
#
# Created: Wed Dec 05 15:20:02 2012
#      by: pyside-uic 0.2.14 running on PySide 1.1.1
#
# WARNING! All changes made in this file will be lost!

from PySide import QtCore, QtGui

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(595, 540)
        self.verticalLayout = QtGui.QVBoxLayout(Form)
        self.verticalLayout.setObjectName("verticalLayout")
        self.tabWidget = QtGui.QTabWidget(Form)
        self.tabWidget.setObjectName("tabWidget")
        self.Tab_Program = QtGui.QWidget()
        self.Tab_Program.setObjectName("Tab_Program")
        self.verticalLayout_2 = QtGui.QVBoxLayout(self.Tab_Program)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.frame_graph_status = QtGui.QFrame(self.Tab_Program)
        self.frame_graph_status.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_graph_status.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_graph_status.setObjectName("frame_graph_status")
        self.horizontalLayout_7 = QtGui.QHBoxLayout(self.frame_graph_status)
        self.horizontalLayout_7.setSpacing(0)
        self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_7.setObjectName("horizontalLayout_7")
        self.frame_program = QtGui.QFrame(self.frame_graph_status)
        self.frame_program.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_program.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_program.setObjectName("frame_program")
        self.graphLayout = QtGui.QVBoxLayout(self.frame_program)
        self.graphLayout.setContentsMargins(-1, 0, -1, 0)
        self.graphLayout.setObjectName("graphLayout")
        self.graphicsView = QtGui.QGraphicsView(self.frame_program)
        self.graphicsView.setObjectName("graphicsView")
        self.graphLayout.addWidget(self.graphicsView)
        self.horizontalLayout_7.addWidget(self.frame_program)
        self.verticalLayout_2.addWidget(self.frame_graph_status)
        self.widget_prog = QtGui.QWidget(self.Tab_Program)
        self.widget_prog.setObjectName("widget_prog")
        self.prog_layout = QtGui.QGridLayout(self.widget_prog)
        self.prog_layout.setContentsMargins(4, 4, 4, 4)
        self.prog_layout.setSpacing(0)
        self.prog_layout.setContentsMargins(0, 0, 0, 0)
        self.prog_layout.setObjectName("prog_layout")
        self.verticalLayout_2.addWidget(self.widget_prog)
        self.tabWidget.addTab(self.Tab_Program, "")
        self.Tab_alarms = QtGui.QWidget()
        self.Tab_alarms.setObjectName("Tab_alarms")
        self.alarms_tab_layout = QtGui.QVBoxLayout(self.Tab_alarms)
        self.alarms_tab_layout.setObjectName("alarms_tab_layout")
        self.tabWidget.addTab(self.Tab_alarms, "")
        self.Tab_settings = QtGui.QWidget()
        self.Tab_settings.setObjectName("Tab_settings")
        self.settings_tab_layout = QtGui.QVBoxLayout(self.Tab_settings)
        self.settings_tab_layout.setObjectName("settings_tab_layout")
        self.tabWidget.addTab(self.Tab_settings, "")
        self.Tab_pid = QtGui.QWidget()
        self.Tab_pid.setObjectName("Tab_pid")
        self.verticalLayout_8 = QtGui.QVBoxLayout(self.Tab_pid)
        self.verticalLayout_8.setSpacing(0)
        self.verticalLayout_8.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_8.setObjectName("verticalLayout_8")
        self.scrollArea_2 = QtGui.QScrollArea(self.Tab_pid)
        self.scrollArea_2.setWidgetResizable(True)
        self.scrollArea_2.setObjectName("scrollArea_2")
        self.scrollAreaWidgetContents_2 = QtGui.QWidget()
        self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 569, 494))
        self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2")
        self.PID_tab_layout = QtGui.QVBoxLayout(self.scrollAreaWidgetContents_2)
        self.PID_tab_layout.setSpacing(0)
        self.PID_tab_layout.setContentsMargins(0, 0, 0, 0)
        self.PID_tab_layout.setObjectName("PID_tab_layout")
        self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2)
        self.verticalLayout_8.addWidget(self.scrollArea_2)
        self.tabWidget.addTab(self.Tab_pid, "")
        self.verticalLayout.addWidget(self.tabWidget)

        self.retranslateUi(Form)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(Form)
        Form.setTabOrder(self.tabWidget, self.graphicsView)
        Form.setTabOrder(self.graphicsView, self.scrollArea_2)

    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
        self.graphicsView.setToolTip(QtGui.QApplication.translate("Form", "decimal point", None, QtGui.QApplication.UnicodeUTF8))
        self.graphicsView.setStatusTip(QtGui.QApplication.translate("Form", "Accuracy can be increased at lower temperatures", None, QtGui.QApplication.UnicodeUTF8))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Tab_Program), QtGui.QApplication.translate("Form", "Program", None, QtGui.QApplication.UnicodeUTF8))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Tab_alarms), QtGui.QApplication.translate("Form", "Alarms", None, QtGui.QApplication.UnicodeUTF8))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Tab_settings), QtGui.QApplication.translate("Form", "Settings", None, QtGui.QApplication.UnicodeUTF8))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Tab_pid), QtGui.QApplication.translate("Form", "PID", None, QtGui.QApplication.UnicodeUTF8))
4

2 回答 2

1

因为有一个答案——它合理地要求我删除我的答案——我必须用我自己的答案来回答这个问题才能关闭它。等待 3 天后......希望我可以删除它 - 但可能不是因为它有答案..

于 2012-12-15T03:42:15.900 回答
0

我下载并尝试了您的应用程序,并看到它或多或少地工作(尽管光标位置在 test_toplevel.py 中出错)。

删除后graph.inhibit_edit = False光标也保持正确。

那么问题已经解决了吗?那么删除您的问题或将其设为已解决将非常有帮助。或者请澄清问题。

于 2012-12-14T23:40:06.013 回答