Unwanted padding around QHBoxLayout
-
I am trying to create a scollable widget containing other widgets organised into groups. I have a class SettingsView that derives from QScrollArea. This contains a widget with a QVBoxLayout to which are added sublcasses of SettingsViewGroup - a custom widget that represents a group of widgets with a heading and a QFormLayout to contain the child widgets. SettingsViewGroup has overloaded methods addRow() to add a widget/layout to the form layout and subclasses call these methods to construct a group.
Problem: when I add a row that is a QHBoxLayout, the layout has unwanted padding around it. I have scoured the web for answers and tried all sorts of potential solutions...
layout->setContentsMargins(0, 0, 0, 0);
layout->setMargin(0);
layout->invalidate(); layout->update();
adding a QSpacerItem after the widgets in the inserted layout
etc...Note that whether or not the extra padding appears seems to depend on the widgets that are contained in the nested layout. In my DeviceSettingsView class (code attached) the row with a combo box and push button have the extra padding while the row with a spin box and label do not!
The only trick that partially works, getting rid of padding to the left of the inserted layout, is to added a dummy widget at the start of the layout and then hide it. However there is still excess padding below the layout and, besides, this is not an elegant solution!
I am wondering if this is an issue with QMacStyle. If so, how do I get around it? If not, is there anything else I can try?
Another issue [solved - see below]: The title of each group is a styled QPushButton which toggles whether or not the groups's child widgets are visible. If the SettingsView (QScrollArea) cannot contain the full height of the groups, the vertical scrollbar becomes active as expected. When a group's title is clicked and the child form layout hidden, the groups below do fill the gap left thanks to a spacer item. But the scrollbar does not reflect this, still corresponding to the height of the scroll area's contents before the layout was hidden. Any ideas?
I am using Qt 4.7.4 with QT Creator 2.3.1 on OSX 10.6.8.
-
The code...
@/******************************************************************************
SettingsViewGroup
******************************************************************************/SettingsViewGroup::SettingsViewGroup(const QString& title, SettingsView* parent)
: _parent(parent)
{
QPushButton* titleButton = new QPushButton(title);
titleButton->setStyleSheet("...");
titleButton->setFixedHeight(30);
titleButton->setAutoFillBackground(true);
titleButton->setContentsMargins(0, 0, 0, 0);_contentLayout = new QFormLayout; _contentLayout->setContentsMargins(0, 0, 0, 0); _contentLayout->setHorizontalSpacing(10); _contentLayout->setVerticalSpacing(8); _contentLayout->setRowWrapPolicy(QFormLayout::DontWrapRows); _contentLayout->setLabelAlignment(Qt::AlignLeft); _contentLayout->setFormAlignment(Qt::AlignLeft); _content = new QWidget; _content->setContentsMargins(0, 0, 0, 0); _content->setFixedWidth(SETTINGS_WIDTH - 35); _content->setLayout(_contentLayout); QVBoxLayout* _outerLayout = new QVBoxLayout(); _outerLayout->setSpacing(8); _outerLayout->addWidget(titleButton); _outerLayout->addWidget(_content); _contentHidden = false; setLayout(_outerLayout); setContentsMargins(0, 0, 0, 0); setFixedWidth(SETTINGS_WIDTH - 35); ...
}
void SettingsViewGroup::titleClicked()
{
_content->setVisible(_contentHidden);
_contentHidden = !_contentHidden;
}void SettingsViewGroup::addRow(const QString& labelText, QWidget* field)
{
field->setContentsMargins(0, 0, 0, 0);
_contentLayout->addRow(labelText, field);
}void SettingsViewGroup::addRow(const QString& labelText, QBoxLayout* field)
{
field->setContentsMargins(0, 0, 0, 0);
field->setMargin(0);
QWidget* dummy = new QWidget;
dummy->setFixedSize(10, 10);
field->insertWidget(0, dummy);
dummy->setVisible(false);
_contentLayout->addRow(labelText, field);
}/******************************************************************************
DeviceSettingsView
******************************************************************************/DeviceSettingsView::DeviceSettingsView(SettingsView* parent)
: SettingsViewGroup("Device", parent)
{
_driver = new QComboBox;
_driver->setEditable(false);
_driver->setContentsMargins(0, 0, 0, 0);// populate _driver combo... _play = newIconButton(ICON_PLAY); _play->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); QHBoxLayout* layout = new QHBoxLayout; layout->setSpacing(10); layout->addWidget(_driver); layout->addWidget(_play); addRow("Driver", layout); _resolution = new QComboBox; _resolution->setEditable(false); addRow("Resolution", _resolution); _stream = new QComboBox; _stream->setEditable(false); addRow("Streams", _stream); _tilt = new QSpinBox; _tilt->setRange(-50, 50); _tilt->setSingleStep(0.5); _tilt->setValue(0); _tiltInfo = new QLabel; _tiltInfo->setText("Tilt not enabled"); layout = new QHBoxLayout; layout->setSpacing(10); layout->addWidget(_tilt); layout->addWidget(_tiltInfo); addRow("Tilt", layout);
...
}/******************************************************************************
SettingsView
******************************************************************************/SettingsView::SettingsView(QWidget parent) : QScrollArea(parent)
{
QVBoxLayout layout = new QVBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);_device = new DeviceSettingsView(this); layout->addWidget(_device); // added other groups here... layout->addItem(new QSpacerItem(100, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding)); QWidget* content = new QWidget; content->setContentsMargins(0, 0, 0, 0); content->setLayout(layout); setWidget(content); setObjectName("settings"); setFixedWidth(SETTINGS_WIDTH); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setStyleSheet( "QScrollArea#settings { " " border: 1px solid black; " " margin: 10px 10px 10px 5px }");
}
@ -
Solved the second problem regarding the vertical scroll bar... called adjustSize() on the group and on the widget containing the group.
@
void SettingsViewGroup::titleClicked()
{
_content->setVisible(_contentHidden);
_contentHidden = !_contentHidden;
adjustSize(); // <-------------- ADDED
_parent->updateLayout(); // <-------------- ADDED
}void SettingsView::updateLayout() // <-------------- ADDED
{
_content->adjustSize();
}
@