Pyqt5:基于QGraphicsView实现读取像素坐标

该篇文章详细介绍了如何使用Python和PyQt5创建一个图像查看器,包括读取图片、在QGraphicsView中显示并保持居中,以及响应鼠标点击和移动事件,获取和显示场景坐标。
摘要由CSDN通过智能技术生成

实现效果如下:

  1. 读取图片,显示在QGraphicsView中显示,移动视图,现实在画面中心。
  2. 点击窗口,返回窗口所在的坐标位置,因为窗口和图像的uv坐标之间完全重合,可以认为读取的就是图像本身的像素坐标。
  3. 鼠标按住不放,可以实时显示位置。

一 初始化

import sys
from PyQt5.QtGui import QPainter, QPixmap, QTransform
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QWidget, QStyleOption, \
    QToolTip
from PyQt5.QtCore import Qt, QSize, QSizeF, QRectF, QPointF
from PyQt5.uic.properties import QtGui


class ImageViewer(QGraphicsView):
    def __init__(self, image_path, parent=None):
        super(ImageViewer, self).__init__(parent)
        self.setRenderHint(QPainter.Antialiasing)
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)
        self.qpixmap = QPixmap(image_path)
        self.image_item = QGraphicsPixmapItem(self.qpixmap)
        self.scene.addItem(self.image_item)
        self.image_item.setFlag(QGraphicsPixmapItem.ItemIsFocusable)
        self.update_scene_size()  # 更新场景大小以适应视图
        self.img = QPixmap(image_path)
        self.deviceTransform = QTransform()  # 创建一个 QTransform 对象
        style_option = QStyleOption()
        self.setCursor(Qt.CrossCursor)  # 设置光标为:移动

二 改变视图大小,图像始终显示在视图中央

       
    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.update_scene_size()

    def update_scene_size(self):
        # 获取视图的大小
        view_size = self.size()
        # 获取图片的大小
        image_size = self.image_item.boundingRect().size()
        # scene_size = self.size()
        offset = QSizeF((image_size.width() - view_size.width()) / 2,
                        (image_size.height() - view_size.height()) / 2)  # 计算偏移量以居中图片
        rect = QRectF(QPointF(offset.width(), offset.height()), QSizeF(view_size))
        # 改变场景的大小,保证场景中图元的中心点始终和视图的中心点重合
        self.scene.setSceneRect(rect)

初始的场景的(0,0)点在视图(即窗口的左上角),图像也在窗口的左上角,改变视图的大小,图像会始终在窗口的左上角显示。因此需要实时移动场景的大小,移动方式由setSceneRect定义,需要传入一个QPointF和QSizeF格式数据。其中QPointF表示矩形范围的左上角点,QSizeF表示矩形的长和宽。

假设给setSceneRect函数传入(x,y,u,v)。可以理解为视图的显示范围从场景坐标(x, x+u),(y,y+v)的位置显示。

三 鼠标按下,获取场景坐标

    def mousePressEvent(self, event):
        if self.scene:
            # 将视图坐标转换为场景坐标
            scenePos = self.mapToScene(event.pos())
            print(scenePos)

四 鼠标按下移动,可是在鼠标旁边显示相应的位置信息

    def mouseMoveEvent(self, event):
        pos = self.mapToScene(event.pos())
        # 显示坐标信息
        coord_info = f"Scene coordinates: ({pos.x()}, {pos.y()})"
        print(coord_info)
        QToolTip.showText(event.screenPos().toPoint(), coord_info, self)
        super(ImageViewer, self).mouseMoveEvent(event)

五 完整代码

        为了更加方便大家理解,其实主要是方便自己用。把完整的代码(包括我中间被注释的测试代码)都放上来。

import sys

from PyQt5.QtGui import QPainter, QPixmap, QTransform
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QWidget, QStyleOption, \
    QToolTip
from PyQt5.QtCore import Qt, QSize, QSizeF, QRectF, QPointF
from PyQt5.uic.properties import QtGui


# class MyScene(QGraphicsScene):
#     def mouseMoveEvent(self, event):
#         # 处理鼠标移动事件
#         super(MyScene, self).mouseMoveEvent(event)
#         print("Mouse moved in the scene")


