Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you hide a QGroupBox frame but preserve it's content visible?

Tags:

qt

groupbox

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:

enter image description here

  • QGroupBox::setTitle("") removes the text.
  • QGroupBox::setFlat(true) makes the frame be a single line.

I end up with this:

enter image description here

Not too bad...but a line remains....is there a way to completely hide the QGroupBox frame but preserve it's content visible?

like image 311
jpo38 Avatar asked Apr 13 '16 15:04

jpo38


4 Answers

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;");
like image 158
pablo_worker Avatar answered Sep 30 '22 14:09

pablo_worker


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);
}
like image 36
Tomas Avatar answered Sep 30 '22 13:09

Tomas


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());
}
like image 33
MasterAler Avatar answered Sep 30 '22 15:09

MasterAler


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.

screenshot of the example

// 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();
}
like image 24
Kuba hasn't forgotten Monica Avatar answered Sep 30 '22 15:09

Kuba hasn't forgotten Monica