代码之家  ›  专栏  ›  技术社区  ›  Gerard097

运行qproperties和imation后qwiget的怪异行为

  •  0
  • Gerard097  · 技术社区  · 7 年前

    我正在两个小部件上运行下一个动画:

    QParallelAnimationGroup* animGroup = new QParallelAnimationGroup;
    
    for (int i = 0; i < 2; ++i) {
        //widgets is an array of 2 QLabels
        QPropertyAnimation* anim = new QPropertyAnimation(widgets[i], "geometry");
        anim->setDuration(750);
        anim->setStartValue(widgets[i]->geometry());
        widgets[i]->setProperty("animating", true);
        qDebug() << QString("Animation Start %1: ").arg(widgets[i]->objectName()) << widgets[i]->pos() << " g " << widgets[i]->geometry();
        //
        anim->setEndValue(widgets[!i]->geometry());
        anim->setEasingCurve(QEasingCurve::OutBack);
        animGroup->addAnimation(anim);
    }
    
    animGroup->start(QAbstractAnimation::DeleteWhenStopped);
    

    到目前为止,动画可以按预期移动两个窗口小部件,但是一旦我调整窗口的大小,这些窗口小部件就会自动移回原来的位置。包含这两个小部件的当前布局是QHBox布局,并具有以下项(顺序相同):

    qLabel0 | qspaceritem0 qtooltip按钮qspaceritem1| Qabel1

    动画之后,它们变成:

    Qabel1 | qspaceritem0 qtooltip按钮qspaceritem1| qLabel0

    但是每当我更改窗口的大小时,小部件上的位置都会重置为原始布局。我还没有从窗口实现ResizeEvent。

    我使用Visual StudioQueVisualStudioTooal2.3.1和Qt 12的Windows 10,用MSVC201764版本和C++ 17启用。

    完成测试代码(新项目):

    swapietemstest.cpp不锈钢

    #include "SwapItemsTest.h"
    
    #include <array>
    
    #include <QHBoxLayout>
    #include <QToolButton>
    #include <QSpacerItem>
    #include <QLabel>
    #include <QDebug>
    #include <QParallelAnimationGroup>
    #include <QPropertyAnimation>
    #include <QTimer>
    
    SwapItemsTest::SwapItemsTest(QWidget *parent)
        : QMainWindow(parent)
    {
        ui.setupUi(this);
    
        auto layout = new QHBoxLayout;
    
        auto toolButton = new QToolButton;
    
        auto left = new QLabel("Left");
        left->setFixedSize(50, size().height());
        left->setFrameShape(QFrame::Box);
        left->setFrameShadow(QFrame::Plain);
        left->setLineWidth(2);
    
        left->setAlignment(Qt::AlignCenter);
    
        auto right = new QLabel("Right");
    
        right->setFixedSize(50, size().height());
        right->setAlignment(Qt::AlignCenter);
        right->setFrameShape(QFrame::Box);
        right->setFrameShadow(QFrame::Plain);
        right->setLineWidth(2);
    
        layout->addWidget(left);
    
        layout->addSpacerItem(new QSpacerItem(40, 40));
    
        layout->addWidget(toolButton);
    
        layout->addSpacerItem(new QSpacerItem(40, 40));
    
        layout->addWidget(right);
    
        ui.centralWidget->setLayout(layout);
    
        auto widgets = std::array{left, right};
    
        connect(toolButton, &QToolButton::clicked, [widgets]() {
            QParallelAnimationGroup* animGroup = new QParallelAnimationGroup;
    
            for (int i = 0; i < 2; ++i) {
                //widgets is an array of 2 QLabels
                QPropertyAnimation* anim = new QPropertyAnimation(widgets[i], "geometry");
                anim->setDuration(750);
                anim->setStartValue(widgets[i]->geometry());
                widgets[i]->setProperty("animating", true);
                anim->setEndValue(widgets[!i]->geometry());
                anim->setEasingCurve(QEasingCurve::OutBack);
                animGroup->addAnimation(anim);
            }
    
            animGroup->start(QAbstractAnimation::DeleteWhenStopped); 
        });
    
    
    }
    

    最快的

    #pragma once
    
    #include <QtWidgets/QMainWindow>
    #include "ui_SwapItemsTest.h"
    
    class SwapItemsTest : public QMainWindow
    {
        Q_OBJECT
    
    public:
        SwapItemsTest(QWidget *parent = Q_NULLPTR);
    
    private:
        Ui::SwapItemsTestClass ui;
    };
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   G.M.    7 年前

    问题是,您将小部件放置在一个布局中,然后尝试自己管理它们的几何图形。一个解决方法是在动画组完成后,通过交换两个小部件来更新布局。然后你的代码变成…

    SwapItemsTest::SwapItemsTest(QWidget *parent)
        : QMainWindow(parent)
    {
        ui.setupUi(this);
    
        auto layout = new QHBoxLayout;
    
        auto toolButton = new QToolButton;
    
        auto left = new QLabel("Left");
        left->setFixedSize(50, size().height());
        left->setFrameShape(QFrame::Box);
        left->setFrameShadow(QFrame::Plain);
        left->setLineWidth(2);
    
        left->setAlignment(Qt::AlignCenter);
    
        auto right = new QLabel("Right");
    
        right->setFixedSize(50, size().height());
        right->setAlignment(Qt::AlignCenter);
        right->setFrameShape(QFrame::Box);
        right->setFrameShadow(QFrame::Plain);
        right->setLineWidth(2);
    
        layout->addWidget(left);
    
        layout->addSpacerItem(new QSpacerItem(40, 40));
    
        layout->addWidget(toolButton);
    
        layout->addSpacerItem(new QSpacerItem(40, 40));
    
        layout->addWidget(right);
    
        ui.centralWidget->setLayout(layout);
    
        auto widgets = std::array{left, right};
    
        connect(toolButton, &QToolButton::clicked,
    
                /*
                 * Note that layout has been added to the capture list for this lambda.
                 */
                [layout, widgets]()
                {
                    QParallelAnimationGroup* animGroup = new QParallelAnimationGroup;
    
                    for (int i = 0; i < 2; ++i) {
                        //widgets is an array of 2 QLabels
                        QPropertyAnimation* anim = new QPropertyAnimation(widgets[i], "geometry");
                        anim->setDuration(750);
                        anim->setStartValue(widgets[i]->geometry());
                        widgets[i]->setProperty("animating", true);
                        anim->setEndValue(widgets[!i]->geometry());
                        anim->setEasingCurve(QEasingCurve::OutBack);
                        animGroup->addAnimation(anim);
                    }
    
                    /*
                     * This is the lambda that will be invoked when the
                     * QPropertyAnimation::finished signal is emitted.  It simply
                     * swaps the positions of the two widgets in the layout.
                     */
                    connect(animGroup, &QPropertyAnimation::finished,
                            [layout, widgets]()
                            {
                                auto index0 = layout->indexOf(widgets[0]);
                                auto index1 = layout->indexOf(widgets[1]);
                                if (index0 < index1) {
                                    layout->takeAt(index1);
                                    layout->takeAt(index0);
                                    layout->insertWidget(index0, widgets[1]);
                                    layout->insertWidget(index1, widgets[0]);
                                } else {
                                    layout->takeAt(index0);
                                    layout->takeAt(index1);
                                    layout->insertWidget(index1, widgets[0]);
                                    layout->insertWidget(index0, widgets[1]);
                                }
                            });
    
                    animGroup->start(QAbstractAnimation::DeleteWhenStopped);
                });
    }
    

    注意,如果调整父窗口小部件的大小,您可能仍然会看到一些奇怪的行为。 在期间 动画。