I have a QGroupBox
. Depending on the context, it's title may be redundent (displayed in another place of the GUI), so I then need to make as if the QGroupBox
was not here....but I must preserve it's content visible (so I don't want to call QGroupBox::hide()
)!
I need to do this dynamically at runtime and would like to avoid creating/destroying the QGroupBox
+ reparenting it's content....there must be an easier way to do this.
What I tried so far:
QGroupBox
visible:
QGroupBox::setTitle("")
removes the text.QGroupBox::setFlat(true)
makes the frame be a single line.
I end up with this:
Not too bad...but a line remains....is there a way to completely hide the QGroupBox
frame but preserve it's content visible?
You can use QFrame
+ QGridLayout
(or some more complex combination of layouts) + QSS instead of a QGroupBox
.
Considering a QGroupBox
only, a trivial solution via QSS could be:
static const char kSavedTitle[] = "_savedTitle";
void hideBoxFrame(QGroupBox * box) {
box->setProperty(kSavedTitle, box->title());
box->setTitle(QString());
box->setStyleSheet("border:none");
}
void showBoxFrame(QGroupBox * box) {
box->setTitle(box->property(kSavedTitle).toString());
box->setStyleSheet(QString());
}
You can derive your own Group Box from the QGroupBox
and reimplement the paintEvent()
method. It should be very simple. Original QGroupBox::paintEvent()
looks like this:
void QGroupBox::paintEvent(QPaintEvent *)
{
QStylePainter paint(this);
QStyleOptionGroupBox option;
initStyleOption(&option);
paint.drawComplexControl(QStyle::CC_GroupBox, option);
}
What you need to do is just to modify the style option right before the widget is painted:
void CMyGroupBox::paintEvent(QPaintEvent *)
{
QStylePainter paint(this);
QStyleOptionGroupBox option;
initStyleOption(&option);
// This should disable frame painting.
option.features = QStyleOptionFrame::None;
paint.drawComplexControl(QStyle::CC_GroupBox, option);
}
My option:
QGroupBox theBox;
theBox.setFlat(true);
theBox.setStyleSheet("border:0;");
Here's an example that does it by swapping the widgets and reparenting the children. It works for any widget that has direct children, not only QGroupBox
. It would require special case handling for widgets such as QScrollArea
and QMainWindow
that wrap children in a special sub-widget.
See this question for a related discussion of programmatically promoting widgets.
// https://github.com/KubaO/stackoverflown/tree/master/questions/group-reparent-36603051
#include <QtWidgets>
/// Replaces the visible widget with a hidden widget, preserving the layout of the
/// children, and making the new widget visible.
void swapWidgets(QWidget * a, QWidget * b)
{
auto src = a->isVisible() ? a : b;
auto dst = a->isVisible() ? b : a;
Q_ASSERT(dst->isHidden());
/// Move the children to the destination
dst->setLayout(src->layout());
/// Replace source with destination in the parent
auto layout = src->parentWidget()->layout();
delete layout->replaceWidget(src, dst);
/// Unparent the source, otherwise it won't be reinsertable into the parent.
src->setParent(nullptr);
/// Only the destination should be seen.
src->hide();
dst->show();
}
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QWidget w;
QGridLayout wLayout{&w};
QPushButton swapBtn{"Swap"};
wLayout.addWidget(&swapBtn);
QWidget noBox;
QGroupBox box{"Group"};
wLayout.addWidget(&box);
QGridLayout boxLayout{&box};
for (int i = 0; i < 16; ++i)
boxLayout.addWidget(new QLabel(QString("Tr%1").arg(i)), i/8, i%8);
swapBtn.connect(&swapBtn, &QPushButton::clicked, [&] { swapWidgets(&box, &noBox); });
w.show();
return app.exec();
}
Yes there is a alternative that you can Try.
You can morph into a QFrame which will keep the behavior But make the container boundaryless
You can simply right click on the Group Box in the QDesigner and Select the 'Morph Into' option to select from
来源:https://stackoverflow.com/questions/36603051/can-you-hide-a-qgroupbox-frame-but-preserve-its-content-visible