c++ - 如何轻松地展开一排 Qt 小部件,使它们始终均匀分布?

标签 c++ qt layout

我有一个 Qt 窗口,窗口底部是一行小部件(主要是按钮和复选框)供用户交互。

我希望那行小部件看起来很漂亮(其中“漂亮”对我来说被定义为“均匀间隔”——也就是说,无论用户为其窗口选择什么宽度,这一行中的小部件应该始终具有它们之间以及最左边和最右边的小部件与窗口边缘之间的空间相等)。

即该行应如下所示(其中 XXX 表示小部件):

 [  XXX  XXX  XXX  XXX  XXX  XXX  ]

这看起来很容易做到——也就是说,我可以做这样的事情:

 QBoxLayout * hbl = new QBoxLayout(Qt::LeftToRight, parentWidget);
 hbl->addStretch();
 hbl->addWidget(new QPushButton);
 hbl->addStretch();
 hbl->addWidget(new QPushButton);
 hbl->addStretch();
 hbl->addWidget(new QPushButton);
 [...]
 hbl->addStretch();

只要所有小部件都可见,就可以工作。

问题是有时我想隐藏行中的一些小部件,因为它们与手头的任务无关。

在这种情况下,剩余可见的小部件最终会分布不均匀,因为无法隐藏与现在隐藏的按钮关联的“拉伸(stretch)”项目。

例如,如果我要隐藏上面显示的行中的第一个和第二个小部件,那么其余的小部件最终看起来像这样:

 [      XXX  XXX  XXX  XXX  ]
  ^^^^^^                  ^^
  too much space on the left!

是否有一种简单的方法来获得我想要的行为,或者我是否需要深入研究显式处理隐式 QSpacerItems?

最佳答案

解决方案

由于QBoxLayout不支持更改QLayoutItem的可见性,我建议您执行以下操作:

  • 使用QLayout::takeAt删除并删除隐藏的小部件左侧的拉伸(stretch)部分。像这样:

      delete hbl->takeAt(ind - 1);
    
  • 使用QBoxLayout::insertStretch在显示的小部件的左侧插入一个新的拉伸(stretch)。像这样:

      hbl->insertStretch(ind);
    

ind 是隐藏/显示的小部件的布局索引。

示例

这是我为您准备的一个最小示例,用于演示建议的解决方案:

#include <QMainWindow>
#include <QBoxLayout>
#include <QPushButton>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr) :
        QMainWindow(parent)
    {
        auto *widget = new QWidget(this);
        auto *hbl = new QHBoxLayout(widget);

        auto *btnLeft = new QPushButton(("Button"), widget);
        auto *btnRight = new QPushButton("Hide/Show", widget);

        hbl->addStretch();
        hbl->addWidget(btnLeft);
        hbl->addStretch();
        hbl->addWidget(new QPushButton("Unused", this));
        hbl->addStretch();
        hbl->addWidget(btnRight);
        hbl->addStretch();

        connect(btnRight, &QPushButton::clicked, [hbl, btnLeft](){
            int ind = 0;

            btnLeft->setVisible(!btnLeft->isVisible());

            for (int n = 0; n < hbl->count(); n++) {
                auto *w = hbl->itemAt(n)->widget();

                if (w && w == btnLeft)
                    ind = n;
            }

            if (btnLeft->isVisible())
                hbl->insertStretch(ind);
            else
                delete hbl->takeAt(ind - 1);
        });

        setCentralWidget(widget);
        resize(800, 600);
    }
};

关于c++ - 如何轻松地展开一排 Qt 小部件,使它们始终均匀分布?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52597506/

相关文章:

c++ - 如何从 QString 获取 const char *

html - Rails 使用 content_for 并渲染相同的布局两次

c++ - boost::python 导出自定义异常

c++ - 将二维空间中的项目映射到内存中

c++ - 一组线程的C++互斥锁

css - 将 DIV 跨越多行

image - VK_IMAGE_LAYOUT_UNDEFINED 与 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 作为帧缓冲区附件的初始布局

c++ - 我可以在 C++ 中嵌套 try-catch block 吗?

单击按钮时 QTableView 不会更新已编辑的单元格

c++ - 拔下 USB 串行电缆时发送信号