移动椭圆会移动 QGraphicsScene 中的其他元素

Moving ellipse moves other elements in QGraphicsScene

我正在用 QGraphicsScene 编写一个简单的图形用户界面。在这个场景中,我有 2 个简单的 XY 轴,我有一个函数来检索我的鼠标在场景中单击的位置。

我在我的场景中添加了一个简单的可移动椭圆,我正在检索它的位置(目前它只是一个点击检测,稍后我会为它的移动实现一个信号)

代码如下:

View.py:

import math
import sys

from PySide2.QtCore import Signal, QPointF
from PySide2 import QtCore
from PySide2.QtGui import QColor, QPainterPath
from PySide2.QtWidgets import (QGraphicsItem,
    QApplication,
    QGraphicsScene,
    QGraphicsView,
    QHBoxLayout,
    QMainWindow,
    QPushButton,
    QWidget,
    QSizeGrip
)
from PySide2 import QtGui
from PySide2.QtGui import QIcon


class GraphicsScene(QGraphicsScene): # Used to indicate inheritance from parent class
    clicked = Signal(QPointF)

    def drawBackground(self, painter, rect):
        l = min(rect.width(), rect.height()) / 30

        x_left = QPointF(rect.left(), 0)
        x_right = QPointF(rect.right(), 0)
        painter.drawLine(x_left, x_right)

        right_triangle = QPainterPath()
        right_triangle.lineTo(-0.5 * math.sqrt(3) * l, 0.5 * l)
        right_triangle.lineTo(-0.5 * math.sqrt(3) * l, -0.5 * l)
        right_triangle.closeSubpath()
        right_triangle.translate(x_right)

        painter.setBrush(QColor("black"))
        painter.drawPath(right_triangle)

        y_top = QPointF(0, rect.top())
        y_bottom = QPointF(0, rect.bottom())
        painter.drawLine(y_top, y_bottom)

        top_triangle = QPainterPath()
        top_triangle.lineTo(.5*l, -0.5 * math.sqrt(3) * l)
        top_triangle.lineTo(-.5*l, -0.5 * math.sqrt(3) * l)
        top_triangle.closeSubpath()
        top_triangle.translate(y_bottom)

        painter.setBrush(QColor("black"))
        painter.drawPath(top_triangle)



    def mousePressEvent(self, event):
        sp = event.scenePos()
        self.clicked.emit(sp)
        super().mousePressEvent(event)


