c++ 自定义可折叠小部件导致大小问题

irlmq6kh  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(102)

我在How to make an expandable/collapsable section widget in Qt上看到了这个帖子的答案,但提出的解决方案并非没有缺陷。
事实上,正如你在下面看到的,一旦小部件被展开和关闭,它不会重置窗口大小,这会产生创建空白空间的效果:

下面是一个可复制的最小示例(您需要从帖子答案中导入剧透部件):

  1. QApplication a(argc, argv);
  2. QWidget* widget = new QWidget();
  3. widget->setFixedWidth(500);
  4. QVBoxLayout* mainLayout = new QVBoxLayout(widget);
  5. QFrame* widgetTop = new QFrame();
  6. widgetTop->setFrameShape(QFrame::StyledPanel);
  7. widgetTop->setFixedHeight(50);
  8. QHBoxLayout* layoutTop = new QHBoxLayout(widgetTop);
  9. QLabel* labelTop = new QLabel("widget-top");
  10. labelTop->setAlignment(Qt::AlignCenter);
  11. layoutTop->addWidget(labelTop);
  12. mainLayout->addWidget(widgetTop);
  13. QFrame* widgetMiddle = new QFrame();
  14. widgetMiddle->setFrameShape(QFrame::StyledPanel);
  15. widgetMiddle->setFixedHeight(150);
  16. QHBoxLayout* layoutMiddle = new QHBoxLayout(widgetMiddle);
  17. QLabel* labelMiddle = new QLabel("widget-middle");
  18. labelMiddle->setAlignment(Qt::AlignCenter);
  19. layoutMiddle->addWidget(labelMiddle);
  20. mainLayout->addWidget(widgetMiddle);
  21. QFrame* widgetBottom = new QFrame();
  22. widgetBottom->setFrameShape(QFrame::StyledPanel);
  23. widgetBottom->setFixedHeight(100);
  24. QHBoxLayout* layoutBottom = new QHBoxLayout(widgetBottom);
  25. QLabel* labelBottom = new QLabel("widget-bottom");
  26. labelBottom->setAlignment(Qt::AlignCenter);
  27. layoutBottom->addWidget(labelBottom);
  28. auto* anyLayout = new QVBoxLayout();
  29. anyLayout->addWidget(widgetBottom);
  30. Spoiler* spoiler = new Spoiler("I'm buggy", 100);
  31. spoiler->setContentLayout(*anyLayout);
  32. mainLayout->addWidget(spoiler);
  33. // Affichage du widget principal
  34. widget->show();
  35. return a.exec();

我尝试使用adjustSize(),但它不适用于QPropertyAnimation
如何让Windows恢复到原来的高度?

sxissh06

sxissh061#

下面是我对Spoiler所做的一些修改来处理这个问题,你必须让你的窗口成为spoiler的父部件:

添加更多成员:

  1. bool collapsing=false;
  2. int contentHeight;

在ctor中所做的更改:

  1. QObject::connect(&toggleButton, &QToolButton::clicked, [this](const bool checked)
  2. {
  3. toggleButton.setArrowType(checked ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow);
  4. toggleAnimation.setDirection(checked ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
  5. //a check for the resize event
  6. if(toggleAnimation.direction()==QAbstractAnimation::Backward)
  7. {
  8. collapsing=true;
  9. }
  10. else
  11. {
  12. collapsing=false;
  13. }
  14. toggleAnimation.start();
  15. });
  16. //get spoiler min and max sizes to normal when animation finishes
  17. QObject::connect(&toggleAnimation, &QParallelAnimationGroup::finished, [this]()
  18. {
  19. parentWidget()->setMaximumHeight(16777215);
  20. parentWidget()->setMinimumHeight(parentWidget()->minimumSizeHint().height());
  21. });

调整事件大小:

  1. void Spoiler::resizeEvent(QResizeEvent *event)
  2. {
  3. //resize parentWidget while spoiler size is animated
  4. //second condition is the explanation behind the problematic behavior
  5. if(toggleAnimation.state()==QAbstractAnimation::Running &&
  6. parentWidget()->minimumHeight()+contentHeight>parentWidget()->height())
  7. {
  8. if(collapsing)
  9. {
  10. int newHeight = parentWidget()->height()-(event->oldSize().height()-event->size().height());
  11. parentWidget()->setFixedHeight(newHeight);
  12. return;
  13. }
  14. int newHeight = parentWidget()->height()-(event->oldSize().height()-event->size().height());
  15. parentWidget()->setFixedHeight(newHeight);
  16. }
  17. }

以下是它第一眼的样子:

但是如果你通过快速点击它来强调它,它就会表现得不正常:

resize事件被调用的次数太快是背后的原因,但我不知 prop 体是怎么回事。
我确实尝试过对父部件大小进行动画处理,但它比这个解决方案更难看,可能是因为我无法确定开始值和结束值。
我提供这个更多的是为了帮助识别问题并提出处理问题的方法,我认为不应该使用这个解决方案,除非你能让它为你的用例工作。

展开查看全部

相关问题