Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Strange QMainWindow Layout behaviour



  • Dear all,

    I am new to Qt and trying to develop a Qt application that runs on a Rapsberry Pi using EGLFS. Development is made on a Linux-PC. However, the layout of the main window drives me crazy.

    For test purposes, I have created an application based on a QMainWindow with 4 QPushButtons on it and chosen a grid layout (right click on the window, layout -> ... ). Each button in one cell of the grid. The size of the window is 480 x 320 (width x height), the size of the Raspi's display.

    On the PC, it looks ok and the preview behaves as expected, but when I run the application on the Raspberry Pi, the buttons are far too large and take more space than is available. Strangely, the reported width of the window is correct (480)... If I then delete the layout of the main window and put just the buttons there, when the application is started on the Raspberryp Pi the size is ok.

    Is there anybody who can explain to me what I am doing wrong?

    I have tried playing with the QT_* environment variables on the Raspberry but as expected, without success.

    What I would like to have in the end is a window that has a row of push buttons at the bottom of the window and a container widget above them (e.g. a QFrame) that occupies the rest of the available space and that i can change depending on the buttons that are pressed.

    Thank you very much for your help!

    Kind regards,

    Ralf



  • Hi,

    the problem is solved.

    I have compiled and run the following program on my Pi:

    #include <QApplication>
    #include <QHBoxLayout>
    #include <QMainWindow>
    #include <QPushButton>
    
    class MainWindow : public QMainWindow
    {
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    };
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
    }
    
    MainWindow::~MainWindow()
    {
    }
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        MainWindow *mainWindow = new MainWindow();
        mainWindow->setCentralWidget(new QWidget());
    
        QPushButton *button1 = new QPushButton("One");
        QPushButton *button2 = new QPushButton("Two");
        QPushButton *button3 = new QPushButton("Three");
        QPushButton *button4 = new QPushButton("Four");
    
        QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(button1);
        layout->addWidget(button2);
        layout->addWidget(button3);
        layout->addWidget(button4);
    
        mainWindow->centralWidget()->setLayout(layout);
        mainWindow->show();
    
        return app.exec();
    }
    

    The result is that I see four buttons on the Pi in a vertical layout, but the buttons are too large. When I run the program on the PC (Windows version) it is ok, I see the four buttons completely.

    It looks like Qt does not detect the correct screen width. However, even when I force it with QT_QPA_EGLFS_WIDTH=480 as recommended in https://doc.qt.io/qt-5/embedded-linux.html it does not work either.

    Then I have set some environment variables to get debug information and I think I have found the source of the problem:

    qt.qpa.eglfs.kms: "HDMI1" mode count: 2 crtc index: 0 crtc id: 49
    qt.qpa.eglfs.kms: mode 0 1920 x 320 @ 59 hz
    qt.qpa.eglfs.kms: mode 1 480 x 320 @ 59 hz
    qt.qpa.eglfs.kms: Selected mode 0 : 1920 x 320 @ 59 hz for output "HDMI1"
    qt.qpa.eglfs.kms: Physical size is QSizeF(0, 0) mm for output "HDMI1"
    qt.qpa.eglfs.kms: Format is 34325258 requested_by_user = false for output "HDMI1"
    qt.qpa.eglfs.kms: Output "HDMI1" framebuffer size is QSize(1920, 320)

    I think the fourth line (selected mode) explains why the height is ok but the width is not. Up to now I had not payed attention to this because my LCD is connected to the SPI port and I have nothing connected to the HDMI ports.

    However, hdmi_mode=1 was already set in /boot/config.txt. Then I found out that one of the configuration programs (perhaps the one that configurees the LCD) had added hdmi_mode=87 to the configuration.

    This seemed a bit strange to me but in fact hdmi_group=2 and hdmi_mode=87 allows the creation of non standard display timings, as is necessary for my display.

    What finally solved the problem was to set the environment variable QT_QPA_EGLFS_KMS_CONFIG to point to a file with the following content:

    {
      "device": "/dev/dri/card1",
      "hwcursor": false,
      "pbuffers": true,
      "outputs": [
        {
          "name": "VGA1",
          "mode": "off"
        },
        {
          "name": "HDMI1",
          "mode": "480x320"
        }
      ]
    }
    

    This is described in the section "EGLFS with the eglfs_kms Backend" of https://doc.qt.io/qt-5/embedded-linux.html. Doing this, the mode is correctly detected (1 instead of 0).

    Perhaps this helps others to solve similar problems.

    Kind regards,

    Ralf



  • @DL5EU said in Strange QMainWindow Layout behaviour:

    when I run the application on the Raspberry Pi, the buttons are far too large and take more space than is available.

    Can you show a picture how it looks like.
    Normally, when using layouts correctly this is exactly what should not happen.

    @DL5EU said in Strange QMainWindow Layout behaviour:

    I have created an application based on a QMainWindow with 4 QPushButtons on it and chosen a grid layout (right click on the window, layout -> ... )

    So you've created your UI in QtDesigner? Show how your widget tree looks like.

    @DL5EU said in Strange QMainWindow Layout behaviour:

    window that has a row of push buttons at the bottom of the window and a container widget above them

    After all, a QGridLayout is maybe not the best solution in your case. Have you tried using nested layouts (A combination of horizontal and vertical box layouts, i.e. QHBoxLayout and QVBoxLayout)?



  • Hello @Pl45m4 ,

    thank you for your answer.

    I have added three screen shots below and hope they will help to clarify my problem. In fact, the image on the Raspberry Pi seems 4 times as large as it should (only the leftmost quarter is displayed).

    The widget tree, is this what shows up in the upper right part of the designer window (MainWindow, centralwidget and the push buttons)? If not, as I am not very familiar with Qt and Qt Creator yet, how can I display it?

    Here is how it looks like on the Raspberry (simulated on the PC):

    Raspberry.png

    And here the preview on the PC:

    Preview.png

    And lastly, this is how it looks like in the Qt Creator:

    Designer.png

    For information, I am using Qt 5.15 and Qt Creator 4.12.2 (based on Qt 5.14.2).

    I have not yet decided which kind of layout to use but it should be easily sizeable, because other users could use a different display (smaller or bigger as my 480x320). For the main window a grid layout is perhaps not the best solution but I would like to use it for the different containers I want to insert in the main window above the buttons at the bottom of the window because it allows a quite flexible layout of my widgets and seems to fit my needs.

    Thank you very much for your help!

    Kind regards,

    Ralf


  • Lifetime Qt Champion

    Hi,

    Are you fixing the size of your widget ?
    What window manager are you using on the Pi ?
    How are you simulating it ?



  • Hello @SGaist,

    I do not use a window manager on the Raspberry Pi but EGLFS as a QPA backend, as it is described in different articles. There is only one window in full screen mode. With QT_QPA_EGLFS_NO_LIBINPUT=1 and QT_QPA_EGLFS_TSLIB=1 in the environment the touch screen also works correctly.

    And I don't simulate my program. It is cross-compiled on the PC and then transferred to and started on the Pi (Raspberry Pi 4B, 4GB). This works well and as long as I do not use layouts but fixed sizes everything is fine.

    I have set the size of my QMainWindow in the geometry settings to 480x320, the size of my LCD. And I have set other environment variables (QT_QPA_EGLFS_PHYSICAL_WIDTH=73.44, QT_QPA_EGLFS_PHYSICAL_HEIGHT=48.96, QT_QPA_EGLFS_WIDTH=480 and QT_QPA_EGLFS_HEIGHT=320) but this did not change anything. Neither did QT_AUTO_SCREEN_SCALE_FACTOR=true and QT_ENABLE_HIGHDPI_SCALING=1.

    I am certain that I haven't fully understood Qt's layout system yet. Perhaps I use it in a wrong way?

    Kind regards,

    Ralf


  • Lifetime Qt Champion

    @DL5EU said in Strange QMainWindow Layout behaviour:

    Here is how it looks like on the Raspberry (simulated on the PC):

    That's why I asked about the simulation.

    What do you get if you do not set the size of your main window ?



  • "Simulated" means that I have not taken a photo of the Pi but I have taken a screen shot of a window on the PC that looks like the display of the Pi.

    And as far as the size of the window is concerned, when I create an application in Qt Creator that is based on a QMainWindow, the main window has always a size, by default it is 800x600 pixels. When I try to set the size of a window that has widgets on it to (0, 0), the window shrinks, probably to the minimum allowed size.

    Kind regards,

    Ralf


  • Lifetime Qt Champion

    To be sure I understand you correctly, are you using a Designer based widget ?



  • Yes, I use Qt Creator to develop the application and the integrated Qt Designer to create the user Interface.

    Regards,

    Ralf


  • Lifetime Qt Champion

    Can you check with a default non Designer based QMainWindow to see if you have the same issue ?



  • Hi,

    the problem is solved.

    I have compiled and run the following program on my Pi:

    #include <QApplication>
    #include <QHBoxLayout>
    #include <QMainWindow>
    #include <QPushButton>
    
    class MainWindow : public QMainWindow
    {
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    };
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
    }
    
    MainWindow::~MainWindow()
    {
    }
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        MainWindow *mainWindow = new MainWindow();
        mainWindow->setCentralWidget(new QWidget());
    
        QPushButton *button1 = new QPushButton("One");
        QPushButton *button2 = new QPushButton("Two");
        QPushButton *button3 = new QPushButton("Three");
        QPushButton *button4 = new QPushButton("Four");
    
        QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(button1);
        layout->addWidget(button2);
        layout->addWidget(button3);
        layout->addWidget(button4);
    
        mainWindow->centralWidget()->setLayout(layout);
        mainWindow->show();
    
        return app.exec();
    }
    

    The result is that I see four buttons on the Pi in a vertical layout, but the buttons are too large. When I run the program on the PC (Windows version) it is ok, I see the four buttons completely.

    It looks like Qt does not detect the correct screen width. However, even when I force it with QT_QPA_EGLFS_WIDTH=480 as recommended in https://doc.qt.io/qt-5/embedded-linux.html it does not work either.

    Then I have set some environment variables to get debug information and I think I have found the source of the problem:

    qt.qpa.eglfs.kms: "HDMI1" mode count: 2 crtc index: 0 crtc id: 49
    qt.qpa.eglfs.kms: mode 0 1920 x 320 @ 59 hz
    qt.qpa.eglfs.kms: mode 1 480 x 320 @ 59 hz
    qt.qpa.eglfs.kms: Selected mode 0 : 1920 x 320 @ 59 hz for output "HDMI1"
    qt.qpa.eglfs.kms: Physical size is QSizeF(0, 0) mm for output "HDMI1"
    qt.qpa.eglfs.kms: Format is 34325258 requested_by_user = false for output "HDMI1"
    qt.qpa.eglfs.kms: Output "HDMI1" framebuffer size is QSize(1920, 320)

    I think the fourth line (selected mode) explains why the height is ok but the width is not. Up to now I had not payed attention to this because my LCD is connected to the SPI port and I have nothing connected to the HDMI ports.

    However, hdmi_mode=1 was already set in /boot/config.txt. Then I found out that one of the configuration programs (perhaps the one that configurees the LCD) had added hdmi_mode=87 to the configuration.

    This seemed a bit strange to me but in fact hdmi_group=2 and hdmi_mode=87 allows the creation of non standard display timings, as is necessary for my display.

    What finally solved the problem was to set the environment variable QT_QPA_EGLFS_KMS_CONFIG to point to a file with the following content:

    {
      "device": "/dev/dri/card1",
      "hwcursor": false,
      "pbuffers": true,
      "outputs": [
        {
          "name": "VGA1",
          "mode": "off"
        },
        {
          "name": "HDMI1",
          "mode": "480x320"
        }
      ]
    }
    

    This is described in the section "EGLFS with the eglfs_kms Backend" of https://doc.qt.io/qt-5/embedded-linux.html. Doing this, the mode is correctly detected (1 instead of 0).

    Perhaps this helps others to solve similar problems.

    Kind regards,

    Ralf


  • Lifetime Qt Champion

    Glad you found out and thanks for the detailed solution !