如何根据同一布局中的另一个窗口小部件将添加的窗口小部件定位到布局?

时间:2016-04-20 14:27:04

标签: c++ qt qcombobox

在我的GUI中,我想基于特定操作触发的信号以编程方式向QComboBox添加verticalLayout。以下代码工作正常,并添加了小部件:

QComboBox* userOptions = new QComboBox();
ui->verticalLayout_13->addWidget(userOptions);

但是,这种方式小部件总是添加到布局的末尾。

我的问题是:如何将添加的QComboBox定位到verticalLayout与同一布局中的另一个小部件对齐? (例如:在“Go”按钮上方)

2 个答案:

答案 0 :(得分:3)

似乎没有办法在您想要的布局中明确插入项目。

你有几个选择来实现" hard"方式:

  • 使用QLayout::takeAt(int index)获取要插入的索引后的所有项目,插入项目,然后插回所拍摄的项目。
  • 创建一个占位符窗口小部件,您可以使用该窗口小部件在布局中保留索引,然后您不要在布局中插入项目,而是嵌套在占位符窗口小部件中的布局中。如果没有项目,占位符窗口小部件将不占用任何空间,并展开以适应放入其中的任何内容。
  • 实现您自己的QLayout子类,该子类支持在特定索引处插入。您必须实现几个功能。
编辑:在我的结尾有一个遗漏,正如Kuba Ober所说,大多数具体布局实现都支持在特定索引处插入,例如QBoxLayout派生的插入方法将索引作为参数传递。

答案 1 :(得分:1)

首先,迭代布局以查找相对于您插入的引用项的索引。然后使用具体布局的特定小部件插入/添加功能。

由于您可能使用QBoxLayout,因此您可以使用其insertWidget方法插入小部件。

// https://github.com/KubaO/stackoverflown/tree/master/questions/insert-widget-36746949
#include <QtWidgets>

namespace SO { enum InsertPosition { InsertBefore, InsertAfter }; }

bool insertWidget(QBoxLayout * layout, QWidget * reference, QWidget * widget,
                  SO::InsertPosition pos = SO::InsertBefore, int stretch = 0,
                  Qt::Alignment alignment = 0) {
   int index = -1;
   for (int i = 0; i < layout->count(); ++i)
      if (layout->itemAt(i)->widget() == reference) {
         index = i;
         break;
      }
   if (index < 0) return false;
   if (pos == SO::InsertAfter) index++;
   layout->insertWidget(index, widget, stretch, alignment);
   return true;
}

QFormLayoutQGridLayoutQStackedLayout可以轻松设计类似的功能。

测试工具:

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   QWidget w;
   QVBoxLayout l{&w};
   QLabel first{"First"};
   QLabel second{"Second"};
   l.addWidget(&first);
   l.addWidget(&second);
   insertWidget(&l, &first, new QLabel{"Before First"}, SO::InsertBefore);
   insertWidget(&l, &second, new QLabel{"After Second"}, SO::InsertAfter);
   w.show();
   return app.exec();
}