当使用QVboxLayout排列小部件时,我希望使用QPropertyAnimation使小部件的高度增加。 问题是,当我打开多个小部件时,它们会在动画期间开始移动/摇动。
我准备了最低工作示例,tar gz project 按"打开"第一个,第二个,然后第三个小部件的按钮,你可以看到他们正在摇晃,在"打开"动画。
有人知道该怎么做才能避免这种情况吗? 我可以在主布局上设置setSizeConstraint(QLayout :: SetFixedSize)并且它们不会动摇,但是然后调整大小并且其他不起作用。
最好的问候
马立克
答案 0 :(得分:0)
前段时间我写了一个布局,它动画了它包含的小部件位置。
您应该以这样的方式构建您的布局:每个应该被动画化的小部件都应该在这个布局中(每个小部件一个Memory Leaks
应该是动画的):
public void renameItems(Activity activity, ...) {
AlertDialog.Builder builderInner = new AlertDialog.Builder(activity, R.style.MyAlertDialogStyle);
LinearLayout layout = new LinearLayout(activity);
final TextView itemTitle = new TextView(activity);
final EditText itemTitleInput = new EditText(activity);
final TextView subItem = new TextView(activity);
final EditText subItemInput = new EditText(activity);
// Irrelevant code ...
}
它有一些你不需要的额外功能(AnimLayout
)。
答案 1 :(得分:0)
对不起它花了我这么久;) 我测试了它,效果很好。
然而,当我使用我之前的代码时,我已经让它工作而不会摇晃。我做的更改是将QWidget添加到QScrollArea中,然后在该小部件上设置QVBoxLayout。 无论如何,非常感谢你的帮助。 下面是一个main.cpp中的示例,并且有变量" animatedLayout"打开或关闭AnimLayout。
#include #include class AnimLayout : public QLayout { Q_OBJECT Q_PROPERTY(QRect widgetRect READ widgetRect WRITE setWidgetRect NOTIFY widgetRectChanged) public: explicit AnimLayout(QWidget *parent = 0); ~AnimLayout(); QSize sizeHint() const; void setGeometry(const QRect &); QSize minimumSize() const; int count() const; QRect widgetRect() const; void setWidgetRect(const QRect &value); void updateItemPosition(); private: void addItem(QLayoutItem *item); QLayoutItem *itemAt(int index) const; QLayoutItem *takeAt(int index); signals: void widgetRectChanged(const QRect &value); public slots: private: QLayoutItem *item; QPropertyAnimation *animation; }; struct FrameDataStruct { QFrame *mainFrame; QFrame *upFrame; QFrame *downFrame; QPushButton *button; QVBoxLayout *upFrameLayout; QLabel *text; QVBoxLayout *downFrameLayout; QVBoxLayout *frameLayout; QPropertyAnimation *animation; int frame_id; int basic_height; bool expanded; AnimLayout *animLayout; }; class Proptest : public QMainWindow { Q_OBJECT public: explicit Proptest(); ~Proptest(); private slots: void setDataStruct(); void startAnimation(int frame_id); void animFinished(int frame_id); private: QMap frameMap; QSignalMapper *animStartMapper; QSignalMapper *animFinishedMapper; bool initialized; QWidget *scrollWidget; QVBoxLayout *main_layout; QWidget *widget; QScrollArea *scrollArea; QVBoxLayout *central_layout; bool layoutAnimated; }; Proptest::Proptest() : widget(new QWidget) { setCentralWidget(widget); this->setGeometry(200,200,300,600); central_layout=new QVBoxLayout(widget); scrollArea=new QScrollArea(widget); central_layout->addWidget(scrollArea); animStartMapper=new QSignalMapper(this); connect(animStartMapper,SIGNAL(mapped(int)),this,SLOT(startAnimation(int))); animFinishedMapper=new QSignalMapper(this); connect(animFinishedMapper,SIGNAL(mapped(int)),this,SLOT(animFinished(int))); scrollWidget=new QWidget(widget); scrollArea->setWidget(scrollWidget); main_layout=new QVBoxLayout(scrollWidget); main_layout->setSizeConstraint(QLayout::SetMinAndMaxSize); scrollArea->setWidgetResizable(true); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); layoutAnimated=true; this->setDataStruct(); } void Proptest::setDataStruct() { for(int i=0;iexpanded=false; r->frame_id=i; r->mainFrame=new QFrame(scrollWidget); r->upFrame=new QFrame(r->mainFrame); r->upFrame->setMinimumHeight(40); r->button=new QPushButton(QString("open"),r->upFrame); r->upFrameLayout=new QVBoxLayout(r->upFrame); r->upFrameLayout->addWidget(r->button); r->downFrame=new QFrame(r->mainFrame); r->text=new QLabel(QString("some text SOME TEXT some text"),r->downFrame); r->downFrameLayout=new QVBoxLayout(r->downFrame); r->downFrameLayout->addWidget(r->text); r->frameLayout=new QVBoxLayout(r->mainFrame); r->frameLayout->addWidget(r->upFrame); r->frameLayout->addItem(new QSpacerItem(10,10)); r->frameLayout->addWidget(r->downFrame); r->frameLayout->setStretch(0,0); r->frameLayout->setStretch(1,1); r->frameLayout->setStretch(2,0); r->downFrame->setVisible(false); r->animation=new QPropertyAnimation(r->mainFrame,"minimumHeight"); r->animation->setDuration(500); connect(r->button,SIGNAL(clicked(bool)),animStartMapper,SLOT(map())); animStartMapper->setMapping(r->button,r->frame_id); connect(r->animation,SIGNAL(finished()),animFinishedMapper,SLOT(map())); animFinishedMapper->setMapping(r->animation,r->frame_id); if(layoutAnimated) { r->animLayout=new AnimLayout(); r->animLayout->addWidget(r->mainFrame); main_layout->addItem(r->animLayout); } else { main_layout->addWidget(r->mainFrame); } frameMap.insert(r->frame_id,r); } main_layout->addItem(new QSpacerItem(10,10,QSizePolicy::Minimum,QSizePolicy::Expanding)); main_layout->setStretch(main_layout->count()-1,1); } void Proptest::startAnimation(int frame_id) { FrameDataStruct *r=frameMap[frame_id]; if(r->expanded) { r->expanded=false; if(layoutAnimated) { r->downFrame->hide(); } else { r->downFrame->setVisible(false); r->animation->setStartValue(r->mainFrame->geometry().height()); r->animation->setEndValue(r->basic_height); } } else { r->expanded=true; if(layoutAnimated) { r->downFrame->show(); } else { r->basic_height=r->mainFrame->geometry().height(); r->animation->setStartValue(r->basic_height); r->animation->setEndValue(r->basic_height*2); r->upFrame->setMinimumHeight(r->upFrame->height()); } } if(!layoutAnimated) r->animation->start(); } void Proptest::animFinished(int frame_id) { FrameDataStruct *r=frameMap[frame_id]; if(r->expanded) r->downFrame->setVisible(true); } Proptest::~Proptest() { } AnimLayout::AnimLayout(QWidget *parent) : QLayout(parent) , item(0) { animation = new QPropertyAnimation(this); animation->setPropertyName("widgetRect"); animation->setDuration(400); animation->setTargetObject(this); } AnimLayout::~AnimLayout() { delete item; } void AnimLayout::addItem(QLayoutItem *newItem) { Q_ASSERT(!item); animation->stop(); item =newItem; emit widgetRectChanged(item->geometry()); invalidate(); } QSize AnimLayout::sizeHint() const { if (!item) return QSize(); QSize result(item->sizeHint()); int m = 2*margin(); result += QSize(m,m); return result; } void AnimLayout::updateItemPosition() { QRect dest = contentsRect(); animation->setEndValue(dest); if (widgetRect()!=dest) { animation->start(); } } void AnimLayout::setGeometry(const QRect &rect) { QLayout::setGeometry(rect); updateItemPosition(); } QLayoutItem *AnimLayout::itemAt(int i) const { return i==0?item:0; } QLayoutItem *AnimLayout::takeAt(int i) { Q_ASSERT(i==0); QLayoutItem *r = item; item = 0; return r; } QRect AnimLayout::widgetRect() const { if (item) return item->geometry(); return QRect(); } void AnimLayout::setWidgetRect(const QRect &value) { if (item && item->geometry()!=value) { item->setGeometry(value); emit widgetRectChanged(item->geometry()); } } QSize AnimLayout::minimumSize() const { QSize result(item->minimumSize()); int m = 2*margin(); result += QSize(m,m); return result; } int AnimLayout::count() const { return item?1:0; } int main(int argc, char *argv[]) { QApplication a(argc, argv); Proptest w; w.show(); return a.exec(); } #include "main.moc"
最好的问候
马立克
答案 2 :(得分:0)
我的回答再次,不知道为什么,但删除了previosu。
我使用了你的AnimLayout,效果很好。 下面是main.cpp中的示例,其中包含" layoutAnimated"变量来打开和关闭AnimLayout。
#include <QApplication>
#include <QtWidgets>
class AnimLayout : public QLayout
{
Q_OBJECT
Q_PROPERTY(QRect widgetRect
READ widgetRect
WRITE setWidgetRect
NOTIFY widgetRectChanged)
public:
explicit AnimLayout(QWidget *parent = 0);
~AnimLayout();
QSize sizeHint() const;
void setGeometry(const QRect &);
QSize minimumSize() const;
int count() const;
QRect widgetRect() const;
void setWidgetRect(const QRect &value);
void updateItemPosition();
private:
void addItem(QLayoutItem *item);
QLayoutItem *itemAt(int index) const;
QLayoutItem *takeAt(int index);
signals:
void widgetRectChanged(const QRect &value);
public slots:
private:
QLayoutItem *item;
QPropertyAnimation *animation;
};
struct FrameDataStruct {
QFrame *mainFrame;
QFrame *upFrame;
QFrame *downFrame;
QPushButton *button;
QVBoxLayout *upFrameLayout;
QLabel *text;
QVBoxLayout *downFrameLayout;
QVBoxLayout *frameLayout;
QPropertyAnimation *animation;
int frame_id;
int basic_height;
bool expanded;
AnimLayout *animLayout;
};
class Proptest : public QMainWindow
{
Q_OBJECT
public:
explicit Proptest();
~Proptest();
private slots:
void setDataStruct();
void startAnimation(int frame_id);
void animFinished(int frame_id);
private:
QMap<int,FrameDataStruct*> frameMap;
QSignalMapper *animStartMapper;
QSignalMapper *animFinishedMapper;
bool initialized;
QWidget *scrollWidget;
QVBoxLayout *main_layout;
QWidget *widget;
QScrollArea *scrollArea;
QVBoxLayout *central_layout;
bool layoutAnimated;
};
Proptest::Proptest()
: widget(new QWidget)
{
setCentralWidget(widget);
this->setGeometry(200,200,300,600);
central_layout=new QVBoxLayout(widget);
scrollArea=new QScrollArea(widget);
central_layout->addWidget(scrollArea);
animStartMapper=new QSignalMapper(this);
connect(animStartMapper,SIGNAL(mapped(int)),this,SLOT(startAnimation(int)));
animFinishedMapper=new QSignalMapper(this);
connect(animFinishedMapper,SIGNAL(mapped(int)),this,SLOT(animFinished(int)));
scrollWidget=new QWidget(widget);
scrollArea->setWidget(scrollWidget);
main_layout=new QVBoxLayout(scrollWidget);
main_layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
layoutAnimated=true;
this->setDataStruct();
}
void Proptest::setDataStruct() {
for(int i=0;i<5;i++) {
FrameDataStruct *r=new FrameDataStruct;
r->expanded=false;
r->frame_id=i;
r->mainFrame=new QFrame(scrollWidget);
r->upFrame=new QFrame(r->mainFrame);
r->upFrame->setMinimumHeight(40);
r->button=new QPushButton(QString("open"),r->upFrame);
r->upFrameLayout=new QVBoxLayout(r->upFrame);
r->upFrameLayout->addWidget(r->button);
r->downFrame=new QFrame(r->mainFrame);
r->text=new QLabel(QString("some text SOME TEXT some text"),r->downFrame);
r->downFrameLayout=new QVBoxLayout(r->downFrame);
r->downFrameLayout->addWidget(r->text);
r->frameLayout=new QVBoxLayout(r->mainFrame);
r->frameLayout->addWidget(r->upFrame);
r->frameLayout->addItem(new QSpacerItem(10,10));
r->frameLayout->addWidget(r->downFrame);
r->frameLayout->setStretch(0,0);
r->frameLayout->setStretch(1,1);
r->frameLayout->setStretch(2,0);
r->downFrame->setVisible(false);
r->animation=new QPropertyAnimation(r->mainFrame,"minimumHeight");
r->animation->setDuration(500);
connect(r->button,SIGNAL(clicked(bool)),animStartMapper,SLOT(map()));
animStartMapper->setMapping(r->button,r->frame_id);
connect(r->animation,SIGNAL(finished()),animFinishedMapper,SLOT(map()));
animFinishedMapper->setMapping(r->animation,r->frame_id);
if(layoutAnimated) {
r->animLayout=new AnimLayout();
r->animLayout->addWidget(r->mainFrame);
main_layout->addItem(r->animLayout);
}
else {
main_layout->addWidget(r->mainFrame);
}
frameMap.insert(r->frame_id,r);
}
main_layout->addItem(new QSpacerItem(10,10,QSizePolicy::Minimum,QSizePolicy::Expanding));
main_layout->setStretch(main_layout->count()-1,1);
}
void Proptest::startAnimation(int frame_id) {
FrameDataStruct *r=frameMap[frame_id];
if(r->expanded) {
r->expanded=false;
if(layoutAnimated) {
r->downFrame->hide();
}
else {
r->downFrame->setVisible(false);
r->animation->setStartValue(r->mainFrame->geometry().height());
r->animation->setEndValue(r->basic_height);
}
} else {
r->expanded=true;
if(layoutAnimated) {
r->downFrame->show();
}
else {
r->basic_height=r->mainFrame->geometry().height();
r->animation->setStartValue(r->basic_height);
r->animation->setEndValue(r->basic_height*2);
r->upFrame->setMinimumHeight(r->upFrame->height());
}
}
if(!layoutAnimated)
r->animation->start();
}
void Proptest::animFinished(int frame_id) {
FrameDataStruct *r=frameMap[frame_id];
if(r->expanded)
r->downFrame->setVisible(true);
}
Proptest::~Proptest() {
}
AnimLayout::AnimLayout(QWidget *parent) :
QLayout(parent) ,
item(0)
{
animation = new QPropertyAnimation(this);
animation->setPropertyName("widgetRect");
animation->setDuration(400);
animation->setTargetObject(this);
}
AnimLayout::~AnimLayout()
{
delete item;
}
void AnimLayout::addItem(QLayoutItem *newItem)
{
Q_ASSERT(!item);
animation->stop();
item =newItem;
emit widgetRectChanged(item->geometry());
invalidate();
}
QSize AnimLayout::sizeHint() const
{
if (!item)
return QSize();
QSize result(item->sizeHint());
int m = 2*margin();
result += QSize(m,m);
return result;
}
void AnimLayout::updateItemPosition()
{
QRect dest = contentsRect();
animation->setEndValue(dest);
if (widgetRect()!=dest) {
animation->start();
}
}
void AnimLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
updateItemPosition();
}
QLayoutItem *AnimLayout::itemAt(int i) const
{
return i==0?item:0;
}
QLayoutItem *AnimLayout::takeAt(int i)
{
Q_ASSERT(i==0);
QLayoutItem *r = item;
item = 0;
return r;
}
QRect AnimLayout::widgetRect() const
{
if (item)
return item->geometry();
return QRect();
}
void AnimLayout::setWidgetRect(const QRect &value)
{
if (item && item->geometry()!=value) {
item->setGeometry(value);
emit widgetRectChanged(item->geometry());
}
}
QSize AnimLayout::minimumSize() const
{
QSize result(item->minimumSize());
int m = 2*margin();
result += QSize(m,m);
return result;
}
int AnimLayout::count() const
{
return item?1:0;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Proptest w;
w.show();
return a.exec();
}
#include "main.moc"
最好的问候
马立克