You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在QtWidgets应用中集成可交互的2cm十字光标?

QtWidgets 十字光标实现与OpenGL集成建议

一、Matplotlib并非最优方案

对于纯QtWidgets应用,Qt原生绘图框架(QGraphicsView/QGraphicsScene或直接在QWidget上绘制)是更轻量、贴合度更高的选择——无需引入matplotlib的额外依赖,代码整合性和运行性能更适配Qt项目。

二、Qt原生实现2cm物理尺寸可移动十字光标

核心思路

采用QGraphicsView+QGraphicsScene架构:

  1. 将图片作为QGraphicsPixmapItem添加到场景
  2. 自定义QGraphicsItem实现十字光标,根据屏幕DPI计算2cm对应的像素尺寸
  3. 监听鼠标事件,同步光标位置

代码示例

import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QGraphicsView, 
                             QGraphicsScene, QGraphicsPixmapItem, QGraphicsItem)
from PyQt5.QtGui import QPixmap, QPainter, QPen, QMouseEvent
from PyQt5.QtCore import Qt, QRectF

# 基于96DPI计算2cm对应的像素值(1cm = 96/2.54 ≈37.795像素)
CM_TO_PIXEL = 96 / 2.54
CROSS_SIZE = 2 * CM_TO_PIXEL

class CrossCursor(QGraphicsItem):
    def __init__(self):
        super().__init__()
        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        # 保持光标尺寸不随视图缩放变化
        self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True)

    def boundingRect(self):
        half = CROSS_SIZE / 2
        return QRectF(-half, -half, CROSS_SIZE, CROSS_SIZE)

    def paint(self, painter, option, widget):
        painter.setPen(QPen(Qt.red, 2))
        # 绘制十字线
        painter.drawLine(-CROSS_SIZE/2, 0, CROSS_SIZE/2, 0)
        painter.drawLine(0, -CROSS_SIZE/2, 0, CROSS_SIZE/2)

    def mouseMoveEvent(self, event: QMouseEvent):
        scene_pos = event.scenePos()
        self.setPos(scene_pos)
        super().mouseMoveEvent(event)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.view = QGraphicsView()
        self.scene = QGraphicsScene()
        self.view.setScene(self.scene)
        self.setCentralWidget(self.view)

        # 添加图片(替换为你的图片路径)
        pixmap = QPixmap("your_image.jpg")
        pix_item = QGraphicsPixmapItem(pixmap)
        self.scene.addItem(pix_item)

        # 添加十字光标
        self.cursor = CrossCursor()
        self.scene.addItem(self.cursor)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
  • 关键说明:ItemIgnoresTransformations确保光标尺寸不受视图缩放影响,始终保持2cm物理大小;通过DPI计算像素值保证跨设备尺寸一致。

三、OpenGL画布集成自定义Item提示

若使用QOpenGLWidget作为画布

  1. 初始化阶段:在initializeGL()中加载图片为OpenGL纹理,初始化绘图状态(如颜色、线宽)
  2. 绘制阶段:在paintGL()中先绘制图片纹理,再用OpenGL指令(如glBegin(GL_LINES))绘制十字光标
  3. 鼠标事件处理:重写mouseMoveEvent(),转换鼠标坐标到OpenGL坐标系(注意OpenGL的y轴方向与Qt相反)

若使用QGraphicsScene配合OpenGL渲染

  • 自定义Item需继承QGraphicsItem,在paint()方法中获取当前OpenGL上下文,直接调用OpenGL绘图指令
  • 启用场景的OpenGL渲染:
    self.view.setViewport(QOpenGLWidget())
    self.view.setRenderHint(QPainter.OpenGL)
    

内容的提问来源于stack exchange,提问作者Josh.h

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 02:41:57