c++ 如何在Qt中创建旋转动画?

ekqde3dh  于 2023-03-14  发布在  其他
关注(0)|答案(1)|浏览(359)

看起来QPropertyAnimation没有“旋转”动画
我尝试使用QVariantAnimation,但动画看起来很奇怪:https://i.imgur.com/KK1zBwv.gif

-编辑-

我已经用注解建议更新了代码
可编译示例:

// mainwindow.h
#include <QtWidgets/QMainWindow>
#include "ui_MainWindow.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindowClass; };
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
private:
    Ui::MainWindowClass *ui;
};
// mainwindow.cpp
#include "MainWindow.h"
#include "pusharrow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindowClass())
{
    ui->setupUi(this);

    ui->centralWidget->setStyleSheet("background-color: black;");
    PushArrow* label = new PushArrow(this);
    label->setStyleSheet("background-color: green;");
    label->setGeometry(100, 100, 32, 32);
    label->show();

    PushArrow_2* label_2 = new PushArrow_2(this);
    label_2->setStyleSheet("background-color: green;");
    label_2->setGeometry(200, 100, 32, 32);
    label_2->show();
}
// pusharrow.h

// arrow.png: https://i.imgur.com/PymLF1N.png

class PushArrow : public QLabel
{
    Q_OBJECT
public:
    QVariantAnimation* animation;
    QPixmap pixmap;
    QPixmap transformedPixmap;
    bool down = false;

    PushArrow(QWidget* parent = 0) : QLabel(parent) 
    { 
        pixmap = QPixmap("C:/Users/arrow.png");
        setPixmap(pixmap);

        animation = new QVariantAnimation(this);
        animation->setDuration(500); // Using a higher value to see how the animation is being performed.

        connect(animation, &QVariantAnimation::valueChanged, [=](const QVariant &value)
        {
            qDebug() << value;
            QTransform t;
            t.rotate(value.toReal());
            transformedPixmap = pixmap.transformed(t, Qt::SmoothTransformation);
            setPixmap(transformedPixmap);
        });
    }


    void mouseReleaseEvent(QMouseEvent* event)
    {
        down = !down;
        if (down)
        {
            animation->setStartValue(0.0f);
            animation->setEndValue(-180.0f);
        }
        else
        {
            animation->setStartValue(-180.0f);
            animation->setEndValue(0.0f);
        }

        animation->start();
        QLabel::mouseReleaseEvent(event);
    }
};


class PushArrow_2 : public QLabel
{
    Q_OBJECT
public:
    QPixmap pixmap;
    QPixmap transformedPixmap;

    bool down = false;
    QTimer* m_timer;
    qreal value = 0.0f;
    qreal startValue;
    qreal endValue;

    PushArrow_2(QWidget* parent = 0) : QLabel(parent) 
    { 
        pixmap = QPixmap("C:/Users/arrow.png");
        transformedPixmap = pixmap;

        m_timer = new QTimer(this);
        m_timer->setInterval(2);

        connect(m_timer, &QTimer::timeout, this, [this]
        {
            if (endValue < 0)
            {
                value -= 1.0f;

                if (abs(value) >= abs(endValue))
                {
                    m_timer->stop();
                    value = endValue;
                }
            }
            else
            {
                value += 1.0f;

                if (value >= abs(endValue))
                {
                    m_timer->stop();
                    value = endValue;
                }
            }

            //qDebug() << value;
            QTransform t;
            t.rotate(value);
            transformedPixmap = pixmap.transformed(t, Qt::SmoothTransformation);
            repaint();
        });

    }


    void mouseReleaseEvent(QMouseEvent* event)
    {
        down = !down;
        if (down)
        {
            startValue = 0.0f;
            endValue = -180.0f;
        }
        else
        {
            startValue = -180.0f;
            endValue = 0.0f;
        }

        m_timer->start();
        QLabel::mouseReleaseEvent(event);
    }


    void paintEvent(QPaintEvent* event) override
    {
        //qDebug() << "rect: " << rect();
        //qDebug() << "transformedPixmap: " << transformedPixmap.rect();

        //QLabel::paintEvent(event);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.drawPixmap(rect(), transformedPixmap, transformedPixmap.rect());
    }
};

使用paintEvent时,动画“几乎”正确,我不明白为什么像素图会变形:https://i.imgur.com/ijQvo61.gif

zpgglvta

zpgglvta1#

对于“更平滑”,transformed()的第二个参数默认为Qt::FastTransformation

transformedPixmap = pixmap.transformed(t, Qt::SmoothTransformation);

关于“不那么奇怪”很难说。你能把QPainterdrawPixmap()这些转换后的像素Map以一种看起来不“奇怪”的方式放在任何地方吗?如果是这样的话,那就是QLabelpaintEvent()如何做的问题了,你需要使用其他的东西或者覆盖这个行为。

**编辑:**如果变形改变了像素图的宽度和高度,那么不要拉伸它,画到中心。例如:

int x = rect().x() + (rect().width() - transformedPixmap.rect().width())/2;
int y = rect().y() + (rect().height() - transformedPixmap.rect().height())/2;
painter.drawPixmap(x, y, transformedPixmap);

相关问题