2017-04-23 242 views
0

我是Qt新手,我很困惑如何使用QGraphicsScene。如果我將10個橢圓添加到場景中,並沿着路徑對它們進行動畫處理,那我該怎麼做?它變得更加複雜,因爲如果我沿着橢圓繪製了10個橢圓,並且我想要對這些橢圓進行動畫處理,以便它們離開它們所在橢圓的中心。在圖片中你可以看到橢圓。這些是用QPainter繪製的我還沒有想出如何將它們添加到場景中,但我希望灰色橢圓在內部和外部圓圈之間移動。我已經通過一些例子,但不能真正適合我的情況。沿着圓形的Qt動畫橢圓

代碼用於與QPainter的繪製橢圓:

QPainter drElps; 
drElps.setBrush(QBrush(QColor(0xaf, 0xaf, 0xaa))); 
drElps.setPen(QPen(QColor(0xaf, 0xaf, 0xaa), 2)); 
double nrElps = 30; 
int degree = (int)(360./nrElps); 
painter.translate(QPointF(big_elps_circle_center)); 
while(--nrElps){ 
painter.drawEllipse(0, -60, 3, 3); 
painter.rotate(degree); 
} 
painter.translate(QPOintF(back_to_origin)); 

Static image

+0

你可以顯示你已經與QPainter的實現代碼。 – eyllanesc

+0

@eyllanesc我已添加代碼。我記得這段代碼,因爲我現在沒有可用的代碼。 – Croolman

回答

1

Qt擁有一套面向動畫類,爲此,你必須首先創建從QGraphicsObject繼承而來的對象,在這個類,你必須實現的方法paintboundingRect

ellipseobject.h

#ifndef ELLIPSEOBJECT_H 
#define ELLIPSEOBJECT_H 

#include <QGraphicsObject> 

class EllipseObject : public QGraphicsObject 
{ 
    Q_OBJECT 
public: 
    EllipseObject(QGraphicsItem * parent = 0); 

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

#endif // ELLIPSEOBJECT_H 

ellipseobject.cpp

#include "ellipseobject.h" 

#include <QPainter> 

EllipseObject::EllipseObject(QGraphicsItem *parent):QGraphicsObject(parent) 
{ 

} 

void EllipseObject::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 
{ 
    Q_UNUSED(option) 
    Q_UNUSED(widget) 
    painter->setRenderHint(QPainter::Antialiasing); 
    painter->setPen(QColor(0xaf, 0xaf, 0xaa)); 
    painter->setBrush(QBrush(QColor(0xaf, 0xaf, 0xaa))); 
    QRectF rect = boundingRect(); 
    painter->drawEllipse(rect); 
} 

QRectF EllipseObject::boundingRect() const 
{ 
    return QRectF(-4, -4, 8, 8); 
} 

然後我們可以使用QPropertyAnimation類,與這一點,我們將動畫的位置。

EllipseObject *item = new EllipseObject; 
QPropertyAnimation *animation = new QPropertyAnimation(item, "pos"); 
for(int j = 0; j < p; j++){ 
    animation->setKeyValueAt(1.0*j/(p-1), 
           (r+ delta*sin(2*M_PI*j/p))*QPointF(qSin(2*M_PI*i/number_of_items), qCos(2*M_PI*i/number_of_items))); 
} 
animation->setDuration(2000); 

因爲我們有並行的動畫幾個元素,我們可以用QParallelAnimationGroup來處理每一個動畫。

group = new QParallelAnimationGroup(this); 
[...] 
group->addAnimation(animation); 

如果我們想要連續,我們可以製作下面的代碼。

group->start(); 
connect(group, &QParallelAnimationGroup::finished,[=](){ 
    group->start(); 
}); 

的完整源代碼here

enter image description here

+0

這是迄今爲止最好的,雖然它不完全是我想要的它給出了一個非常清晰的想法。雖然我認爲我將它與'advance()'方法結合使用,但是github鏈接導致空的Qt項目。 – Croolman

+0

'advance()',你是什麼意思? – eyllanesc

+0

'QGraphicsScene'的'advance()'方法可以在超時時調用,類似於@king_nak的答案在 – Croolman

1

如果繪製他們的QPainter那麼你對你的。 QGraphivsScene的要點是從QGraphicsItem繼承,繪製paintEvent上需要繪製的內容,將它們添加到場景中。

你在paintEvent上繪製了超過1個項目 - 所以你是你自己的 - 而QGraphivsScene不能幫你。現在

,該怎麼做正確:

  • 繼承QGraphicsScene或QGraphivsView
  • 繼承QGraphicsEllipseItem並創建一個MovableEllipseItem在MovableEllipseItem構造
  • ,創建一個QTimer,連接它的超時()信號與移動插槽,您將定義

在您的移動插槽上,計算橢圓的位置並移動(x,y)它。

+0

我是否正確理解,那麼對於添加到場景中的每個橢圓,都會有一個單獨的定時器? – Croolman

+0

如果您將QTimer添加爲Ellipse對象內部的靜態內容,那麼您只需要一個。重要的是將timeout()連接到每個Ellipse實例。 –

1

您可以使用自定義圖形項目,QGraphicsScene::advance機制以及QTimeLine來控制動畫。

輪廓是這樣的:

QGraphicsScene *sc = new QGraphicsScene; 
QTimeLine *tl = new QTimeLine(1000); 
tl->setFrameRange(-20, 20); 
connect(tl, &QTimeLine::frameChanged, sc, &QGraphicsScene::advance); 
connect(tl, &QTimeLine::finished, tl, &QTimeLine::toggleDirection); 
connect(tl, &QTimeLine::finished, tl, &QTimeLine::start); 

for (int i = 0; i < 30; ++i) { 
    sc->addItem(new AnimItem(360./30*i, tl)); 
} 

在自定義AnimItem,需要實現繪圖/動畫邏輯。一個好的基地將是QGraphicsEllipseItem。例如:

AnimItem::AnimItem(qreal angle, QTimeLine *timer, QGraphicsItem *parent) 
    : QGraphicsEllipseItem(0, 0, 3, 3, parent), 
     m_timer(timer) 
{ 
    QTransform t; 
    t.rotate(angle); 
    t.translate(0, -120); 
    setTransform(t); 
    setBrush(QBrush(QColor(0xaf, 0xaf, 0xaa))); 
} 

void AnimItem::advance(int phase) 
{ 
    if (phase == 1) { 
     QTransform t = transform(); 
     t.translate(0, m_timer->currentFrame()/5); 
     setTransform(t); 
    } 
} 
+0

這段代碼將動態創建大橢圓周圍的橢圓,不會嗎?這將會像加載動畫一樣。我需要他們全部在同一時間超時 - 最好,但不是必要的情況下,在隨機方向,在這兩個更大的橢圓之間。我承認我可能會表達自己不太清楚。 – Croolman