Как легко распространять ряд виджетов Qt, чтобы они всегда были равномерно распределены? - PullRequest
0 голосов
/ 01 октября 2018

У меня есть окно 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();

Это работает, пока все виджеты видны.

Проблема в том, что иногда я хочу скрыть некоторые извиджеты в строке, так как они не имеют отношения к поставленной задаче.

В этом случае оставшиеся видимые виджеты заканчиваются неравномерно, потому что нет способа скрыть «растянутые» элементы, связанные с теперь скрытыми кнопками.

Например,если бы я скрыл первый и второй виджеты в строке, показанной выше, то оставшиеся виджеты в конечном итоге выглядят так:

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

Есть ли простой способ получить желаемое поведение или янужно погрузиться в явную обработку неявных QSpacerItems?

1 Ответ

0 голосов
/ 02 октября 2018

Решение

Поскольку QBoxLayout не поддерживает изменение видимости QLayoutItem, я бы посоветовал вам сделать следующее:

  • удалить и удалитьрастянуть влево от скрытого виджета, используя QLayout::takeAt, например:

    delete hbl->takeAt(ind - 1);
    
  • вставить новое растяжение слева от отображаемого виджетаиспользование QBoxLayout::insertStretch примерно так:

    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);
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...