QGraphicsItem setShear ? (适用于单件或多件)
QGraphicsItem setShear ? (applicable for single or multiple items)
要在 QGraphicsItem 上应用旋转,我可以调用 rotate()
或 setRotation()
。我看到的情况:
item.rotate(angle);
结果轮换,如我所料;但是如果我复制该项目(在子类中使用 cop 构造函数),则不会复制旋转(即使我复制所有转换)。
item.setRotation(angle);
导致项目具有 rotation()
属性 我可以复制 - 但需要更新。
所以第二个版本就是我需要的。
我也希望能够对我的项目应用剪切。
item.shear(shx, shy);
初始项目看起来不错 - 但我找不到复制此剪刀的方法。我也找不到与旋转类似的 属性:我找不到 setShear()
。
更重要的是,如果我尝试使用变换来实现组剪切(像这样 旋转),我会得到非常奇怪的结果...
如何为剪切创建一个类似的存储 属性?
编辑:
正在尝试
QTransform t;
t.shear(shx, shy);
item->setTransform(t, true);
也给了我一个巨大的缩放比例和一些旋转...我试图将 shx
和 shy
除以 100,这似乎是合理的(不确定是否正确?)。
注意 - 将在答案中移动代码片段,因为它似乎可以工作。
看来我必须将剪切因子除以 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();
}
要在 QGraphicsItem 上应用旋转,我可以调用 rotate()
或 setRotation()
。我看到的情况:
item.rotate(angle);
结果轮换,如我所料;但是如果我复制该项目(在子类中使用 cop 构造函数),则不会复制旋转(即使我复制所有转换)。
item.setRotation(angle);
导致项目具有 rotation()
属性 我可以复制 - 但需要更新。
所以第二个版本就是我需要的。
我也希望能够对我的项目应用剪切。
item.shear(shx, shy);
初始项目看起来不错 - 但我找不到复制此剪刀的方法。我也找不到与旋转类似的 属性:我找不到 setShear()
。
更重要的是,如果我尝试使用变换来实现组剪切(像这样
如何为剪切创建一个类似的存储 属性?
编辑:
正在尝试
QTransform t;
t.shear(shx, shy);
item->setTransform(t, true);
也给了我一个巨大的缩放比例和一些旋转...我试图将 shx
和 shy
除以 100,这似乎是合理的(不确定是否正确?)。
注意 - 将在答案中移动代码片段,因为它似乎可以工作。
看来我必须将剪切因子除以 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();
}