1
votes

So, I took it down a few notches and am trying simple programs to get the hang of Qt's tools.

First I tried a simple label inside main() function, then a button inside it. All good.

Next, I tried the same, but inside a main window (using the Qt's created documents). After the one-button program worked, I did a two-button program, that simple. Worked.

Then, I tried Qt's Box Layouts. In none of these "main window" tries, I changed the main.cpp file created by Qt.

Here's the mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPushButton>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QPushButton *button1;
    QPushButton *button2;
};

#endif // MAINWINDOW_H

Next, the mainwindow.cpp file:

#include "mainwindow.h"
#include <QPushButton>
#include <QHBoxLayout>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle(tr("Two Button Example"));
    resize(400,300);

    button1 = new QPushButton(tr("Bye!"));
    button1->setGeometry(0,0,200,30);
    //button1->setParent(this);
    connect(button1,SIGNAL(clicked()),this,SLOT(close()));
    button1->show();

    button2 = new QPushButton(tr("Hide B1!"));
    button2->setGeometry(0,0,200,30);
    //button2->setParent(this);
    connect(button2,SIGNAL(clicked()),button2,SLOT(hide()));
    button2->show();

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(button1);
    layout->addWidget(button2);
    setLayout(layout);
}

MainWindow::~MainWindow()
{

}

I'm studying this book (for the layouts specifically, Chapter 2, the Find Dialog example (page 16 of the book, or 34 from the pdf file): C++ GUI Programming with Qt 4 1st ed.pdf

For this specific problem, I also used this: QHBoxLayout - Qt Examples and Tutorials What I noticed:

  • Commenting the QHBoxLayout part, all the way to the "setLayout" function, makes no difference in the program. No test I've done is affected by this QBoxLayout thing;
  • The "setGeometry" function sets the position (first two parameters) and size (width and heightm, last two parameters) of a widget. This position is related to the parent widget, which may be the screen itself when no parent is assigned;
  • When the "setParent" functions for the buttons are commented and the "show" function is uncommented, the buttons are shown each in a separate window from the MainWindow. When I uncomment the "setParent" functions, the buttons are shown inside the MainWindow, and there's no difference if there are or no "show" functions for the buttons. The detail is, for the book I referenced, no example so far have had the need to declare the parent widgets, nor did the example in Qt's Examples and Tutorials site;
  • If I don't use the "setGeometry" function, the buttons are big, like 600x600, whatever. They follow the rules above regarding the other functions, but they are huge and always one on top of the other, not side by side. The function "sizeHint()" used extensively in the book, also has no effect;

Appearently, it's all following the same syntaxes and rules of the examples. So, what am I doing wrong, or not doing here? If it's not a problem to enlight me with the "sizeHint()" function, too, that would be great.

Thanks in advance!

2
Don't call setLayout on a QMainWindow -- it already has its own custom layout that's responsible for a large part of its functionality.G.M.

2 Answers

1
votes

I don't even remember the origin of the problem, but I have never been able to work with the layouts right in the window. In company I worked with Qt we used a central widget for managing layouts, so the diagram is: window -> central widget -> layouts -> subwidgets. If I modified your code so, it would look like this:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    setWindowTitle(tr("Two Button Example"));
    resize(400,300);

    auto *parentWidget = new QWidget;
    auto button1 = new QPushButton(tr("Bye!"), parentWidget);
    button1->setGeometry(0,0,200,30);
    connect(button1,SIGNAL(clicked()),this,SLOT(close()));

    auto button2 = new QPushButton(tr("Hide B1!"), parentWidget);
    button2->setGeometry(0,0,200,30);
    connect(button2,SIGNAL(clicked()),button2,SLOT(hide()));

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(button1);
    layout->addWidget(button2);
    parentWidget->setLayout(layout);
    setCentralWidget(parentWidget);
}

Also, I don't quite understand why do you try to set the button size if the layout resets it later. To change the size inside a layout you must change the sizeHint of a widget:

 setWindowTitle(tr("Two Button Example"));
 resize(400,300);

 auto *parentWidget = new QWidget;
 auto button1 = new QPushButton(tr("Bye!"), parentWidget);
 button1->setMaximumSize(20, 20);
 connect(button1,SIGNAL(clicked()),this,SLOT(close()));

 auto button2 = new QPushButton(tr("Hide B1!"), parentWidget);
 button2->setMaximumSize(20, 20);
 connect(button2,SIGNAL(clicked()),button2,SLOT(hide()));

 QHBoxLayout *layout = new QHBoxLayout;
 layout->addWidget(button1);
 layout->addWidget(button2);
 parentWidget->setLayout(layout);
 setCentralWidget(parentWidget);
0
votes

After some observation, I believe I know why it wasn't working. In the examples provided, the person was using QDialog or applying the layouts straight to the main() code, while I was using the QMainWindow class. I suppose that when you use a QMainWindow class, you always have to set a Central Widget in order to make layouts work (setting this central widget layout). So a solution would be:

QWidget centerWidget = new QWidget();
setCentralWidget(centerWidget);
//Add buttons, lists, and whatever

/*Add a QHBoxLayout or a QVBoxLayout and use
layout->addWidget() to add the widgets created,
like the examples. Then:*/

centerWidget->setLayout(layout);

It works, like Victor Polevoy suggested. Just answering as I believe I understood why weren't my QLayouts working.