QWidget - 调整动画大小

Posted

技术标签:

【中文标题】QWidget - 调整动画大小【英文标题】:QWidget - resize animation 【发布时间】:2010-07-19 17:49:47 【问题描述】:

假设我有一个QHBoxLayout,其中有 2 个QTextEdits,它们之间有一个带有向右箭头的按钮。当您单击按钮时,右侧的QTextEdit 会通过移动左边框逐渐关闭,直到与右侧边框相遇。同时,左侧QTextEdit 的右边框取代了右侧QTextEdit 释放的位置。并且在按下按钮后,系统的状态又回到了之前的状态。

编辑:为了组织这个,我做了以下事情:

1) 在头文件中:

class MyWidget : public QWidget


    Q_OBJECT

    QTextEdit       *m_textEditor1;
    QTextEdit       *m_textEditor2;
    QPushButton     *m_pushButton;
    QHBoxLayout     *m_layout;
    int              m_deltaX;

public:

    MyWidget(QWidget * parent = 0);


    ~MyWidget()


private slots:
    void closeOrOpenTextEdit2(bool isClosing);


;

2) 在源文件中:

MyWidget::MyWidget(QWidget * parent):QWidget(parent),m_deltaX(0)



  m_pushButton = new QPushButton(this);
  m_pushButton->setText(">");
  m_pushButton->setCheckable(true);
  connect(m_pushButton, SIGNAL(clicked(bool)), this, SLOT(closeOrOpenTextEdit2(bool)));

  m_textEditor1 = new QTextEdit(this);
  m_textEditor1->setText("AAAAA AAAAAAAAAAA AAAAAAAAAAA  AAAAAAA AAAAAAAAAAA AAAAAAAAAAA  AA");

  m_textEditor2 = new QTextEdit(this);


  m_layout = new QHBoxLayout;
  m_layout->addWidget(m_textEditor1);
  m_layout->addWidget(m_pushButton);
  m_layout->addWidget(m_textEditor2);

  setLayout(m_layout);


void MyWidget::closeOrOpenTextEdit2(bool isClosing)

    QPropertyAnimation *animation1 = new QPropertyAnimation(m_textEditor2, "geometry");
    QPropertyAnimation *animation2 = new QPropertyAnimation(m_pushButton, "geometry");
    QPropertyAnimation *animation3 = new QPropertyAnimation(m_textEditor1, "geometry");

    if(isClosing) //close the second textEdit
    
        m_pushButton->setText("<");

        QRect te2_1 = m_textEditor2->geometry();
        m_deltaX = te2_1.width()-3;
        QRect te2_2(te2_1.x()+m_deltaX, te2_1.y(), 3 ,te2_1.height());

        QRect pb_1 = m_pushButton->geometry();
        QRect pb_2(pb_1.x()+m_deltaX, pb_1.y(), pb_1.width() ,pb_1.height());

        QRect te1_1 = m_textEditor1->geometry();
        QRect te1_2(te1_1.x(), te1_1.y(), te1_1.width()+m_deltaX, te1_1.height());


         //animation->setDuration(10000);
         animation1->setStartValue(te2_1);
         animation1->setEndValue(te2_2);

         animation2->setStartValue(pb_1);
         animation2->setEndValue(pb_2);

         animation3->setStartValue(te1_1);
         animation3->setEndValue(te1_2);
    
    else //open
    
       m_pushButton->setText(">");

       QRect te2_1 = m_textEditor2->geometry();
       QRect te2_2(te2_1.x()-m_deltaX, te2_1.y(), 3+m_deltaX ,te2_1.height());

       QRect pb_1 = m_pushButton->geometry();
       QRect pb_2(pb_1.x()-m_deltaX, pb_1.y(), pb_1.width() ,pb_1.height());

       QRect te1_1 = m_textEditor1->geometry();
       QRect te1_2(te1_1.x(), te1_1.y(), te1_1.width()-m_deltaX, te1_1.height());


        //animation->setDuration(10000);
        animation1->setStartValue(te2_1);
        animation1->setEndValue(te2_2);

        animation2->setStartValue(pb_1);
        animation2->setEndValue(pb_2);

        animation3->setStartValue(te1_1);
        animation3->setEndValue(te1_2);

    
    animation1->start();
    animation2->start();
    animation3->start();

编辑:

我有以下问题:

当我关闭第二个QTextEdit(通过单击按钮)并调整MyWidget 的大小时,QTextEdit 会恢复其状态(但它当然应该保持关闭状态)。我该如何解决这个问题?

请给我一个代码 sn-p。

【问题讨论】:

【参考方案1】:

Qt's Animation framework 听起来是个不错的起点。您可以尝试按照他们的教程进行调整,以适应您的用例。我已经用过它,而且看起来很简单。

【讨论】:

我已阅读并熟悉这些示例。不幸的是,我的经验不允许我实施这种情况。 @Narek 为什么?你能详细说明吗?出了什么问题? 好的,我已经改变了我的问题。请参见上文。【参考方案2】:

1) 您可以将按钮替换为垂直布局,将按钮放置在此布局内,最后在按钮下方添加一个垂直间隔(与布局相同)。

...

QVBoxLayout* m_buttonLayout = new QVBoxLayout();

m_layout = new QHBoxLayout();
m_layout->addWidget(m_textEditor1);
m_layout->addLayout(m_buttonLayout);
m_layout->addWidget(m_textEditor2);

