Qt удаляет пустое пространство между виджетами в QVBoxLayout

У меня раздражающая проблема. Я создал QVBoxLayout, в который я добавил свои виджеты. Это пример из моего конструктора:

layout = new QVBoxLayout;
layout->setMargin(0);
layout->setContentsMargins(QMargins(0,0,0,0));
layout->setSpacing(0);

И тогда у меня есть функция для добавления виджетов.

layout->addWidget(_wave);

_wave это мой собственный виджет. Но вы можете добавить все, что хотите, например, QButton.

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

Я добавил везде setMargins, setSpacing и т. Д. Пожалуйста, помогите мне с этим, я действительно не знаю, что мне делать.

Извините за цвета, но я хотел упомянуть, чего я хочу достичь. У меня есть mainWindow, на котором я добавил QWidget. Этот виджет имеет синий фон. Затем к макету я добавляю несколько виджетов, которые оранжевого цвета на этом изображении. Я просто хочу быть уверен, что этот синий фон между виджетами не виден. Я хочу иметь виджет под виджетом, без пробела.

5 ответов

Решение

Я знаю, что вопрос был опубликован год назад, но если он поможет некоторым людям сэкономить время, я был бы рад. У меня была та же проблема, и я смог ее решить, установив:

  • "QFrame.setFrameShape ()" для "NoFrame"
  • "QFrame.seLineWidth ()" в 0.

Изображение ниже является результатом 2-х "QtextEdit", помещенных рядом в макете, используя описанный метод.

http://doc.qt.io/qt-5/qframe.html

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

// After all widgets are added to the layout
layout->insertStretch( -1, 1 );

Второй аргумент должен быть выше, чем любой другой фактор растяжения. Коэффициент растяжения по умолчанию равен нулю, поэтому, если вы не установите его, вышеприведенный однострочный должен работать.

Интервал Никогда Ноль?

Как говорится в документе Qt, некоторые виджеты GUI по умолчанию имеют вокруг себя дополнительную рамку.

принимать QPushButton В качестве примера:

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

Таким образом, виновником является не макет, а сам виджет. "Невидимое" поле виджета по умолчанию сохраняется, даже если для разметки было установлено значение 0.

Soultion

Если вам действительно нужен " компактный " макет, я предлагаю прибегнуть к таблице стилей виджета.


Примеры

Вот примеры, иллюстрирующие идею:

Здесь мы имеем вертикальный макет с полем и полем, равным 0, и кнопки с пользовательской таблицей стилей:

 QPushButton {
     border: 2px solid #8f8f91;
     border-radius: 6px;
     background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                       stop: 0 #f6f7fa, stop: 1 #dadbde);
     min-width: 80px;
 }

// (further stylesheet for button click is needed)

Сброс таблицы стилей позволяет сделать макет более компактным:

Вставить по умолчанию QPushButton чтобы увидеть разницу:

Вы можете видеть, что есть место вокруг по умолчанию QPushButton, То же самое для других видов виджетов.

Похоже, что по умолчанию макеты QT растягивают свои дочерние виджеты, чтобы заполнить пространство макета. Я нашел способ достичь того, что, как я полагаю, вы ищете. Вы можете добавить в макет разделитель с помощью sizeType Expanding (по умолчанию), и он займет все пространство в макете и уменьшит другие виджеты до минимального размера. Вы можете сделать это в визуальном дизайнере QT Creator или в коде примерно так:

      QVBoxLayout *layout = ui->verticalLayout_2;
layout->setContentsMargins(QMargins(0,0,0,0));
layout->setSpacing(0);
QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
layout->addSpacerItem(spacer);

for (int i=0; i<5; ++i)
{
    auto button = new QPushButton(ui->centralwidget);
    button->setText("Click me");
    layout->insertWidget(layout->count() - 1, button, 0, Qt::AlignmentFlag::AlignTop);
}

Если это сделано в коде, вы, вероятно, захотите вставить виджет в count() - 1, чтобы разделитель был последним элементом макета.

Изменить: ответ Kiss-o-matic делает то же самое в 1 строке. И да, вероятно, было бы лучше добавить разделитель после всех остальных элементов, если только вы, как и я, не делаете это для области прокрутки, куда элементы будут добавляться пользователем. Вот почему я сначала добавил разделитель, а потом элементы.

Я могу ошибаться, но, похоже, нет очевидного и не взломанного способа сделать то, что вы хотите. Тем не менее, в соответствии с документацией вы можете обнаружить, что выполнение макета вручную решит вашу проблему. ( http://doc.qt.io/qt-5/layout.html: макет вручную)

Кажется, что можно реализовать класс Layout, который на самом деле обеспечивает очень компактную горизонтальную или вертикальную разметку, и я считаю, что я написал ее несколько лет назад с использованием Python и Qt. Имея это в виду, вы должны быть в состоянии реализовать свой собственный MyCompactLayout(horizontal=True) и использовать это.

Другие вопросы по тегам