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

只愿长相守 提交于 2019-12-05 08:36:44
MasterAler

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;");
Reinstate Monica

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!