QGraphicsItem setShear? (适用于单件或多件)

时间:2015-06-16 20:59:31

标签: qt transformation qgraphicsitem

要在QGraphicsItem上应用轮换,我可以调用rotate()setRotation()。我看到的发生了什么:

item.rotate(angle);
正如我所料,

导致轮换;但如果我复制项目(使用子类中的警察构造函数),则不会复制任何旋转(即使我复制了所有转换)。

item.setRotation(angle);

导致项目具有rotation()属性,我可以复制 - 但需要更新。

所以第二个版本就是我需要的。

我希望能够对我的物品施加剪切力。

item.shear(shx, shy);

在初始项目上看起来不错 - 但我找不到复制此剪切的方法。我也找不到与轮换类似的属性:我找不到setShear()

更重要的是,如果我尝试使用变换,以实现群剪(如此question's旋转),我会得到非常奇怪的结果......

如何为剪切创建类似的存储属性?

编辑:

尝试

QTransform t;
t.shear(shx, shy);
item->setTransform(t, true);

还给了我一个巨大的缩放和一些轮换......我试图将shxshy除以100,这似乎是合理的(不确定是否正确?)。

注意 - 会将代码段移动到答案中,因为它似乎可以正常工作。

1 个答案:

答案 0 :(得分:0)

似乎我必须将剪切因子除以100(这似乎并非总是如此)。

void shearItem(qreal shx, qreal shy)
{
    QRectF rect;
    foreach(QGraphicsItem* item, scene()->selectedItems())
        rect |= item->mapToScene(item->boundingRect()).boundingRect();    
    QPointF center = rect.center();

    QTransform t;

    t.translate(center.x(), center.y());
    // seems shear increases item to gigantic proportions so I tried
    t.shear(shx/100, shy/100);
    t.translate(-center.x(), -center.y());

    foreach(QGraphicsItem* item, scene()->selectedItems())
    {
        item->setPos(t.map(item->pos()));
        item->setTransform(t, true);
    }
}

我认为转换是在项目上组合的,所以我不需要做任何动作来组合任何旋转或缩放或剪切...我可以使用

item->setTransform(t, true);

适用于所有变换,因此无需单独设置旋转或缩放。

translate()rotate()scale()shear()方法之间似乎没有任何冲突,并设置了转换矩阵。所以组合这些函数,然后复制转换似乎很好。 (http://doc.qt.io/qt-4.8/qtransform.html#setMatrix)。

似乎没有任何记录的原因需要缩小剪切因子...(http://doc.qt.io/qt-4.8/qtransform.html#shear)。
如果我在项目构造函数中设置剪切,它可以在不必除以100的情况下工作 然而,如果我在上面的代码中调用剪切器,而没有缩小因子,我也会调整大小。我发现这很令人困惑......但只要它有效......

完整示例代码:包括旋转变化和剪切变化

myview.h

#ifndef MYVIEW_H
#define MYVIEW_H

#include <QGraphicsView>
#include <QAction>
#include <QContextMenuEvent>
#include <QGraphicsItem>

class MyView : public QGraphicsView
{
    Q_OBJECT

public:
    MyView(QWidget *parent = 0);

protected:
    virtual void contextMenuEvent(QContextMenuEvent *event);

private slots:
    void rotateItem(qreal deg = 10);
    void shearItem(qreal shx = 10, qreal shy = 10);

private:
    void createActions();
    QAction *rotateAct;
    QAction *shearAct;
};

#endif // MYVIEW_H

myview.cpp

#include "myview.h"
#include <QMenu>

MyView::MyView(QWidget *parent) : QGraphicsView(parent)
{
    createActions();
    setScene(new QGraphicsScene(-500, -150, 1000, 600, this));
    setDragMode(RubberBandDrag);
}

void MyView::contextMenuEvent(QContextMenuEvent *event)
{
    QGraphicsItem* item = itemAt(event->pos());
    if(item != NULL)
        item->setSelected(true);

    if(scene()->selectedItems().isEmpty())  return;

    QMenu menu(this);
    menu.addAction(rotateAct);
    menu.addAction(shearAct);
    menu.exec(event->globalPos());
}

void MyView::rotateItem(qreal deg)
{
    QRectF rect;
    foreach(QGraphicsItem* item, scene()->selectedItems())
        rect |= item->mapToScene(item->boundingRect()).boundingRect();    
    QPointF center = rect.center();

    QTransform t;
    t.translate(center.x(), center.y());
    t.rotate(deg);
    t.translate(-center.x(), -center.y());

    foreach(QGraphicsItem* item, scene()->selectedItems())
    {
        item->setPos(t.map(item->pos()));
        item->setRotation(item->rotation() + deg);
    }
}

void MyView::shearItem(qreal shx, qreal shy)
{
    QRectF rect;
    foreach(QGraphicsItem* item, scene()->selectedItems())
        rect |= item->mapToScene(item->boundingRect()).boundingRect();    
    QPointF center = rect.center();

    QTransform t;

    t.translate(center.x(), center.y());
    t.shear(shx, shy);
    // seems shear increases item to gigantic proportions so I tried
    //t.shear(shx/100, shy/100);
    t.translate(-center.x(), -center.y());

    foreach(QGraphicsItem* item, scene()->selectedItems())
    {
        item->setPos(t.map(item->pos()));
        item->setTransform(t, true);
    }
}

void MyView::createActions()
{
    rotateAct = new QAction(tr("Rotate 10 degrees"), this);
    connect(rotateAct, SIGNAL(triggered()), this, SLOT(rotateItem()));
    shearAct = new QAction(tr("Shear 10, 10"), this);
    connect(shearAct, SIGNAL(triggered()), this, SLOT(shearItem()));
}

main.cpp中:

#include <QtGui>    
#include "myview.h"    

int main( int argc, char **argv )
{
    QApplication app(argc, argv);
    MyView* view = new MyView();

    QGraphicsRectItem* rItem = view->scene()->addRect(30, 40, 100, 100, Qt::NoPen, Qt::blue);
    QGraphicsRectItem* rItem1 = view->scene()->addRect(-30, -40, 100, 100, Qt::NoPen, Qt::red);
    QGraphicsEllipseItem* eItem = view->scene()->addEllipse(70, -50, 100, 100, Qt::NoPen, Qt::blue);

    foreach(QGraphicsItem* item, view->scene()->items())
    {
        item->setFlag(QGraphicsItem::ItemIsMovable);
        item->setFlag(QGraphicsItem::ItemIsFocusable);
        item->setFlag(QGraphicsItem::ItemIsSelectable);
    }

    view->show();
    return app.exec();
}