如何在保留布局功能的同时将两个小部件叠加在一起?

时间:2013-07-19 22:10:37

标签: c++ qt user-interface

在开发Qt UI时,我经常希望在现有UI之上显示通知或其他显示工具。

但是,我只发现了两种方法,但都没有完全解决问题。

选项1

使通知小部件成为显示的小部件的兄弟,但不要将其添加到任何布局并将其提升到另一个布局之上。

问题:窗口小部件不能在布局中,因此您必须手动调整窗口大小以适合其内容,并且只要父窗口是必须的,您就必须将其移动到正确的位置调整大小。

选项2

将小部件添加到显示的小部件旁边的布局中。

问题:由于窗口小部件是布局的一部分,因此当窗口小部件可见时,它会移动其他显示的窗口小部件,而不是在它们之上。

示例 - 此处通知将“v0.3b”标签向上推,而不是显示在其上方。在上部,由于它是左侧有垫片的布局的一部分,因此其尺寸适合于其内容。 enter image description here

解决方案

是否有像QStackedWidget这样的东西一次显示多个页面,空白区域显示下面的小部件?这种UI功能还有其他选择吗?

3 个答案:

答案 0 :(得分:1)

你是对的,QStackedWidget / QStackedLayout是你的朋友。制作具有堆叠布局的自定义小部件,当消息进入时,您将活动小部件设置为带有警告消息的小部件,使用计时器,您可以回到正常状态。 此自定义小部件可以放在右下角的主窗口中。使用spacer,这可以很容易地完成,对吗?

答案 1 :(得分:0)

我可能采用的一种方法是将通知窗口小部件创建为自己的自定义窗口小部件,其大小与其所在的窗口小部件的大小相匹配。使自定义窗口小部件的背景透明。

NotificationWidget::paintEvent(QPaintEvent* event) {
  QPainter painter(this);
  QColor bg;
  bg.setAlpha(0);

  painter.fillRect(rect(), QBrush(bg));
  QWidget::paintEvent(event);
}

仅绘制该窗口小部件的通知部分。它可以像平常一样放入布局中。现在,每当您调整父级的大小时,自定义通知小部件也将调整大小,此小部件的可见部分将位于正确的位置。您还需要在构造函数中执行以下操作:

NotificationWidget::NotificationWidget(QWidget* parent = 0) : QWidget(parent) {
  setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
  setAutoFillBackground(false);

  // add whatever widgets/layouts you want
}

答案 2 :(得分:0)

您可以对选项1进行一些调整:

  • 创建弹出窗口小部件,为其提供相关的父窗口小部件,但不要将其添加到任何布局中。
  • 为弹出窗口小部件本身提供一个布局和任何子元素,以使其尽可能复杂。
  • 在弹出窗口小部件布局上调用setSizeConstraint(QLayout::SetFixedSize);
  • 在弹出窗口小部件上使用move()对其进行定位(相对于其父窗口小部件)
  • 在弹出窗口小部件上使用show()和hide()来控制其可见性。

与命名相反,SetFixedSize选项不需要您实际对固定大小进行硬编码。这只是意味着小部件将始终使用其(动态)sizeHint()作为其应有的大小。所有其他大小限制选项(扩展等)都依赖于sizeHint()和父布局的组合,在这种情况下您没有这种选择。

示例:

HoverWidget::HoverWidget(QWidget *parent)
    : QFrame(parent)
    , label1(new QLabel(this))
    , label2(new QLabel(this))
{
    auto vlayout = new QVBoxLayout(this);
    vlayout->addWidget(label1);
    vlayout->addWidget(label2);
    vlayout->setSizeConstraint(QLayout::SetFixedSize);
    hide();
}

HoverWidget::showNear(int left, int top)
{
    auto const hoverSize = sizeHint();   // don't use size() here.
    auto const parentSize = parentWidget()->size();
    // TODO: make this code a bit more complex to make sure the widget stays
    //       within the parent, by using hoverSize and parentSize to edit
    //       the left, top parameters.
    move(left, top);
    show();
}