QT案例解析(2): Application Chooser Example

演示效果

在这里插入图片描述

步骤概述

  1. 继承 QGraphicsWidget 显示图片
  2. 继承 QGraphicsView 重写resizeEvent
  3. 实现功能
    点击图片会有动画效果

涉及知识点

图形视图框架 (QGraphicsScene(场景)),QGraphicsView(视图)),QGraphicsItem(图形项))
动画框架 (QAbstractAnimation(基类))
状态机框架 (QStateMachine(状态机) QState(状态))
信号与槽 (Signals & Slots)
2D绘图 (paint)

代码解析

一、继承 QGraphicsWidget

实现图片显示
实现点击功能

class Pixmap : public QGraphicsWidget
{
    Q_OBJECT

public:
    Pixmap(const QPixmap &pix, QGraphicsItem *parent = 0)
        : QGraphicsWidget(parent), orig(pix), p(pix)
    {
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) Q_DECL_OVERRIDE
    {
    	//画个图 QPointF() 相当于 QPointF(0,0)
        painter->drawPixmap(QPointF(), p);
    }
	
	//重写鼠标点击事件
    virtual void mousePressEvent(QGraphicsSceneMouseEvent * ) Q_DECL_OVERRIDE
    {
    	//发送点击信号
        emit clicked();
    }

	//重写设置几何布局 (设置大小和位置)
    virtual void setGeometry(const QRectF &rect) Q_DECL_OVERRIDE
    {
    	//传递给父类 如果不加上这行 在 QGraphicsView 中 默认位置
        QGraphicsWidget::setGeometry(rect);

		//如果设置的rect宽 大于 图片的宽
        if (rect.size().width() > orig.size().width())
            p = orig.scaled(rect.size().toSize());// toSize 返回int类型
        else
            p = orig;
    }

Q_SIGNALS:
    void clicked();

private:
    QPixmap orig; 	//源图片
    QPixmap p;		//改变大小后的图片
};

二、继承 QGraphicsView

实现视图显示
重写resizeEvent

class GraphicsView : public QGraphicsView
{
    Q_OBJECT
public:
    GraphicsView(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent)
    {
    }

    virtual void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE
    {
    	//视图自适应大小 拉动窗体时可以跟着变化
        fitInView(sceneRect(), Qt::KeepAspectRatio);
    }
};

三、主函数

/***************************************
 *功能: 给Pixmap创建状态
 *objects: Pixmap 队列 (因为Pixmap最顶层是继承QObject,所以用 QObjectList 是可以的)
 *selectRect: 状态的样子,触发状态时就会变成 selectRect 所描述的位置和大小
 *parent: 将新建的state添加到parent
 **************************************/
void createStates(const QObjectList &objects,
                  const QRect &selectedRect, QState *parent)
{
    for (int i = 0; i < objects.size(); ++i) {
        QState *state = new QState(parent);
        state->assignProperty(objects.at(i), "geometry", selectedRect);
        //通过点击来触发状态
        parent->addTransition(objects.at(i), SIGNAL(clicked()), state);
    }
}

/***************************************
 *功能: 给Pixmap创建动画 (即状态变换的过程)
 *objects: Pixmap 队列 (因为Pixmap最顶层是继承QObject,所以用 QObjectList 是可以的)
 *machine: 状态机
 **************************************/
void createAnimations(const QObjectList &objects, QStateMachine *machine)
{
    for (int i=0; i<objects.size(); ++i) {
    	//这里是肥猫添加的
        QPropertyAnimation *Animation = new QPropertyAnimation(objects.at(i), "geometry");
        Animation->setEasingCurve(QEasingCurve::OutInQuint);
        Animation->setDuration(1000);
        machine->addDefaultAnimation(Animation);
    }

}

int main(int argc, char **argv)
{
    Q_INIT_RESOURCE(appchooser);

    QApplication app(argc, argv);

    Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png"));
    Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png"));
    Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png"));
    Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png"));
	//取个对象名称
    p1->setObjectName("p1");
    p2->setObjectName("p2");
    p3->setObjectName("p3");
    p4->setObjectName("p4");
	//设置初始位置大小
    p1->setGeometry(QRectF(  0.0,   0.0, 64.0, 64.0));
    p2->setGeometry(QRectF(236.0,   0.0, 64.0, 64.0));
    p3->setGeometry(QRectF(236.0, 236.0, 64.0, 64.0));
    p4->setGeometry(QRectF(  0.0, 236.0, 64.0, 64.0));
	//将Pixmap添加到场景中
    QGraphicsScene scene(0, 0, 300, 300);
    scene.setBackgroundBrush(Qt::white);
    scene.addItem(p1);
    scene.addItem(p2);
    scene.addItem(p3);
    scene.addItem(p4);
	//设置视图
    GraphicsView window(&scene);
    window.setFrameStyle(0);
    //场景将显示视图的左上角
    window.setAlignment(Qt::AlignLeft | Qt::AlignTop);
    //关闭滚动功能
    window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	//状态机
    QStateMachine machine;
    //记录原有状态 意思是 A组状态变化后,当触发B组状态变化时,A组状态会回到原来的状态
    machine.setGlobalRestorePolicy(QState::RestoreProperties);
	//创建一个状态组
    QState *group = new QState(&machine);
    group->setObjectName("group");
	
    QRect selectedRect(86, 86, 128, 128);
	//给状态组添加状态
    QState *idleState = new QState(group);
    group->setInitialState(idleState);
	
    QObjectList objects;
    objects << p1 << p2 << p3 << p4;
    //设置状态
    createStates(objects, selectedRect, group);
    //设置状态变化间的动画
    createAnimations(objects, &machine);
	//初始化
    machine.setInitialState(group);
    machine.start();

    window.resize(300, 300);
    window.show();

    return app.exec();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值