Can you hide a QGroupBox frame but preserve it's content visible?
Solution 1
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());
}
Solution 2
My option:
QGroupBox theBox;
theBox.setFlat(true);
//This removes the border from a QGroupBox named "theBox".
theBox.setStyleSheet("QGroupBox#theBox {border:0;}");
//This removes the border from the group box and all of its children
theBox.setStyleSheet("border:0;");
Solution 3
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);
}
Solution 4
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();
}
![jpo38](https://i.stack.imgur.com/MfMjU.png?s=256&g=1)
jpo38
Software developer, mainly C++, worked with MFC, now working with Qt. Using CMake and more Python every day...
Updated on June 15, 2022Comments
-
jpo38 about 2 years
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 theQGroupBox
was not here....but I must preserve it's content visible (so I don't want to callQGroupBox::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? -
-
jpo38 about 8 yearsThat's an option, but more difficult to setup than applying a stylesheet as commented by MasterAler
-
jpo38 over 7 yearsNice alternative.
-
Cecil Curry over 6 yearsActually, this solution is approximately as trivial to implement as MasterAler's prior solution but has the significant advantage of not hiding the frames of all child widgets. While simple, setting a stylesheet of
border:0
unconditionally applies that style to all child widgets. That's bad. While slightly less simple, this solution suffers no such critical defects. That's good. -
jpo38 over 6 yearsBut QFrame won't let you display a title on the bar ("Emulator 0" in my screenshot)
-
Sachith Bathiya over 6 yearsthat's true. But it looks like the easiest approach to do that with a label
-
fogx over 4 yearshow would i do this for the PyQt version? I am unsure of how to change the method, because the module doesn't have the logic...
def paintEvent(self, a0: QtGui.QPaintEvent) -> None: ...