1

The following is the smallest example I could make to present the isuue.

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QVBoxLayout *vLayout = new QVBoxLayout(this);

    QGroupBox *gb = new QGroupBox;
//    MyGroupBox *gb = new MyGroupBox;
    vLayout->addWidget(gb);

    QPushButton *btB = new QPushButton;
    vLayout->addWidget(btB);
}

enter image description here

The code above produces the image above, it's just a group box and a button in vertical layout.

If I replace QGropBox by MyGroupBox then it doesn't show there anymore. The code below produces the image below.

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QVBoxLayout *vLayout = new QVBoxLayout(this);

//    QGroupBox *gb = new QGroupBox;
    MyGroupBox *gb = new MyGroupBox;
    vLayout->addWidget(gb);

    QPushButton *btB = new QPushButton;
    vLayout->addWidget(btB);
}

enter image description here

Where mygroupbox.h (the constructor body is empty in the .cpp file):

#include <QWidget>

class MyGroupBox : public QWidget
{
    Q_OBJECT
public:
    explicit MyGroupBox(QWidget *parent = 0);

signals:

public slots:

};

Why the group box isn't showing there? How to make it appear?

KcFnMi
  • 3,922
  • 8
  • 43
  • 90
  • 1
    You're adding an empty widget, so there's nothing to display. If you want to prove there is something there or not, try inherit from `QFrame` and call `setFrameStyle(QFrame::Panel)` on it so you get a border where the widget is – Steve Lorimer Jun 30 '16 at 16:52
  • 1
    This is tagged with C++11, but it's just C++98 :( Qt+C++11 looks way nicer and less verbose than that! – Kuba hasn't forgotten Monica Jun 30 '16 at 17:11
  • @KubaOber please appreciate my C++11 politeness at http://stackoverflow.com/questions/38130827/quiloader-widget-not-showing-if-loaded-in-derived-qwidget. – KcFnMi Jun 30 '16 at 20:17
  • @KubaOber, besides your feedback, is there someway to check how far away am I from C++11 (or even 14)? Any tool? – KcFnMi Jul 03 '16 at 19:24

2 Answers2

3

This is why it doesn't appear:

class MyGroupBox : public QWidget

Your "group box" is basically just a QWidget. Inherit from QGroupBox instead.

anonymous
  • 3,754
  • 2
  • 15
  • 36
3

As an aside, a minimal example could look like the below. Not a single declaration/statement/expression can be removed. The button aids in visualizing the problem, so it should be left in. The use of a failure trigger variable highlights exactly what condition triggers the failure: the code self-documents and you almost need no narrative to explain it. The question could be as concise as the test case below and one sentence "Why is the group box's border not visible when fail is true?". Most likely, had you followed the minimization fully through, you'd realize yourself what the problem was - it becomes rather obvious. It's not so when MyGroupBox is declared in another file!

The technique of putting it all into a single main.cpp file is critical in spotting the problem: all of the code is physically next to each other, making it much easier to spot mistakes! When you minimize, usually the first things that have to go are separate files: cram it all into one file, and then relentlessly remove absolutely everything that's not directly needed in reproducing the issue.

#include <QtWidgets>

struct MyGroupBox : public QWidget {};

int main(int argc, char ** argv) {
   bool fail = true;
   QApplication app{argc, argv};
   QWidget widget;
   QVBoxLayout layout{&widget};
   QGroupBox groupBox;
   MyGroupBox myGroupBox;
   QPushButton button;
   layout.addWidget(fail ? static_cast<QWidget*>(&myGroupBox) : &groupBox);
   layout.addWidget(&button);
   widget.show();
   return app.exec();
}

This concise style is not only for trivial test cases. In your real code, the Widget's header and implementation could look as follows:

// Widget.h
#include <QtWidgets>
#include "MyGroupBox.h"

class Widget : public QWidget {
  Q_OBJECT
  QVBoxLayout layout{this};
  MyGroupBox groupBox;
  QPushButton button{tr("Click Me!")};
public:
  explicit Widget(QWidget * parent = nullptr);
};

// Widget.cpp
#include "Widget.h"

Widget::Widget(QWidget * parent) :
  QWidget{parent} {
  layout.addWidget(&groupBox);
  layout.addWidget(&button);
}

If you insist on shielding the interface from implementation details, don't use pointers to widgets etc., use a PIMPL.

// Widget.h
#include <QWidget>

