通过实现:一个在其中显示各种类型QGraphicsItem的窗口例子,介绍如何使用Qt预定义的各种标准的QGraphicsItem类型(如QGraphicsEllipseItem、QGraphicsRectItem等),以及自定义的QGraphicsItem类型(如本例中不停闪烁的圆及来回移动的星星等)来创建图元。
QTimeLine类提供用于控制动画的时间表,通常用于定期调用插槽来为GUI控件创建动画。简单来说,就是可以通过 QTimeLine 来快速的实现动画效果,其原理就是在指定的时间内发出固定帧率的信号,通过连接该信号去改变目标控件的值,由于时间断帧率高,所以整体看起来就是连续的动画效果。
以上说得可能有些抽象,下面结合实例和用法步骤来看看。
用法
将使用步骤总结为以下几点:1.创建 QTimeLine对象的时候传入时间值,单位是毫秒,该时间就是动画运行的时间;
2.设置帧率范围,通过setFrameRange()进行设置,该值表示在规定的时间内将要执行多少帧;
3.连接frameChanged()信号,并在槽中对需要实现动画的控件进行赋值,如QProgressBar的setValue().
4.调用 start()开始执行时间轴动作。
例如:
progressBar = new QProgressBar(this);
progressBar->setRange(0, 100);
progressBar->move(100,100);
// Construct a 1-second timeline with a frame range of 0 - 100
QTimeLine *timeLine = new QTimeLine(1000, this);
timeLine->setFrameRange(0, 100);
connect(timeLine, SIGNAL(frameChanged(int)), progressBar, SLOT(setValue(int)));
// Clicking the push button will start the progress bar animation
QPushButton * pushButton = new QPushButton(tr("Start animation"), this);
connect(pushButton, SIGNAL(clicked()), timeLine, SLOT(start()));
当 QTimeLine调用 start()后将进入运行状态,并会发出frameChanged()信号,而连接该信号的槽中将会不断的对目标控件进行相应的动作赋值,从而实现动画效果。
可以通过调用setUpdateInterval()来指定更新间隔。完成后,QTimeLine进入NotRunning状态,并发出finished().
默认情况下,时间轴从开始到结束运行一次,此时必须再次调用start()才能从头开始重新启动。要进行时间线循环,您可以调用setLoopCount(),并在完成之前传递时间轴应该运行的次数。
通过调用setDirection(),方向也可以改变,可以让时间线向后运行。
也可以通过调用setPaused()来暂停和取消暂停时间轴的运行。
对于交互式控件,提供了setCurrentTime()函数,该函数直接设置时间线的时间位置。
原文链接:https://blog.csdn.net/luoyayun361/article/details/80381984
图元的动画显示有江中两种方式可以实现:
1.利用 QGraphicsItemAnimation类和QTimLine类实现 。如本例中圆是闪烁功能的实现
2.在图元类中利用定时器QTimer和图元的重画函数paint()实现。如本例中星星不停的左右移动
flash.h
#ifndef FLASH_H
#define FLASH_H
#include
#include
#include
class Flash : public QObject,public QGraphicsItem
{
Q_OBJECT
public:
explicit Flash(QObject *parent = nullptr);
QRectF boundingRect() const; //图元边界函数,完成以图元坐标系为基础,增加两个像素点的冗余工作
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) ;
void timerEvent(QTimerEvent *);
private:
bool flash;
QTimer *timer;
signals:
};
#endif // FLASH_H
flash.cpp
#include "flash.h"
Flash::Flash(QObject *parent) : QObject(parent)
{
flash=true;
setFlag(ItemIsMovable);
startTimer(1000);
}
QRectF Flash::boundingRect() const //图元边界函数,完成以图元坐标系为基础,增加两个像素点的冗余工作
{
qreal adjuct=2;
return QRectF(-10-adjuct,-10-adjuct,43+adjuct,43+adjuct);
}
void Flash::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(Qt::NoPen); //闪烁图元的阴影区不绘制边线
painter->setBrush(Qt::darkGray); //闪烁图元的阴影区的阴影画刷颜色为深灰
painter->drawEllipse(-7,-7,40,40); //绘制阴影区
painter->setPen(QPen(Qt::black,0)); //闪烁区的椭圆边线颜色为黑色,线宽为0
painter->setBrush(flash?(Qt::red):(Qt::yellow));
//设置闪烁区的椭圆画刷颜色根据颜色切换标识flash决定填充哪一种颜色,颜色在红色和黄色之间选择
painter->drawEllipse(-10,-10,40,40); //绘制与阴影区同样大小的椭圆,并错开一定的距离实现立体效果
}
void Flash::timerEvent(QTimerEvent *) //定时器响应闪烁效果
{
flash=!flash;
update();
}
startItem.h
#ifndef STARTITEM_H
#define STARTITEM_H
#include
#include
#include
class StartItem : public QObject
{
Q_OBJECT
public:
explicit StartItem(QObject *parent = nullptr);
QRectF boundingRect() const; //图元边界函数
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) ;
StartItem();
private:
QPixmap pix;
signals:
};
#endif // STARTITEM_H
startItem.cpp
#include "startitem.h"
StartItem::StartItem(QObject *parent) : QObject(parent)
{
}
StartItem::StartItem()
{
pix.load(":/new/images/star.png");
}
QRectF StartItem::boundingRect() const
{
return QRectF (-pix.width()/2,-pix.height()/2,pix.width(),pix.width());
}
void StartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawPixmap(boundingRect().topLeft(),pix);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void initScene(); //初始化场景
void createAction(); //创建主窗体的所有动作
void createMenus(); //创建主窗体的菜单栏
private:
QGraphicsScene *scene;
QAction *act_New;
QAction *act_Clear;
QAction *act_exit;
QAction *act_addEllipseItem;
QAction *act_addPolygonItem;
QAction *act_addTextItem;
QAction *act_addRectItem;
QAction *act_addAlphaItem;
QAction *act_addflashItem;
QAction *act_addAnimItem;
public slots:
void slotNew(); //新建一个显示窗体
void slotClear(); //清除场景中所有的图元
void slotAddEllipseItem(); //在场景中加入一个椭圆形图元
void slotAddPolygonItem(); //在场景中加入一个多边形形图元
void slotAddTextItem(); //在场景中加入一个文字图元
void slotAddRectItem(); //在场景中加入一个长方形形图元
void slotAddAlphaItem(); //在场景中加入一个透明蝴蝶图片
void slotAddFlashItem(); //在场景中加入一个闪烁图元
void slotAddAnimationItem(); //在场景中加入一个动画星星
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "flash.h"
#include
#include
#include "startitem.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
createAction(); //创建主窗体的所有动作
createMenus(); //创建主窗体的菜单栏
scene=new QGraphicsScene;
scene->setSceneRect(-200,-200,400,400);
initScene();
QGraphicsView *view=new QGraphicsView;
view->setScene(scene);
view->setMinimumSize(400,400);
view->show();
setCentralWidget(view);
setWindowTitle(QStringLiteral("Graphics Items"));
}
MainWindow::~MainWindow()
{
}
void MainWindow::createAction() //创建主窗体的所有动作
{
act_New=new QAction(QStringLiteral("新建"),this);
act_Clear=new QAction(QStringLiteral("清除"),this);
act_exit=new QAction(QStringLiteral("退出"),this);
act_addEllipseItem=new QAction(QStringLiteral("加入 椭圆"),this);
act_addPolygonItem=new QAction(QStringLiteral("加入 多边形"),this);
act_addTextItem=new QAction(QStringLiteral("加入 文字"),this);
act_addRectItem=new QAction(QStringLiteral("加入 长方形"),this);
act_addAlphaItem=new QAction(QStringLiteral("加入 透明图片"),this);
act_addflashItem=new QAction(QStringLiteral("加入 闪烁圆"),this);
act_addAnimItem=new QAction(QStringLiteral("加入 星星"),this);
connect(act_New,SIGNAL(triggered()),this,SLOT(slotNew()));
connect(act_Clear,SIGNAL(triggered()),this,SLOT(slotClear()));
connect(act_exit,SIGNAL(triggered()),this,SLOT(close()));
connect(act_addEllipseItem,SIGNAL(triggered()),this,SLOT(slotAddEllipseItem()));
connect(act_addPolygonItem,SIGNAL(triggered()),this,SLOT(slotAddPolygonItem()));
connect(act_addTextItem,SIGNAL(triggered()),this,SLOT(slotAddTextItem()));
connect(act_addRectItem,SIGNAL(triggered()),this,SLOT(slotAddRectItem()));
connect(act_addAlphaItem,SIGNAL(triggered()),this,SLOT(slotAddAlphaItem()));
connect(act_addflashItem,SIGNAL(triggered()),this,SLOT(slotAddFlashItem()));
connect(act_addAnimItem,SIGNAL(triggered()),this,SLOT(slotAddAnimationItem()));
}
void MainWindow::createMenus() //创建主窗体的菜单栏
{
QMenu *fileMenu=menuBar()->addMenu(QStringLiteral("文件"));
fileMenu->addAction(act_New);
fileMenu->addAction(act_Clear);
fileMenu->addSeparator();
fileMenu->addAction(act_exit);
QMenu *itemMenu=menuBar()->addMenu(QStringLiteral("元素"));
itemMenu->addAction(act_addEllipseItem);
itemMenu->addAction(act_addPolygonItem);
itemMenu->addAction(act_addTextItem);
itemMenu->addAction(act_addRectItem);
itemMenu->addAction(act_addAlphaItem);
itemMenu->addAction(act_addflashItem);
itemMenu->addAction(act_addAnimItem);
}
void MainWindow::initScene() //初始化场景
{
int i;
for(i=0;i<3;i++)
slotAddEllipseItem();
for(i=0;i<3;i++)
slotAddPolygonItem();
for(i=0;i<3;i++)
slotAddTextItem();
for(i=0;i<3;i++)
slotAddRectItem();
for(i=0;i<3;i++)
slotAddAlphaItem();
for(i=0;i<3;i++)
slotAddFlashItem();
for(i=0;i<3;i++)
slotAddAnimationItem();
}
void MainWindow::slotClear() //清除场景中所有的图元
{
QList listItem =scene->items();
while(!listItem.empty())
{
scene->removeItem(listItem.at(0));
listItem.removeAt(0);
}
}
void MainWindow::slotNew() //新建一个显示窗体
{
slotClear();
initScene();
MainWindow *newWin=new MainWindow;
newWin->show();
}
void MainWindow::slotAddEllipseItem() //在场景中加入一个椭圆形图元
{
QGraphicsEllipseItem *item=new QGraphicsEllipseItem(QRectF (0,0,80,60));
item->setBrush(QColor(qrand()%256,qrand()*256,qrand()%256));
item->setFlag(QGraphicsItem::ItemIsMovable);
scene->addItem(item);
item->setPos((qrand()%int(scene->sceneRect().width())-200),
((qrand()%int(scene->sceneRect().height()))-200)
);
}
void MainWindow::slotAddPolygonItem() //在场景中加入一个多边形形图元
{
QVector v;
v<< QPoint(30,-15) <setBrush(QColor(qrand()%256,qrand()*256,qrand()%256));
item->setFlag(QGraphicsItem::ItemIsMovable);
scene->addItem(item);
item->setPos((qrand()%int(scene->sceneRect().width())-200),
((qrand()%int(scene->sceneRect().height()))-200)
);
}
void MainWindow::slotAddTextItem() //在场景中加入一个文字图元
{
QFont font("Times",16);
QGraphicsTextItem *item = new QGraphicsTextItem("Hello Qt");
item->setFont(font);
item->setDefaultTextColor(QColor(qrand()%256,qrand()*256,qrand()%256));
item->setFlag(QGraphicsItem::ItemIsMovable);
scene->addItem(item);
item->setPos((qrand()%int(scene->sceneRect().width())-200),
((qrand()%int(scene->sceneRect().height()))-200)
);
}
void MainWindow::slotAddRectItem() //在场景中加入一个长方形形图元
{
QGraphicsRectItem *item=new QGraphicsRectItem(QRectF(0,0,60,50));
QPen pen;
pen.setWidth(3);
pen.setColor(QColor(qrand()%256,qrand()*256,qrand()%256));//画笔和画刷的颜色随机
item->setPen(pen);
item->setBrush(QColor(qrand()%256,qrand()*256,qrand()%256));
item->setFlag(QGraphicsItem::ItemIsMovable);
scene->addItem(item);
item->setPos((qrand()%int(scene->sceneRect().width())-200),
((qrand()%int(scene->sceneRect().height()))-200)
);
}
void MainWindow::slotAddAlphaItem() //在场景中加入一个透明蝴蝶图片
{
QGraphicsPixmapItem *item =scene->addPixmap(QPixmap(":/new/images/image.png"));
item->setFlag(QGraphicsItem::ItemIsMovable);
item->setPos((qrand()%int(scene->sceneRect().width())-200),
((qrand()%int(scene->sceneRect().height()))-200)
);
}
void MainWindow::slotAddFlashItem() //在场景中加入一个闪烁图元
{
Flash *item=new Flash;
scene->addItem(item);
item->setPos((qrand()%int(scene->sceneRect().width())-200),
((qrand()%int(scene->sceneRect().height()))-200)
);
}
void MainWindow::slotAddAnimationItem() //在场景中加入一个动画星星
{
StartItem *item=new StartItem;
QTimeLine *timeLine=new QTimeLine(4000);
timeLine->setCurveShape(QTimeLine::SineCurve);
timeLine->setLoopCount(0);
QGraphicsItemAnimation *anim=new QGraphicsItemAnimation;
anim->setItem(item);
anim->setTimeLine(timeLine);
int y=(qrand()%400)-200;
for(int i=0;i<400;i++)
{
anim->setPosAt(i/400.0,QPointF(i-200,y));
// void setPosAt(qreal step, const QPointF &pos);
}
timeLine->start();
scene->addItem(item);
}
效果: