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

Dynamically add Widgets to Layout



  • Ok i have the following Issue.

    I have a Main Window were i create a custom widget and set it as the Central Widget:

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        mMineField = new MineField(4, 4, 3, this);
        setCentralWidget(mMineField);
    }
    

    The MineField creates depending of which width and height is supplied a count of Cells to display.

    #include <QVector>
    #include <QWidget>
    
    #include "cell.h"
    
    class MineField : public QWidget
    {
        Q_OBJECT
    public:
        explicit MineField(int width,
                           int height,
                           int countOfBombs,
                           QWidget *parent = nullptr);
    
    private:
        QVector<Cell *> createCells(int width, int height, int countOfBombs);
    
        int mWidth;
        int mHeight;
        QVector<Cell *> mCells;
    };
    

    I try to create the Cells and add the to a grid layout like this:

    #include "minefield.h"
    
    #include "cell.h"
    
    #include <QDebug>
    #include <QGridLayout>
    
    #include <random>
    
    MineField::MineField(int width,
                         int height,
                         int countOfBombs,
                         QWidget *parent)
        :QWidget{ parent },
          mWidth{ width},
          mHeight{ height },
          mCells{ createCells(width, height, countOfBombs) }
    {
        auto layout = new QGridLayout;
    
        for(int i = 0; i < mCells.size(); ++i) {
            auto row = static_cast<int>(i %  mWidth);
            auto column = static_cast<int>(i /  mWidth);
    
            qDebug() << "Column = " << column << " Row = " << row;
    
            layout->addWidget(mCells[i], row, column);
        }
    
        setLayout(layout);
    }
    
    QVector<Cell *> MineField::createCells(
            int width, int height, int countOfBombs)
    {
        QVector<Cell *> cells;
        auto size = static_cast<int>(width * height);
        cells.reserve(size);
    
        for(auto i = 0; i < size; ++i) {
            if(i < countOfBombs) {
                cells.push_back(new Cell(Cell::State::mine, this));
            }
            else {
                cells.push_back(new Cell(Cell::State::empty, this));
            }
        }
        return cells;
    }
    
    

    However i don't see anything displayed in the window. Is there an Issue in how i create the widgets dynamically?

    Edit:

    It looks like the Cells are at the correct position. Just the image of them is not displayed. I already tested that Cell paints itself directly in a QMainWindow. Then Why it does not work in the Layout?.

    The Cell is also derrived from QWidget and paints like this:

    void Cell::paintEvent(QPaintEvent *event)
    {
        Q_UNUSED(event)
        QPainter painter{ this };  
        painter.drawImage(geometry(), displayImage(mDisplayType));
    }
    


  • I found the Issue myself in the paintEvent of Cell.

    It has to use rect() instead of geometry():

    void Cell::paintEvent(QPaintEvent *event)
    {
        Q_UNUSED(event)
        QPainter painter{ this };  
        painter.drawImage(rect(), displayImage(mDisplayType));
    }
    

  • Lifetime Qt Champion

    @sandro4912
    Yep or else it might be offset in an unwanted way :)



  • yeah it was quite a nasty bug to find. Not very obvious in the first place.


Log in to reply