实现效果如下:
- 读取图片,显示在QGraphicsView中显示,移动视图,现实在画面中心。
- 点击窗口,返回窗口所在的坐标位置,因为窗口和图像的uv坐标之间完全重合,可以认为读取的就是图像本身的像素坐标。
- 鼠标按住不放,可以实时显示位置。
一 初始化
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_())