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

QGraphicsScene中自定义QGraphicsItem绕中心旋转及QGraphicsView原点设置

解决方案:自定义图形项绕中心旋转 + QGraphicsView原点调整

咱们一步步解决你的两个问题:让自定义图形项绕自身中心旋转,以及把QGraphicsView的原点设置到左下角。


一、让Grafica_PPU绕自身中心旋转

你的核心问题在于混淆了场景坐标和图形项的局部坐标,以及手动在paint里处理旋转的方式不对。Qt的QGraphicsItem本身提供了transform系统,用它来处理旋转会更可靠简洁。

修改步骤:

  1. 重构Grafica_PPU的坐标逻辑
    把图形项的位置从boundingRect中剥离,改用QGraphicsItem自带的setPos()方法设置它在场景中的位置,boundingRect只描述图形项自身的局部矩形(从(0,0)开始)。

    先修改头文件areagrafica.h,新增存储自身宽高的成员:

    private:
        GraphicModuleData infoGrafiche;
        qreal Alpha;
        QString Testo;
        QPen Penna;
        qreal m_width, m_height; // 存储自身宽高,避免重复读取infoGrafiche
    

    然后修改areagrafica.cpp的构造函数,设置位置、旋转原点和角度:

    Grafica_PPU::Grafica_PPU(QString ModuleName, GraphicModuleData tmpInfoGrafiche, QPen Pen, qreal tmpAlpha)
        : infoGrafiche(tmpInfoGrafiche), Penna(Pen), Testo(ModuleName), Alpha(tmpAlpha),
          m_width(tmpInfoGrafiche.Width), m_height(tmpInfoGrafiche.Height)
    {
        // 设置图形项在场景中的位置
        setPos(tmpInfoGrafiche.posX, tmpInfoGrafiche.posY);
        // 把旋转原点设为图形项自身的中心
        setTransformOriginPoint(m_width / 2, m_height / 2);
        // 设置旋转角度
        setRotation(tmpAlpha);
        // 可选:开启可选/可移动,方便调试
        setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
    }
    
  2. 修正boundingRect()函数
    现在boundingRect要返回图形项的局部坐标范围,同时为了避免旋转后图形被裁剪,我们可以返回一个包含旋转后最大范围的矩形:

    QRectF Grafica_PPU::boundingRect() const {
        // 计算旋转后的最大边界(用对角线长度确保覆盖所有旋转情况)
        qreal maxDim = qMax(m_width, m_height);
        qreal halfMax = maxDim / 2;
        return QRectF(-halfMax, -halfMax, maxDim, maxDim);
        // 如果不需要考虑极端旋转裁剪,也可以直接返回原始矩形:
        // return QRectF(0, 0, m_width, m_height);
    }
    
  3. 简化paint()函数
    现在不需要手动处理translate和rotate了,Qt会通过transform自动帮我们转换坐标系,直接在局部坐标系绘制即可:

    void Grafica_PPU::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
        painter->setPen(Penna);
        painter->setRenderHint(QPainter::Antialiasing);
        painter->setRenderHint(QPainter::TextAntialiasing);
        
        // 绘制自身矩形(局部坐标从0,0开始)
        QRectF rect(0, 0, m_width, m_height);
        painter->drawRect(rect);
        // 绘制中心圆点
        painter->drawPoint(rect.center());
        // 绘制居中文字
        painter->drawText(rect, Qt::AlignCenter, Testo);
    }
    

二、把QGraphicsView的原点设置为左下角

默认QGraphicsView的原点在左上角,我们可以通过修改view的变换矩阵来翻转y轴,再调整平移让原点对齐左下角。

修改主窗口代码:

在MainWindow的构造函数中,添加以下代码(假设你的QGraphicsView对象名为Grafico_View):

// 关联场景和视图
Grafico_View->setScene(Grafico_Scena);

// 翻转y轴,将坐标系的y轴方向改为向上(默认是向下)
Grafico_View->scale(1, -1);

// 平移视图,让场景的左下角对齐视图可视区域的左下角
Grafico_View->translate(0, -Grafico_View->viewport()->height());

处理窗口大小变化:

如果窗口resize,视图的视口高度会变化,需要重新调整平移参数。可以在MainWindow中重写resizeEvent:

void MainWindow::resizeEvent(QResizeEvent *event) {
    QMainWindow::resizeEvent(event);
    if (Grafico_View) {
        // 先重置变换,再重新设置
        Grafico_View->resetTransform();
        Grafico_View->scale(1, -1);
        Grafico_View->translate(0, -Grafico_View->viewport()->height());
    }
}

最后调整调用代码

现在构造函数已经处理了旋转,调用时直接传入角度即可:

GraphicModuleData tmp;
tmp.posX = 45;
tmp.posY = 100; // 注意:视图翻转y轴后,posY的方向会反过来,按需调整数值
tmp.Height = 22;
tmp.Width = 54;

// 创建两个测试项,一个旋转0度,一个旋转45度(示例)
Grafica_PPU *test = new Grafica_PPU("PP55103", tmp, *Grafico_Matita_Nera, 0.0);
Grafica_PPU *test2 = new Grafica_PPU("PP55103", tmp, *Grafico_Matita_Nera, 45.0);

Grafico_Scena->addItem(test);
Grafico_Scena->addItem(test2);

这样修改后,你的自定义图形项就会绕自身中心旋转,QGraphicsView的原点也会落在左下角了。

内容的提问来源于stack exchange,提问作者Pierluigi Rovere

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:38:55