图像类QGraphicsView

 涉及到的函数属性和通信信号

Functions

Virtual functions

Slots

Signals

 官方最权威的解释:QGraphicsView — Qt for Python

以下是参考到的博文和总结:

小白白也能学会的 PyQt 教程 —— 图像类及图像相关基础类介绍_51CTO博客_pyqt图像处理

PySide6————QtWidgets.QGraphicsView、QtWidgets.QGraphicsView、QtWidgets.QGraphicsItem教程-CSDN博客

https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/index.html

视图VIew、场景Scene和图元Item

https://blog.csdn.net/La_vie_est_belle/article/details/86999825

这篇写图形视图框架博主写的通俗易懂,有本书,有兴趣可以去这里《快速掌握PyQt5》专栏整理成书出版啦!-CSDN博客

事件顺序

视图-场景-图元

图形视图的坐标体系

(更新) 图形视图基于笛卡尔坐标系,视图,场景和图元坐标系都一样——左上角为原点,向右为x正轴,向下为y正轴。

 理解:

1.三个类:QGraphicsItem图元类、QGraphicsScene场景类和QGraphicsView视图类,图元放在场景上,场景内容通过视图来显示。

视图和场景布置好后增加图元(不同形状包括矩形、圆形、椭圆形、直线、多边形等、图像、文本等内容)先添加的图元处于后添加的图元下方(Z轴方向),图元中还可以增加另一个图元(父子关系),也可以可以对图元进行分组(同时操作,包括移动修改或删除之类)group1,group2.组的边界其位置和大小可用boundRect()方法来获取。

        self.group1 = QGraphicsItemGroup()
        self.group2 = QGraphicsItemGroup()
        self.group1.addToGroup(self.rect1)
        self.group1.addToGroup(self.ellipse1)
        self.group2.addToGroup(self.rect2)
        self.group2.addToGroup(self.ellipse2)
        self.group1.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)
        self.group2.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)

接着调用setFlags()方法设置属性,让分组可以选中和移动。boundRect()方法放回一个QRectF值,该值可以显示出分组的边界位置和大小;

  • self.scene.addItem(self.group1)

  • self.scene.addItem(self.group2)

将分组添加到场景当中。

若需要增加矩形、多边形等,或者进行拖拽,缩放,双击等事件,都是对图元进行的操作

2.坐标与检测碰撞(图元)

坐标https://blog.51cto.com/liming19680104/4996853

视图坐标是窗口界面的物理坐标,以左上点为原点;

场景坐标,类似QPainter的逻辑坐标,以场景中心为原点;

图元坐标,局部逻辑坐标,以图元中心为原点。

第15.47节、PyQt显示部件:QGraphicsView图形视图和QGraphicsScene图形场景简介及应用案例_小戴BOTAOY演示博客

class mainWin(QtWidgets.QWidget,ui_mainWin.Ui_mainWin):

    def __init__(self):

        super().__init__()

        self.setupUi(self)

        self.graphicsView.setStyleSheet("padding: 0px; border: 0px;")#内边距和边界去除

        self.scene = QtWidgets.QGraphicsScene(self)

        self.graphicsView.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) 
