C++ 如何轻松地分布一行Qt小部件,使它们始终均匀分布?

C++ 如何轻松地分布一行Qt小部件,使它们始终均匀分布?,c++,qt,layout,C++,Qt,Layout,我有一个Qt窗口,窗口底部有一行小部件(主要是按钮和复选框),供用户交互 我希望这一行小部件看起来很漂亮(我把“漂亮”定义为“等距”——也就是说,无论用户为其窗口选择什么宽度,这一行中的小部件之间以及最左边和最右边的小部件与窗口边缘之间的空间应始终相等) i、 e.行应如下所示(其中XXX表示小部件): 这看起来很容易做到,也就是说,我可以做这样的事情: QBoxLayout * hbl = new QBoxLayout(Qt::LeftToRight, parentWidget); hbl

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

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

i、 e.行应如下所示(其中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();
 [      XXX  XXX  XXX  XXX  ]
  ^^^^^^                  ^^
  too much space on the left!
只要所有小部件都是可见的,它就可以工作

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

在这种情况下,剩下的可见窗口小部件的间距不均匀,因为无法隐藏与现在隐藏的按钮关联的“拉伸”项

例如,如果我要在上面显示的行中隐藏第一个和第二个小部件,那么剩余的小部件最终将如下所示:

 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();
 [      XXX  XXX  XXX  XXX  ]
  ^^^^^^                  ^^
  too much space on the left!
有没有一种简单的方法可以获得我想要的行为,或者我需要深入到显式处理隐式QSpacerItems吗?

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

  • 使用以下方法移除并删除隐藏小部件左侧的拉伸:

      delete hbl->takeAt(ind - 1);
    
      hbl->insertStretch(ind);
    
  • 在显示的小部件左侧插入一个新的拉伸,如下所示:

      delete hbl->takeAt(ind - 1);
    
      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);
    }
};
#包括
#包括
#包括
类主窗口:公共QMainWindow
{
Q_对象
公众:
显式主窗口(QWidget*parent=nullptr):
QMainWindow(父窗口)
{
auto*widget=新的QWidget(此);
auto*hbl=新的QHBoxLayout(小部件);
auto*btnLeft=新的QPushButton((“按钮”),小部件;
auto*btnRight=新的QPushButton(“隐藏/显示”,小部件);
hbl->addStretch();
hbl->addWidget(btnLeft);
hbl->addStretch();
hbl->addWidget(新的QPushButton(“未使用”,此));
hbl->addStretch();
hbl->addWidget(btnRight);
hbl->addStretch();
连接(btnRight,&QPushButton::单击,[hbl,btnLeft](){
int ind=0;
btnLeft->setVisible(!btnLeft->isVisible());
对于(int n=0;ncount();n++){
自动*w=hbl->itemAt(n)->widget();
如果(w&&w==btnLeft)
ind=n;
}
如果(btnLeft->isVisible())
hbl->插入拉伸(ind);
其他的
删除hbl->takeAt(ind-1);
});
setCentralWidget(小部件);
调整大小(800600);
}
};

不要使用
addSpasing()
。但是,只需使用函数
void setspace(int)
为布局项设置一次间距。哎呀,这些行应该是
addStretch()
。我现在就来修复它。只保留第一个和最后一个拉伸,并删除其余部分。@scopchanov将所有小部件推到行的水平中心,而不是沿行的整个宽度均匀分布。(…这不一定是坏事;这不是我想要达到的样子)我得到了它,我想得更远。@JeremyFriesner,这对你有用吗?我很高兴听到您的反馈。@JeremyFriesner,我很高兴听到您的反馈,非常欢迎您!