class ImageViewer(QGraphicsView):
    def __init__(self, image_path, parent=None):
        super(ImageViewer, self).__init__(parent)
        self.setRenderHint(QPainter.Antialiasing)
        # self.setDragMode(QGraphicsView.ScrollHandDrag)
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)
        self.qpixmap = QPixmap(image_path)
        self.image_item = QGraphicsPixmapItem(self.qpixmap)
        self.scene.addItem(self.image_item)
        self.image_item.setFlag(QGraphicsPixmapItem.ItemIsFocusable)
        # 设置图元的位置
        # self.image_item.setPos(QPointF(100, 100))
        # print(self.image_item.pos())
        # self.fit_image()  # 调整图片大小以适应视图
        self.update_scene_size()  # 更新场景大小以适应视图
        self.img = QPixmap(image_path)
        self.deviceTransform = QTransform()  # 创建一个 QTransform 对象
        style_option = QStyleOption()
        self.setCursor(Qt.CrossCursor)  # 设置光标为:移动

    # def fit_image(self):
    #     self.scene.clear()
    #     self.image_item = QGraphicsPixmapItem(self.qpixmap)
    #     self.scene.addItem(self.image_item)
    #     # 调整图片大小以适应视图
    #     self.image_item.setPixmap(
    #         self.image_item.pixmap().scaled(self.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
    #     self.update_scene_size()  # 更新场景大小以适应视图

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.update_scene_size()

    def mouseMoveEvent(self, event):
        pos = self.mapToScene(event.pos())
        # 显示坐标信息
        coord_info = f"Scene coordinates: ({pos.x()}, {pos.y()})"
        print(coord_info)
        QToolTip.showText(event.screenPos().toPoint(), coord_info, self)
        super(ImageViewer, self).mouseMoveEvent(event)

    def mousePressEvent(self, event):
        if self.scene:
            # 将视图坐标转换为场景坐标
            scenePos = self.mapToScene(event.pos())
            # item = self.scene.itemAt(scenePos, self.deviceTransform)
            print(scenePos)
            # # 查询场景中这个位置的图元
            # # item = self.scene.itemAt(item)
            # if item:
            #     print(f"Clicked on item: {item}")
            #     print(f"Item position in scene coordinates: {item.pos()}")
            #     # 这里可以添加更多逻辑来处理点击事件和图元信息

    def update_scene_size(self):
        # 获取视图的大小
        view_size = self.size()
        # 获取图片的大小
        image_size = self.image_item.boundingRect().size()
        # scene_size = self.size()
        offset = QSizeF((image_size.width() - view_size.width()) / 2,
                        (image_size.height() - view_size.height()) / 2)  # 计算偏移量以居中图片
        # print(offset.width())
        # a = offset.width()
        rect = QRectF(QPointF(offset.width(), offset.height()), QSizeF(view_size))
        # self.scene.setSceneRect(-100, -110, 800, 600)
        print("设置场景的大小")
        print(self.scene.sceneRect())
        # self.setGeometry(1000, 500, 800, 600)
        print("视图的大小")
        print(self.size())
        self.scene.setSceneRect(rect)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    viewer = ImageViewer("img/path.jpg")  # 替换为你的图像路径
    window = QWidget()
    window.resize(1800, 1600)
    viewer.show()
    sys.exit(app.exec_())

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
很高兴为您解答PyQt5中的QGraphicsView图像漫游代码。实现图像漫游的关键是使用QGraphicsView的滚动条,以下是一个简单的示例代码: ``` import sys from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * class GraphicsView(QGraphicsView): def __init__(self, parent=None): super().__init__(parent) scene = QGraphicsScene(self) scene.setSceneRect(0, 0, 1000, 1000) # 设置场景大小 self.setScene(scene) self.setRenderHint(QPainter.Antialiasing) self.setDragMode(QGraphicsView.ScrollHandDrag) # 设置拖动模式 self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 水平滚动条隐藏 self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 垂直滚动条隐藏 self.setFixedSize(500, 500) # 设置窗口大小 self.setSceneRect(0, 0, 1000, 1000) # 设置场景大小 # 添加图像到场景中 pixmap = QPixmap("image.jpg") item = QGraphicsPixmapItem(pixmap) self.scene().addItem(item) def wheelEvent(self, event): # 缩放图像 scaleFactor = 1.15 if event.angleDelta().y() > 0: self.scale(scaleFactor, scaleFactor) else: self.scale(1 / scaleFactor, 1 / scaleFactor) if __name__ == '__main__': app = QApplication(sys.argv) view = GraphicsView() view.show() sys.exit(app.exec_()) ``` 在这个示例代码中,我们创建了一个继承自QGraphicsViewGraphicsView类。在类的构造函数中,我们创建了一个QGraphicsScene,并将其设置为QGraphicsView的场景。然后,我们设置了一些属性,如拖动模式、滚动条的隐藏等。最后,我们将图片放入场景中,并重写了wheelEvent方法,实现了缩放操作。 希望这个回答能够帮助您解决问题,如有疑问请及时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值