#改变对齐方式

        self.graphicsView.setSceneRect(0,0,self.graphicsView.viewport().width(),self.graphicsView.height()) #设置图形场景大小和图形视图大小一致

        self.graphicsView.setScene(self.scene)

        self.addScenes() #调用绘制图形的方法

        self.scene.mousePressEvent = self.mousePressEvent  #接管图形场景的鼠标事件 

  def addScenes(self): #绘制图形

        originX,originY = 40,60  #坐标基点

        self.itemHELLO = self.scene.addText("HELLO!")  #输出hello

        self.itemHELLO.setPos(0, 0)

        #绘制矩形

        pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.red))

        rectF = QtCore.QRectF(originX+300-8, originY-25, 20, 50)

        self.elpItem = self.scene.addEllipse(rectF, pen)

        # 绘制曲线

        pen.setColor(QtGui.QColor(QtCore.Qt.blue))

        path = QtGui.QPainterPath()

        path.moveTo(originX,originY)

        path.cubicTo(originX+100, originY-150, originX+200, originY+150,originX+300,originY)

        myGradient = QtGui.QLinearGradient()

        myFont = QtGui.QFont()

        textPoint = QtCore.QPointF(originX+35,originY-4)

        path.addText(textPoint, myFont, "老猿Python")

        self.itemPath = self.scene.addPath(path,pen,myGradient)

        #绘制下划线

        pen.setColor(QtGui.QColor(QtCore.Qt.darkRed))

        line = QtCore.QLineF(QtCore.QPointF(originX+190, originY-20), QtCore.QPointF(originX+275, originY-20))

        self.itemLine = self.scene.addLine(line, pen)

        self.itemLine.setPos(0,originY-20)

        #绘制文字

        self.itemText = self.scene.addText("跟老猿学Python!")

        self.itemText.setPos(originX+185,originY+1)

        #绘制图片

        pixmap = QtGui.QPixmap(r"F:\coffeDog\咖啡狗小图.jpg")

        self.pixmapItem = self.scene.addPixmap(pixmap)

        self.pixmapItem.setPos(originX-34,originY-16)

        #绘制x轴

        pen.setColor(QtGui.QColor(QtCore.Qt.red))

        self.xLine = self.scene.addLine(originX,originY, originX+300, originY, pen)

    def myMousePressEvent(self,mouseEvent):

        print("myMousePressEvent",mouseEvent.type(),mouseEvent.scenePos())

        point = mouseEvent.scenePos()

        if  point:

            self.movePath(point) #移动相关图元,方法单独实现

        else:print("not valid point")

def mouseMoveEvent(self, event):
    if self.rect.collidesWithItem(self.ellipse, Qt.IntersectsItemBoundingRect):
        print(self.rect.collidingItems(Qt.IntersectsItemShape))
    super().mouseMoveEvent(event)

collidesWithItem矩形框检测碰撞椭圆的真实边界,即为椭圆的边,而不是选择出现的虚线矩形边,碰撞到返回TRUE

collidingItems()方法在指定检测方式后可以返回所有符合碰撞条件的其他图元,返回值类型为列表

如:[<PyQt5.QtWidgets.QGraphicsEllipseItem object at 0x7fea87ed0790>]

博主举例还有其他具体的检测方式:

【常量】Qt.ContainsItemShape   

【值】0x0:【触发条件】以形状为范围,当前图元被其他图元完全包含住

Qt.IntersectsItemShape   

0x1:以形状为范围,当前图元被完全包含或者与其他图元有交集

Qt.ContainsItemBoundingRect   

0x2: 以边界为范围,当前图元被其他图元完全包含住

Qt.IntersectsItemBoundingRect   

0x3:以边界为范围,当前图元被完全包含或者与其他图元有交集
QGraphicsEllipseItem — Qt for Python(左上角坐标和宽,高)

PySide2.QtWidgets.QGraphicsEllipseItem.setRect(x, y, w, h)

Parameters:x – float,y – float,w – float,h – float

这篇博文中提到一个绘制矩形的bughttps://www.cnblogs.com/ybqjymy/p/12375790.html

拿一个例子来对比,假设有一个矩形左上角为(0, 0),长宽都为100.那么我们期待的一个矩形的左上角和右下角应该是(0, 0)(100, 100)。
但,如果用构造函数QRect(0, 0, 100, 100)会得到:

  • 左上角(0, 0)
  • 右下角(0, 99)

而对于构造函数QRectF(0, 0, 100, 100)会得到:

  • 左上角(0.0, 0.0)
  • 右下角(0.0, 100.0)

但是,这里的QRect和QRectF在实际绘制过程中会重叠,也就是说他们实际上是一样的。

所以文档才建议,或者你可以使用QRectF,否则就要把这个陷阱铭记于心。
同时构造QRect的时候,建议使用。

  • QRect(int x, int y, int width, int height)
    同时在代码中避免使用QRect的:
  • right()
  • bottom()
    相关函数。
    或者,将错就错,在构造时候使用了TopLeft和BottomRight,那么就记得要+1或者-1,或者在后续使用过程中对获得的Width或者Height进行+/-1。

https://www.cnblogs.com/ybqjymy/p/12375790.html