m_buttonLayout->addWidget(m_pushButton);
m_buttonLayout->addItem( new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding) );

2) 我想您可以(并且应该)为小部件的 maximumSize(或只是 maximumWidth)属性设置动画,并让布局负责计算实际的几何图形。这也将简化您的计算。例如

QPropertyAnimation *animation1 = new QPropertyAnimation(m_textEditor2, "maximumWidth");
QPropertyAnimation *animation2 = new QPropertyAnimation(m_textEditor, "maximumWidth");

if (isClosing)

    int textEdit2_start = m_textEditor2->maximumWidth();
    int textEdit2_end = 0;

    int textEdit_start = m_textEditor->maximumWidth();
    int textEdit_end = textEdit_start + textEdit2_start;

    animation1->setStartValue(textEdit2_start);
    ...

此外,现在您根本不必为按钮几何图形设置动画(假设您已为其设置了固定大小)。

PS。我没有编译代码,所以可能会有一些小错误,但你应该明白。

【讨论】:

如何去掉按钮和右边QTextEdit之间的距离(原来存在于QHBoxLayout中)? 您解决第二个问题的逻辑很好,但这是一个小问题:它稍等片刻,然后立即关闭第二个 QTextEdit。当我添加 animation1->setDuration(3000); 时,它等待了更多,然后,同样的行为,immediatley 关闭了。我们如何逐步做到这一点? 您可以使用 QBoxLayout::setStretchFactor 消除布局中元素之间的间隙(即,将每个小部件的拉伸因子设置为零)。对于另一个问题,您也可以尝试为 minimumWidth 设置动画。 minimumWidth 有效,但 maxmimuWidth 没有。因此我在bugreports.qt.nokia.com 上打开了一个错误。 你可以在这里看到这个错误:bugreports.qt.nokia.com/browse/QTCREATORBUG-1916【参考方案3】:

这是我想要的:

头文件

class MyWidget : public QWidget


    Q_OBJECT

    QTextEdit       *m_textEditor1;
    QTextEdit       *m_textEditor2;
    QPushButton     *m_pushButton;
    QHBoxLayout     *m_layout;
    QVBoxLayout     *m_buttonLayout;

    int              m_deltaX;
    bool             m_isClosed;


public:

    MyWidget(QWidget * parent = 0);
    ~MyWidget()

    void resizeEvent( QResizeEvent * event );

private slots:
    void closeOrOpenTextEdit2(bool isClosing);

;

源文件

MyWidget::MyWidget(QWidget * parent):QWidget(parent),m_deltaX(0)


  m_pushButton = new QPushButton(this);
  m_pushButton->setText(">");
  m_pushButton->setCheckable(true);
  m_pushButton->setFixedSize(16,16);
  connect(m_pushButton, SIGNAL(clicked(bool)), this, SLOT(closeOrOpenTextEdit2(bool)));

  m_textEditor1 = new QTextEdit(this);
  m_textEditor1->setText("AAAAA AAAAAAAAAAA AAAAAAAAAAA  AAAAAAA AAAAAAAAAAA AAAAAAAAAAA  AA");

  m_textEditor2 = new QTextEdit(this);

  m_buttonLayout = new QVBoxLayout();
  m_buttonLayout->addWidget(m_pushButton);
  m_buttonLayout->addItem( new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding) );


  m_layout = new QHBoxLayout;
  m_layout->addWidget(m_textEditor1, 10);
  m_layout->addSpacing(15);
  m_layout->addLayout(m_buttonLayout);
  m_layout->setSpacing(0);
  m_layout->addWidget(m_textEditor2, 4);

  setLayout(m_layout);
  resize(800,500);


void MyWidget::closeOrOpenTextEdit2(bool isClosing)

    m_isClosed = isClosing;
    QPropertyAnimation *animation1 = new QPropertyAnimation(m_textEditor2, "maximumWidth");

    if(isClosing) //close the second textEdit
    
        m_textEditor2->setMaximumWidth(m_textEditor2->width());

        int textEdit2_start = m_textEditor2->maximumWidth();

        m_deltaX = textEdit2_start;
        int textEdit2_end = 3;



        animation1->setDuration(500);
        animation1->setStartValue(textEdit2_start);
        animation1->setEndValue(textEdit2_end);


        m_pushButton->setText("<");

    
    else //open
    


        int textEdit2_start = m_textEditor2->maximumWidth();
        int textEdit2_end = m_deltaX;


        animation1->setDuration(500);
        animation1->setStartValue(textEdit2_start);
        animation1->setEndValue(textEdit2_end);


        m_pushButton->setText(">");

    

    animation1->start();




void MyWidget::resizeEvent( QResizeEvent * event )

    if(!m_isClosed)
        m_textEditor2->setMaximumWidth( QWIDGETSIZE_MAX );

【讨论】:

也许对您的解决方案的描述,而不是高度特定于您的情况代码,对 SO 上的其他人更有帮助

以上是关于QWidget - 调整动画大小的主要内容,如果未能解决你的问题,请参考以下文章

QWidget 调整大小问题

在调整大小期间保持子类 QWidget 的纵横比

当小部件集更改时,调整 QWidget 的大小以仅保存当前小部件

调整大小的 opencv 图像在 QWidget C++ 上未正确显示

Qt QStackedWidget 调整大小问题

QTableWidget 与其父 QWidget 的边框对齐