class MyView(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("8D.me")
        self.setFixedSize(800, 500)

        self.btn = QPushButton("test2")
        self.btn.setStyleSheet( "color: white; border-radius: 4px; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); background: rgb(66, 184, 221); min-width:100px;min-height:30px")

        self.view = QGraphicsView()

        print(self.view.size())
        self.view.scale(1, -1)
        self.scene = GraphicsScene()
        self.view.setScene(self.scene)
        self.setIcon()
        self.ellipse=self.scene.addEllipse(10,10,10,10)
        self.ellipse.setFlag(QGraphicsItem.ItemIsMovable)


        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QHBoxLayout(central_widget)
        layout.addWidget(self.btn)
        layout.addWidget(self.view)
        #flags = QtCore.Qt.WindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
        #self.setWindowFlags(flags)
        self.scene.clicked.connect(self.handle_clicked)

    def handle_clicked(self, p):
        print("position",self.ellipse.pos())
        print("clicked", p.x(), p.y())
        print(self.view.size())

# Insert methods for creating/adding elements to the default view.
# Mehods....
    def setIcon(self):
        appIcon = QIcon('logo')
        self.setWindowIcon(appIcon)

#Insert here the public methods called by the Controller to update the view

main.py:

import View
#import Model
#import Controller

#Useful example: https://realpython.com/python-pyqt-gui-calculator/
def main():
    """Main function."""
    # Create an instance of QApplication
    app = QApplication([])

    # Show the GUI
    mainwindow =View.MyView()
    mainwindow.show()

    # Create instances of model and controller
    #model = Model.myModel()
    #Controller.myController(view=mainwindow,model=model)
    return app.exec_()

if __name__ == '__main__':
    main()

编辑: 我还添加了 main 代码。由于我使用的是 MVC 设计模式,因此我将视图放在单独的文件中。

我的 GUI 如下所示:

目前为止一切正常。

问题是如果我移动椭圆(正确移动)我的 XY 轴也会移动,但我不明白为什么。

例如,如果我将椭圆移向右上角,我的 GUI 将如何变化:

有什么问题吗?如何“修复”XY 轴?我想保持轴不动,只移动场景区域内的椭圆。

我解决了以下问题:https://forum.qt.io/topic/48564/force-qgraphicsview-size-to-match-qgraphicsscene-size/7

基本上我在我的代码中添加了以下几行:

self.view.setFixedSize(600,480)       
self.view.setSceneRect(-300,-220,600,480)      
self.view.fitInView(0,0,600,480, Qt.KeepAspectRatio)

所以新的View.py是:

import math
import sys
from PySide2.QtCore import Signal, QPointF, Qt
from PySide2 import QtCore
from PySide2.QtGui import QColor, QPainterPath
from PySide2.QtWidgets import (QGraphicsItem,
    QApplication,
    QGraphicsScene,
    QGraphicsView,
    QHBoxLayout,
    QMainWindow,
    QPushButton,
    QWidget,
    QSizeGrip
)
from PySide2 import QtGui
from PySide2.QtGui import QIcon


class GraphicsScene(QGraphicsScene): # Used to indicate inheritance from parent class
    clicked = Signal(QPointF)

    def drawBackground(self, painter, rect):
        #print('Pinto rect',rect.width(),rect.height())
        l = min(rect.width(), rect.height()) / 30
        #print('printo l',l)

        #Qui c'è il bug. La funzione drawbackground viene chiamata a ogni modifica della scene.
        #Lo starting point del drawing della line cambia nel tempo, ecco perchè mi si spostano gli assi
        x_left = QPointF(rect.left(), 0)
        x_right = QPointF(rect.right(), 0)
        print('printo gli x',rect.left(),rect.height())
        painter.drawLine(x_left, x_right)

        right_triangle = QPainterPath()
        right_triangle.lineTo(-0.5 * math.sqrt(3) * l, 0.5 * l)
        right_triangle.lineTo(-0.5 * math.sqrt(3) * l, -0.5 * l)
        right_triangle.closeSubpath()
        right_triangle.translate(x_right)

        painter.setBrush(QColor("black"))
        painter.drawPath(right_triangle)

        y_top = QPointF(0, rect.top())
        y_bottom = QPointF(0, rect.bottom())
        painter.drawLine(y_top, y_bottom)

        top_triangle = QPainterPath()
        top_triangle.lineTo(.5*l, -0.5 * math.sqrt(3) * l)
        top_triangle.lineTo(-.5*l, -0.5 * math.sqrt(3) * l)
        top_triangle.closeSubpath()
        top_triangle.translate(y_bottom)

        painter.setBrush(QColor("black"))
        painter.drawPath(top_triangle)



    def mousePressEvent(self, event):
        sp = event.scenePos()
        self.clicked.emit(sp)
        super().mousePressEvent(event)


class MyView(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("8D.me")
        self.setFixedSize(800, 500)

        self.btn = QPushButton("test2")
        self.btn.setStyleSheet( "color: white; border-radius: 4px; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); background: rgb(66, 184, 221); min-width:100px;min-height:30px")

        self.view = QGraphicsView()
        print(self.view.size())

        self.view.setFixedSize(600,480)
        self.view.setSceneRect(-300,-220,590,470)
        self.view.fitInView(0,0,600,480, Qt.KeepAspectRatio)

        self.view.scale(1, -1)
        self.scene = GraphicsScene()
        self.view.setScene(self.scene)

        self.setIcon()
        self.ellipse=self.scene.addEllipse(-5,-5,10,10)
        self.ellipse.setFlag(QGraphicsItem.ItemIsMovable)


        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QHBoxLayout(central_widget)
        layout.addWidget(self.btn)
        layout.addWidget(self.view)
        #flags = QtCore.Qt.WindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
        #self.setWindowFlags(flags)
        self.scene.clicked.connect(self.handle_clicked)

    def handle_clicked(self, p):
        print("position",self.ellipse.pos())
        print("clicked", p.x(), p.y())
        print(self.view.size())

# Insert methods for creating/adding elements to the default view.
# Mehods....
    def setIcon(self):
        appIcon = QIcon('logo')
        self.setWindowIcon(appIcon)

#Insert here the public methods called by the Controller to update the view