#QGraphicsItem特性:
    #鼠标按下、移动、释放和双击事件,以及鼠标悬浮事件、滚轮事件和右键菜单事件
    #键盘输入事件
    #拖放事件
    #分组
    #碰撞检测
#视图与场景大小一致
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QTransform
from PyQt5.QtWidgets import QApplication, QGraphicsItem, QGraphicsScene, QGraphicsView
 
 
class Demo(QGraphicsView):
    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300, 300)
 
        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 300, 300)
 
        # 1矩形和椭圆,双击删除
        self.rect = self.scene.addRect(100, 30, 100, 30)
        self.ellipse = self.scene.addEllipse(100, 80, 50, 40)
        self.pic = self.scene.addPixmap(QPixmap('pic.png').scaled(60, 60))
        self.pic.setOffset(100, 130)
        #设置属性可选择、可移动、获得焦点
        self.rect.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsFocusable)
        self.ellipse.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsFocusable)
        self.pic.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsFocusable)
 
        self.setScene(self.scene)
 
        # 2
        print(self.scene.items())
        print(self.scene.items(order=Qt.AscendingOrder))
        print(self.scene.itemsBoundingRect())
        print(self.scene.itemAt(110, 40, QTransform()))
 
        # 3获取焦点可以拖动,改变选择图形的坐标位置
        self.scene.focusItemChanged.connect(self.my_slot)
 
    def my_slot(self, new_item, old_item):
        print('new item: {}\nold item: {}'.format(new_item, old_item))
 
    # 4
    def mouseMoveEvent(self, event):
        print(self.scene.collidingItems(self.ellipse, Qt.IntersectsItemShape))
        super().mouseMoveEvent(event)
 
    # 5 还需要修改(双击删除)
    def mouseDoubleClickEvent(self, event):
        item = self.scene.itemAt(event.pos(), QTransform())
        self.scene.removeItem(item)
        super().mouseDoubleClickEvent(event)
 
 
if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

import sys
from PyQt5.QtGui import QPixmap, QTransform
from PyQt5.QtWidgets import QApplication, QGraphicsItem, QGraphicsScene, QGraphicsView
#场景设置比视图大,视图大小为300x300,场景大小为500x500。
 
class Demo(QGraphicsView):
    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300, 300)
 
        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 500, 500)
        self.scene.addEllipse(QRectF(200, 200, 50, 50))
 
        #蓝色的圆 红色的正方形
        self.ellipse = self.scene.addEllipse(QRectF(200, 200, 50, 50), brush=QBrush(QColor(Qt.blue)))
        self.rect = self.scene.addRect(QRectF(300, 300, 50, 50), brush=QBrush(QColor(Qt.red)))
        self.ellipse.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)
        self.rect.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)

        self.setScene(self.scene)

        #缩放scale和移动
        self.press_x = None
 
    # 1缩放
    def wheelEvent(self, event):
        if event.angleDelta().y() < 0:
            self.scale(0.9, 0.9)
        else:
            self.scale(1.1, 1.1)
        # super().wheelEvent(event)
 
    # 2移动、旋转(顺时针+、逆时针-)
    def mousePressEvent(self, event):
        self.press_x = event.x()
        # super().mousePressEvent(event)
 
    def mouseMoveEvent(self, event):
        if event.x() > self.press_x:
            self.rotate(10)
        else:
            self.rotate(-10)
        # super().mouseMoveEvent(event)


 
#视图比场景大,视图大小为600x600,而场景大小只有300x300
 
class Demo(QGraphicsView):
    def __init__(self):
        super(Demo, self).__init__()
        self.resize(600, 600)
        #设置视图的大小
 
        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 300, 300)
        #设置场景的大小
        #场景大小与视图不一致时,双击鼠标获取的event.pos()是视图上的坐标,
        #但是self.scene.itemAt()需
        ##要的是场景坐标。把视图坐标传给场景的itemAt()方法是获取不到任何图元的,
        #所以我们应该要进行转换!

    def mouseDoubleClickEvent(self, event):
        point = self.mapToScene(event.pos())
        item = self.scene.itemAt(point, QTransform())
        self.scene.removeItem(item)
        super().mouseDoubleClickEvent(event)
————————————————
版权声明:本文为CSDN博主「la_vie_est_belle」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/La_vie_est_belle/article/details/86999825

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值