Qt 如何在QGraphicsView中执行QGraphicsSitem的交换?
我在这个项目中的想法是对项目执行交换动画。 但问题是,当我第一次对项目执行交换时,它们保持其位置不变,但当其他动画开始时,涉及到已交换的项目,这些项目会返回到其初始位置。请告诉我我做错了什么。动画如下:Qt 如何在QGraphicsView中执行QGraphicsSitem的交换?,qt,swap,qgraphicsview,qgraphicswidget,Qt,Swap,Qgraphicsview,Qgraphicswidget,我在这个项目中的想法是对项目执行交换动画。 但问题是,当我第一次对项目执行交换时,它们保持其位置不变,但当其他动画开始时,涉及到已交换的项目,这些项目会返回到其初始位置。请告诉我我做错了什么。动画如下: #包括 #包括 /** *要在QGraphicsView中显示的元素 */ 类QGraphicsRectWidget:公共QGraphicsWidget { Q_对象 整数m_数; 公众: 无效更改位置(QGraphicsRectWidget*其他) { setPos(mapToParent(
#包括
#包括
/**
*要在QGraphicsView中显示的元素
*/
类QGraphicsRectWidget:公共QGraphicsWidget
{
Q_对象
整数m_数;
公众:
无效更改位置(QGraphicsRectWidget*其他)
{
setPos(mapToParent(其他->x()x())
:abs(x()-其他->x()),0);
}
静态整数;
QGraphicsRectWidget(QGraphicsSitem*parent=0):QGraphicsWidget(parent),m_编号(number)
{NUMBER++;}
空漆(QPainter*油漆工,const QstyleOptionGraphics现场*,
QWidget*)Q_DECL_覆盖
{
painter->fillRect(rect(),QColor(127,63,63));
painter->drawText(rect(),QString(“%1”).arg(m_编号),QTextOption(Qt::AlignCenter));
}
};
int QGraphicsRectWidget::NUMBER=1;
MyAnim类:公共QPropertyAnimation
{
Q_对象
QGraphicsView&pview;//必须在其中交换元素的视图
int i1,i2;//要交换的元素的索引
公众:
MyAnim(QGraphicsView&view,int index1=0,int index2=1,QObject*par=0)
:QPropertyAnimation(par)、pview(view)、i1(index1)、i2(index2)
{
QObject::connect(这个,信号(finished()),插槽(slotOnFinish());
}
公众时段:
/**/
//动画结束时触发,并将目标元素的位置设置为其结束值的位置
void slotOnFinish()
{
自动列表=pview.items();
静态施法(列表at(i1))
->转换位置(静态_转换(列表位于(i2));
}
};
类GraphicsView:公共QGraphicsView
{
Q_对象
公众:
GraphicsView(QGraphicscene*场景,QWidget*父对象=NULL):QGraphicsView(场景,父对象)
{
}
受保护的:
虚拟void resizeEvent(QResizeEvent*事件)Q_DECL_覆盖
{
fitInView(scene()->scene());
QGraphicsView::resizeEvent(事件);
}
};
#定义交换单元高度75
/**
*为QGraphicsView中的项目创建交换动画
*/
QParallelLanimationGroup*getSwapAnimation(QGraphicsView&view,int-noItem1,int-noItem2)
{
自动列表=view.items();
QGraphicsRectWidget*wgt1=静态_cast(list.at(noItem1));
qgraphicsretwidget*wgt2=静态_cast(list.at(noItem2));
MyAnim*pupperAnim,*plowerAnim;
QParallelLanimationGroup*par=新的QParallelLanimationGroup;
plowerAnim=新MyAnim(视图,noItem1,noItem2);
plowerAnim->setTargetObject(wgt2);
plowerAnim->setPropertyName(“pos”);
plowerAnim->setDuration(5000);
plowerAnim->setKeyValueAt(1.0/3.0,QPoint(wgt2->x(),wgt1->y()-交换高度));
plowerAnim->setKeyValueAt(2.0/3.0,QPoint(wgt1->x(),wgt1->y()-交换高度));
plowerAnim->setEndValue(wgt1->pos());
pupperAnim=新MyAnim(视图,noItem2,noItem1);
pupperAnim->setTargetObject(wgt1);
pupperAnim->setPropertyName(“pos”);
pupperAnim->setDuration(5000);
pupperAnim->setKeyValueAt(1.0/3.0,QPoint(wgt1->x(),wgt2->y()+交换高度));
pupperAnim->setKeyValueAt(2.0/3.0,QPoint(wgt2->x(),wgt2->y()+交换高度));
pupperAnim->setEndValue(wgt2->pos());
par->addAnimation(木偶动画);
par->addAnimation(plowerAnim);
返回票面金额;
}
int main(int argc,字符**argv)
{
QApplication应用程序(argc、argv);
QGraphicsRectWidget*按钮1=新的QGraphicsRectWidget;
QGraphicsRectWidget*按钮2=新的QGraphicsRectWidget;
QGraphicsRectWidget*按钮3=新的QGraphicsRectWidget;
QGraphicsRectWidget*按钮4=新的QGraphicsRectWidget;
按钮2->设置值(1);
按钮3->设置值(2);
按钮4->设置值(3);
Qgraphicscene场景(0,0,300,300);
场景:挫折地刷(QColor(23,0,0));
场景。附加项(按钮1);
场景.附加项(按钮2);
场景.附加项(按钮3);
场景.附加项(按钮4);
图形视图窗口(和场景);
window.setFrameStyle(0);
setAlignment(Qt::AlignLeft | Qt::AlignTop);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QList items=window.items();
点启动(20,125);
for(auto item:items)//在初始位置设置项
{
QGraphicsWidget*wgt=静态铸件(项目);
wgt->调整大小(50,50);
wgt->moveBy(start.x(),start.y());
start.setX(start.x()+70);
}
QSequentialAnimationGroup gr;
gr.addAnimation(getSwapAnimation(窗口,0,1));
gr.addAnimation(getSwapAnimation(窗口,1,2));
gr.addAnimation(getSwapAnimation(窗口,2,3));
gr.addAnimation(getSwapAnimation(窗口,3,1));
gr.start();
调整窗口大小(300300);
window.show();
返回app.exec();
}
#包括“main.moc”
UPD:不要为了这个目的而使用动画
UPD*:忘记上一个UPD您的动画将保留创建动画时所涉及项目的位置。在第二个动画运行时,此信息无效 你需要重新设计动画
#include <QtCore>
#include <QtWidgets>
/**
* Element to be displayed in QGraphicsView
*/
class QGraphicsRectWidget : public QGraphicsWidget
{
Q_OBJECT
int m_number;
public:
void changePosition(QGraphicsRectWidget *other)
{
setPos(mapToParent(other->x() < x() ? -abs(x() - other->x())
: abs(x() - other->x()) ,0));
}
static int NUMBER;
QGraphicsRectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent), m_number(NUMBER)
{ NUMBER++;}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *) Q_DECL_OVERRIDE
{
painter->fillRect(rect(), QColor(127, 63, 63));
painter->drawText(rect(), QString("%1").arg(m_number), QTextOption(Qt::AlignCenter));
}
};
int QGraphicsRectWidget::NUMBER = 1;
class MyAnim : public QPropertyAnimation
{
Q_OBJECT
QGraphicsView &pview; // View in which elements must be swapped
int i1, i2; // Indices for elements to be swapped
public:
MyAnim(QGraphicsView &view, int index1 = 0, int index2 = 1, QObject *par = 0)
: QPropertyAnimation(par), pview(view), i1(index1), i2(index2)
{
QObject::connect(this, SIGNAL(finished()), SLOT(slotOnFinish()));
}
public slots:
/* !!!!!!!!!!!!!!!!!!!!!!! HERE IS THE PROBLEM (brobably) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
// Triggered when animation is over and sets position of target element to position of its end value
void slotOnFinish()
{
auto list = pview.items();
static_cast<QGraphicsRectWidget*>(list.at(i1))
->changePosition(static_cast<QGraphicsRectWidget*>(list.at(i2)));
}
};
class GraphicsView : public QGraphicsView
{
Q_OBJECT
public:
GraphicsView(QGraphicsScene *scene, QWidget *parent = NULL) : QGraphicsView(scene, parent)
{
}
protected:
virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE
{
fitInView(scene()->sceneRect());
QGraphicsView::resizeEvent(event);
}
};
#define SWAP_HEIGHT 75
/**
* Creates swap animation for items in QGraphicsView
*/
QParallelAnimationGroup* getSwapAnimation(QGraphicsView &view, int noItem1, int noItem2)
{
auto list = view.items();
QGraphicsRectWidget *wgt1 = static_cast<QGraphicsRectWidget*>(list.at(noItem1));
QGraphicsRectWidget *wgt2 = static_cast<QGraphicsRectWidget*>(list.at(noItem2));
MyAnim *pupperAnim, *plowerAnim;
QParallelAnimationGroup *par = new QParallelAnimationGroup;
plowerAnim = new MyAnim(view, noItem1, noItem2);
plowerAnim->setTargetObject(wgt2);
plowerAnim->setPropertyName("pos");
plowerAnim->setDuration(5000);
plowerAnim->setKeyValueAt(1.0/3.0, QPoint(wgt2->x(), wgt1->y() - SWAP_HEIGHT));
plowerAnim->setKeyValueAt(2.0/3.0, QPoint(wgt1->x(), wgt1->y() - SWAP_HEIGHT));
plowerAnim->setEndValue(wgt1->pos());
pupperAnim = new MyAnim(view, noItem2, noItem1);
pupperAnim->setTargetObject(wgt1);
pupperAnim->setPropertyName("pos");
pupperAnim->setDuration(5000);
pupperAnim->setKeyValueAt(1.0/3.0, QPoint(wgt1->x(), wgt2->y() + SWAP_HEIGHT));
pupperAnim->setKeyValueAt(2.0/3.0, QPoint(wgt2->x(), wgt2->y() + SWAP_HEIGHT));
pupperAnim->setEndValue(wgt2->pos());
par->addAnimation(pupperAnim);
par->addAnimation(plowerAnim);
return par;
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QGraphicsRectWidget *button1 = new QGraphicsRectWidget;
QGraphicsRectWidget *button2 = new QGraphicsRectWidget;
QGraphicsRectWidget *button3 = new QGraphicsRectWidget;
QGraphicsRectWidget *button4 = new QGraphicsRectWidget;
button2->setZValue(1);
button3->setZValue(2);
button4->setZValue(3);
QGraphicsScene scene(0, 0, 300, 300);
scene.setBackgroundBrush(QColor(23, 0, 0));
scene.addItem(button1);
scene.addItem(button2);
scene.addItem(button3);
scene.addItem(button4);
GraphicsView window(&scene);
window.setFrameStyle(0);
window.setAlignment(Qt::AlignLeft | Qt::AlignTop);
window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QList<QGraphicsItem*> items = window.items();
QPoint start(20, 125);
for (auto item : items) // Set items in initial position
{
QGraphicsWidget *wgt = static_cast<QGraphicsWidget*>(item);
wgt->resize(50,50);
wgt->moveBy(start.x(), start.y());
start.setX(start.x() + 70);
}
QSequentialAnimationGroup gr;
gr.addAnimation(getSwapAnimation(window, 0, 1));
gr.addAnimation(getSwapAnimation(window, 1, 2));
gr.addAnimation(getSwapAnimation(window, 2, 3));
gr.addAnimation(getSwapAnimation(window, 3, 1));
gr.start();
window.resize(300, 300);
window.show();
return app.exec();
}
#include "main.moc"
// https://github.com/KubaO/stackoverflown/tree/master/questions/scene-anim-swap-40787655
#include <QtWidgets>
#include <cmath>
class QGraphicsRectWidget : public QGraphicsWidget
{
public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
{
painter->fillRect(rect(), Qt::blue);
painter->setPen(Qt::yellow);
painter->drawText(rect(), QString::number(zValue()), QTextOption(Qt::AlignCenter));
}
};
class SwapAnimation : public QPropertyAnimation
{
QPointer<QObject> other;
qreal offset;
QPoint propertyOf(QObject *obj) {
return obj->property(propertyName().constData()).toPoint();
}
void updateState(State newState, State oldState) override {
if (newState == Running && oldState == Stopped) {
auto start = propertyOf(targetObject());
auto end = propertyOf(other);
auto step1 = fabs(offset);
auto step2 = QLineF(start,end).length();
auto steps = 2.0*step1 + step2;
setStartValue(start);
setKeyValueAt(step1/steps, QPoint(start.x(), start.y() + offset));
setKeyValueAt((step1+step2)/steps, QPoint(end.x(), end.y() + offset));
setEndValue(end);
setDuration(10.0 * steps);
}
QPropertyAnimation::updateState(newState, oldState);
}
public:
SwapAnimation(QObject *first, QObject *second, qreal offset) : other(second), offset(offset) {
setTargetObject(first);
setPropertyName("pos");
}
};
QParallelAnimationGroup* getSwapAnimation(QObject *obj1, QObject *obj2)
{
auto const swapHeight = 75.0;
auto par = new QParallelAnimationGroup;
par->addAnimation(new SwapAnimation(obj2, obj1, -swapHeight));
par->addAnimation(new SwapAnimation(obj1, obj2, swapHeight));
return par;
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QGraphicsScene scene(0, 0, 300, 300);
QGraphicsRectWidget buttons[4];
int i = 0;
QPointF start(20, 125);
for (auto & button : buttons) {
button.setZValue(i++);
button.resize(50,50);
button.setPos(start);
start.setX(start.x() + 70);
scene.addItem(&button);
}
QSequentialAnimationGroup gr;
gr.addAnimation(getSwapAnimation(&buttons[0], &buttons[1]));
gr.addAnimation(getSwapAnimation(&buttons[1], &buttons[2]));
gr.addAnimation(getSwapAnimation(&buttons[2], &buttons[3]));
gr.addAnimation(getSwapAnimation(&buttons[3], &buttons[1]));
gr.start();
QGraphicsView view(&scene);
view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view.resize(300, 300);
view.show();
return app.exec();
}