Qt文档阅读笔记-Transformations解析及例子

本文详细介绍了QGraphicsItem中的变换方法,包括旋转、缩放等,并通过实例演示了如何使用这些变换方法。此外,还解释了变换是如何在父级和子级间累积的,以及在场景坐标系中应用变换的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

官方解析

博主小栗子


官方解析

QGraphicsItem除了基于他的坐标pos()外,还支持投影变化。下面提供了几种变化item的方式。下面来说明下简单的转换,可以通过调用setRotation()或setScale(),或者调用setTransform(),这个方式是通过变化矩阵实现的。下面来说明下高级点的操作,可以通过调用setTransformations()选择几个被写好的transformations进行图像变化。

item的转变是从parent到child逐步累计的(这一点和OpenGL感觉有点差别,OpenGL是只对当前矩阵上的物体有影响),举个栗子,如果一个parentItem和childItem同时被设置旋转90度,那么childItem最后将旋转180读。同样的道理,如果一个parent item在他的原始尺寸上放大了2倍,那么他所有的child item都会被放大2倍。当一个item被转化成其他形态后他自己的坐标系将不受影响(这个功能牛逼,赞一下);所有的关于几何的函数(比如contains(),update(),所有的mapping函数)都将可以在他原坐标系进行操作。为了方便,QGraphicsItem提供了一个叫sceneTransform()的函数,这个函数返回这个Item的总变化矩阵(包括他的位置,和所有parent的坐标以及transformations)以及他在场景中的位置。调用resetTransform()可以重设他的变化矩阵。

在线性代数里面,矩阵是不具有交换率的,所以不同顺序的操作,会有不同的转变。举个栗子,放大后旋转和旋转后放大将造成不同的结果。但是在QgraphicsItem中却可以进行这样的骚操作,也就是有交换律;QGraphicsItem有着他固定的操作,顺序如下:
1.调用transform实现最基本的转换(transform);
2.item是按照transformatins列表进行的(transformations());
3.item的旋转依赖于他转换的源坐标(rotation(),transformOriginPoint());
4.item的放缩也依赖于他的源坐标(scale(),transformOriginPoint())。

博主小栗子

运行截图如下:

源码如下:

mygraphicsitem.h

#ifndef MYGRAPHICSITEM_H
#define MYGRAPHICSITEM_H

#include <QGraphicsItem>

class MyGraphicsItem:public QGraphicsItem
{
public:
    MyGraphicsItem();

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    QRectF boundingRect() const;

};

#endif // MYGRAPHICSITEM_H

mygraphicsview.h

#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H

#include <QGraphicsView>

QT_BEGIN_NAMESPACE
class QGraphicsScene;
class QGraphicsItem;
class QTimeLine;
QT_END_NAMESPACE

class MyGraphicsItem;

class MyGraphicsView : public QGraphicsView
{
    Q_OBJECT
public:
    explicit MyGraphicsView(QWidget *parent = 0);

public slots:
    void updateStep(int value);
    void finished();

signals:
    void mousePos();

protected:
    void mouseMoveEvent(QMouseEvent *event)Q_DECL_OVERRIDE;

private:
    QGraphicsScene *m_scene;
    QList<QGraphicsItem*> m_list;

    QTimeLine *m_timeLine;
    MyGraphicsItem *m_currentItem;

    bool timeLineIsRun;
};

#endif // MYGRAPHICSVIEW_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>


namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    void mouseMoveEvent();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

mygraphicsitem.cpp

#include "mygraphicsitem.h"
#include <QPainter>

MyGraphicsItem::MyGraphicsItem()
{

}

void MyGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->save();
    painter->setPen(QPen(Qt::red,4));
    painter->drawRect(0,0,50,50);
    painter->restore();
}

QRectF MyGraphicsItem::boundingRect() const
{
    return QRectF(0,0,50,50);
}

mygraphicsview.cpp

#include "mygraphicsview.h"
#include "mygraphicsitem.h"
#include <QGraphicsScene>
#include <QTransform>
#include <QMouseEvent>
#include <QTimeLine>
#include <QDebug>

MyGraphicsView::MyGraphicsView(QWidget *parent)
    : QGraphicsView(parent)
{
    MyGraphicsItem *item=new MyGraphicsItem;
    m_scene=new QGraphicsScene;
    this->setScene(m_scene);
    m_scene->addItem(item);

    m_list.append(item);

    setMouseTracking(true);

    m_timeLine=new QTimeLine;
    m_timeLine->setFrameRange(0,500);
    connect(m_timeLine,SIGNAL(frameChanged(int)),this,SLOT(updateStep(int)));
    connect(m_timeLine,SIGNAL(finished()),this,SLOT(finished()));

    m_currentItem=NULL;
    timeLineIsRun=false;
}

void MyGraphicsView::updateStep(int value)
{
    if(m_currentItem==NULL&&timeLineIsRun)
        return;

//    QPointF pt=m_currentItem->boundingRect().center();
//    m_currentItem->setTransformOriginPoint(pt); //it only works for item. isn't QTransform
//    m_currentItem->setRotation(value);


//    QPointF pt=m_currentItem->boundingRect().center();
//    qreal scaleX_Y=value/100.0;
//    QTransform tran;
//    tran.translate(pt.x(),pt.y());  //move to center
//    tran.scale(scaleX_Y,scaleX_Y);
//    m_currentItem->setTransform(tran);
//    QTransform t;
//    t.translate(-pt.x(), -pt.y());  //equal to reset
//    m_currentItem->setTransform(t, true);

    QPointF pt=m_currentItem->boundingRect().center();
    qreal angle=value/2.0;
    QTransform transform;
    transform.translate(pt.x(),pt.y());  //move to center
    transform.rotate(angle,Qt::XAxis);
    m_currentItem->setTransform(transform);
    QTransform t;
    t.translate(-pt.x(), -pt.y());  //equal to reset
    m_currentItem->setTransform(t, true);


    update();
}

void MyGraphicsView::finished()
{
    qDebug()<<"finished!";
    timeLineIsRun=!timeLineIsRun;
    m_currentItem->resetTransform();
    m_currentItem=NULL;
}

void MyGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
    QGraphicsView::mouseMoveEvent(event);
    QTransform transform;
    QGraphicsItem *item=m_scene->itemAt(mapToScene(event->pos()),transform);
    if(item&&!timeLineIsRun){

        //makes item's view big or small
        m_currentItem=static_cast<MyGraphicsItem*>(item);
        m_timeLine->start();
        timeLineIsRun=!timeLineIsRun;
    }
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "mygraphicsitem.h"
#include <QGraphicsScene>
#include <QTransform>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT1995

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值