class WidgetPrivate;
class Widget : public QWidget {
   Q_OBJECT
   Q_DECLARE_PRIVATE(Widget)
   QScopedPointer<WidgetPrivate> const d_ptr;
public:
   explicit Widget(QWidget * parent = nullptr);
};

// Widget.cpp
#include "Widget.h" // should always come first!
#include "MyGroupBox.h"

class WidgetPrivate {
   Q_DECLARE_PUBLIC(Widget)
   Widget * const q_ptr;
public:
   QVBoxLayout layout{q_func()};
   QGroupBox groupBox;
   MyGroupBox myGroupBox;
   QPushButton button{"Click Me!"};
   WidgetPrivate(Widget * q) : q_ptr(q) {
      layout.addWidget(&groupBox);
      layout.addWidget(&button);
   }
};

Widget::Widget(QWidget * parent) :
   QWidget{parent}, d_ptr{new WidgetPrivate{this}}
{}
Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 88,505
  • 13
  • 129
  • 275
  • It's nice to see a Qt programmer using automatic storage. ;-) Is this becoming idiomatic, with the tendency to Pointers Everywhere just another example of the vast body of outdated example code out there, or my poor searching... or are you still a minority in this sense? There's certainly an issue with outdated style, as you've commented earlier, and Qt with modern C++ features looks a lot more bearable to me. I'm just wondering whether pointers are following a similar pattern. Stack semantics is a main reason I like GTKmm so much (in its interface; of course, the underlying C is all dynamic). – underscore_d Jun 30 '16 at 19:25
  • Really should I prefer `QVBoxLayout layout{this}` on the .h then `QVBoxLayout *vLayout = new QVBoxLayout(this)` in the .cpp? Would you mind post a reference for your style? – KcFnMi Jun 30 '16 at 19:25
  • The tendency to Pointers Everywhere just another example of the vast body of outdated example code out there. Worse yet, there was no reason to code that way even in Qt 4, even using a C++98 compiler. Holding Qt's containers and QObjects by pointer is double indirection, since a `QObject` or a `QVector` is a pointer-to-PIMPL... Specifically a `QObject` is a `QScopedPointer`. Both Qt 4 and Qt 5 source can be trivially modified to make `QObject` and all derived types moveable when compiled with C++11. – Kuba hasn't forgotten Monica Jun 30 '16 at 19:31
  • @KcFnMi Fwiw, my "reference" for preferring Kuba's syntax is that I don't use pointers unless I have a reason to use pointers. Sadly, Qt example code seems to follow the opposite rule, for no real reason I've been able to work out. – underscore_d Jun 30 '16 at 19:34
  • 1
    @KcFnMi What do you mean "a reference" to "my" style? Hold things by value - that should always be default - unless you have a really good reason to do otherwise. That's not my style, that's basic conservative C++ coding. Indirection costs extra, additional dynamic allocations cost extra. It's all premature pessimization to use it haphazardly. Understand the semantics of the code you write. E.g. the order of member declarations has a meaning and can't be arbitrary. I've run into a C++ codebase where they insisted on sorting all class member declarations alphabetically... Nuts. – Kuba hasn't forgotten Monica Jun 30 '16 at 19:34
  • I was meaning who besides you think so... (There is a guideline posted somewhere telling that?) But now I think I got it. I'm a little biased by Qt's code as noted. – KcFnMi Jun 30 '16 at 19:41
  • "who besides you think so" Anyone who doesn't want to write C++ that works like molasses? Why don't you hold all **other** members of your classes by pointer *either*? What's so special about `QObject` vs. for example `int`? You could dynamically allocate every single member of your class, yet you don't. It'd be ridiculous, right? It is - so don't. `QObject` isn't magic. Privately it's a `QScopedPointer`. Ignoring that, there's nothing in its API that prevents you from storing it by value. Lots of Qt examples are verbose, pessimized and mindlessly following a rather useless pattern. – Kuba hasn't forgotten Monica Jun 30 '16 at 19:45
  • @KubaOber Thought so :-) I'm a lot more likely to try Qt now that I've been lucky enough to see past all the awful examples - some in official docs - to the revelation that it's not 1998 anymore! GTKmm got my attention first as it was (seemingly) far easier to find official content touting its modern C++ credentials, whereas with Qt, most of the encouraging stuff I've since found is on dev blogs - with the official tutorial tending toward the old style of MACROS and pointers everywhere. I see now that 5.7 _requires_ C++11 - very nice. But enough thinking aloud. Thanks for the great summaries! – underscore_d Jun 30 '16 at 19:48