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

Drawing Frames arround Widgets



  • Ok this is maybe a weired question.

    I try to make a minesweeper clone in Qt. I already have all the elmenets like the LCDs, the face and the Minefield. However I wonder how you could draw the frames arround them. Maybe you can give me some hint how to do it the easiest.

    Screenshot_20191004_095528.png


  • Lifetime Qt Champion

    Hi
    Since you cannot draw outside a
    Widget form its paintEvent
         its not that trivial to do.

    I used an overlay widget ( transparent for mouseclicks) to draw
    around widgets.
    https://stackoverflow.com/questions/19199863/draw-rectangular-overlay-on-qwidget-at-click

    Can I ask what the use case is?
    Maybe there is easier way to fulfill the same requirement.


  • Moderators

    You can probably use style sheets (QSS) or QStyle to change the colour of your widget's frames (QFrame). This should be quite easy to achieve - but as @mrjj points out, it won't paint outside of the widget.



  • @mrjj

    Like i said i would like to draw the frame arround the widgets like the classic minesweeper has:

    Screenshot_20191004_120228.png

    I have the 2 LCD Displays the SmilieyButton and the minefield as Widgets. So i wonder how i can archieve to have the frame arround them.


  • Lifetime Qt Champion

    @sandro4912
    Hi
    Well the easy way would be to put them/each
    inside a QFrame and style that one to look like you want.



  • Ok this kinda works. I used 3 Frames like this:

    2f621cd1-162b-4593-88d4-ec9eeae071d4-image.png

    However to archieve the style like above i need to switch white and black lines from the borders of the inner ones. Is there a way to do that?


  • Lifetime Qt Champion

    @sandro4912
    Hi
    If you mean the sunken style then yes
    alt text

    its just a setting from raised to sunken.

    alt text



  • With the frames my App looks like this:

    1966f261-46dd-44f3-9862-ea32fa07cfc5-image.png

    How can i get rid of the spacings from the frame to the widgets?

    I thought it was in the layout and setSpacing(0); whould remove it but it doesn't

    The code so far:

    private:
        LcdDisplay *mLcdDisplayMinesLeft;
        LcdDisplay *mLcdDisplayElapsedTime;
        SmileyPushButton *mSmileyPushButton;
        Minefield *mMinefield;
    
        QFrame *mTopFrame;
        QFrame *mBottomFrame;
        QFrame *mMainFrame;
    
    Game::Game(QWidget *parent) :
        QWidget(parent),
        mLcdDisplayMinesLeft{ new LcdDisplay{ mDefaultMines} },
        mLcdDisplayElapsedTime{ new LcdDisplay },
        mSmileyPushButton{ new SmileyPushButton },
        mMinefield{ new Minefield{
                    mDefaultFieldWidth,
                    mDefaultFieldHeight,
                    mDefaultMines }},
        mTopFrame{ new QFrame },
        mBottomFrame{ new QFrame },
        mMainFrame{ new QFrame }
    {
        mMainFrame->setFrameStyle(QFrame::Panel | QFrame::Raised);
        mMainFrame->setLineWidth(3);
    
        mTopFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
        mTopFrame->setLineWidth(3);
    
        mBottomFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
        mBottomFrame->setLineWidth(3);
    
        auto topLayout = new QHBoxLayout;
        topLayout->setSpacing(0);
        topLayout->addWidget(mLcdDisplayMinesLeft);
        topLayout->addStretch();
        topLayout->addWidget(mSmileyPushButton);
        topLayout->addStretch();
        topLayout->addWidget(mLcdDisplayElapsedTime);
        mTopFrame->setLayout(topLayout);
    
        auto bottomLayout = new QHBoxLayout;
        bottomLayout->setSpacing(0);
        bottomLayout->addWidget(mMinefield);
        mBottomFrame->setLayout(bottomLayout);
    
        auto mainLayout = new QVBoxLayout;
        mainLayout->setSpacing(0);
        mainLayout->addWidget(mTopFrame);
        mainLayout->addWidget(mBottomFrame);
    
        mMainFrame->setLayout(mainLayout);
    
        auto layout = new QVBoxLayout;
        layout->setSpacing(0);
        layout->addWidget(mMainFrame);
    
        setLayout(layout);
    }
    
    

  • Lifetime Qt Champion

    @sandro4912
    Hi
    Looking good. :)

    The space can most likely be removed with

    layout->setContentsMargins(0,0,0,0);

    all layout have a default values of 9 for all 4 sides



  • @mrjj

    Appling the margin i get this:

    cd97f0df-bb0a-4ec9-ad36-808589b172e6-image.png

    This is almost perfect. Just one nitpick.

    The Top and Bottom frame seem to touch each other without any spae inbetween. Any change to add a space like between the outside frame and the inside frames?

    The code now looks like this:

        auto topLayout = new QHBoxLayout;
        topLayout->setSpacing(0);
        topLayout->setContentsMargins(0,0,0,0);
        topLayout->addWidget(mLcdDisplayMinesLeft);
        topLayout->addWidget(mSmileyPushButton);
        topLayout->addWidget(mLcdDisplayElapsedTime);
        mTopFrame->setLayout(topLayout);
    
        auto bottomLayout = new QHBoxLayout;
        bottomLayout->setSpacing(0);
        bottomLayout->setContentsMargins(0,0,0,0);
        bottomLayout->addWidget(mMinefield);
        mBottomFrame->setLayout(bottomLayout);
    
        auto mainLayout = new QVBoxLayout;
        mainLayout->setSpacing(0);
        mainLayout->addWidget(mTopFrame);
        mainLayout->addWidget(mBottomFrame);
    
        mMainFrame->setLayout(mainLayout);
    
        auto layout = new QVBoxLayout;
        layout->setSpacing(0);
        layout->setContentsMargins(0,0,0,0);
        layout->addWidget(mMainFrame);
    
        setLayout(layout);
    


  • I could solve the Issue by removing the Space 0 here:

    auto mainLayout = new QVBoxLayout;
        //mainLayout->setSpacing(0);
        mainLayout->addWidget(mTopFrame);
        mainLayout->addWidget(mBottomFrame);
    

    Which gives:

    110f829d-24f0-4382-a414-ca3b200d02ff-image.png

    That looks pretty close to the original:

    b5a3a974-f0aa-4e07-867b-137dde40f3d0-image.png

    Although it looks like there is still some kind of space between the minefield and the frame? Can it be removed aswell?


  • Lifetime Qt Champion

    Hi
    It looks very much like the original
    How nostalgic :)



  • Yes the only Issue I still see is the remainig space between minefield and the bottomFrame.


  • Lifetime Qt Champion

    Hi
    There ?
    alt text



  • Yes in the original theres no space at all.

    I already throw out the top frame for testing to see if it causes it but still same result.


  • Lifetime Qt Champion

    @sandro4912
    Hi
    Im not sure where that space comes from as it seems you have it to zero

    auto bottomLayout = new QHBoxLayout;
    bottomLayout->setSpacing(0);
    bottomLayout->setContentsMargins(0,0,0,0);
    bottomLayout->addWidget(mMinefield);
    mBottomFrame->setLayout(bottomLayout);

    Did you try to raise the margins to see if you then get more space there ?



  • This post is deleted!


  • @mrjj

    Yes if i rais the margin these spaces get higher. Still is very weired that 0 still gives these gaps.

    I run the game in KDE Neon and Windows 10. On both OS is the same behaviour.


  • Moderators

    hi @sandro4912 ,

    my guess is, that the margins come from the mainLayout. You only set the setContentsMargins to 0 inside the bottomLayout, but the insert that layout into the mainLayout which has its own contentMargins still != 0



  • @J-Hilk

    No it still has the same Issue:

        auto topLayout = new QHBoxLayout;
        topLayout->setSpacing(0);
        topLayout->setContentsMargins(0,0,0,0);
        topLayout->addWidget(mLcdDisplayMinesLeft);
        topLayout->addWidget(mSmileyPushButton);
        topLayout->addWidget(mLcdDisplayElapsedTime);
        mTopFrame->setLayout(topLayout);
    
        auto bottomLayout = new QHBoxLayout;
        bottomLayout->setSpacing(0);
        bottomLayout->setContentsMargins(0,0,0,0);
        bottomLayout->addWidget(mMinefield);
        mBottomFrame->setLayout(bottomLayout);
    
        auto mainLayout = new QVBoxLayout;
        mainLayout->setSpacing(0);
        mainLayout->setContentsMargins(0,0,0,0);
        mainLayout->addWidget(mTopFrame);
        mainLayout->addWidget(mBottomFrame);
    
        mMainFrame->setLayout(mainLayout);
    
        auto layout = new QVBoxLayout;
        layout->setSpacing(0);
        layout->setContentsMargins(0,0,0,0);
        layout->addWidget(mMainFrame);
    
        setLayout(layout);
    

    Result:
    e9de883c-65c2-4d40-8e1b-c83887644194-image.png


  • Moderators

    @sandro4912
    mmh, strange.

    I'm out of easy ideas to try 😞
    sry


  • Lifetime Qt Champion

    Hi
    What about INSIDE minefield ?
    Did you use layout there ?



  • Yes inside the Minfield I place the Cells like this in the constructor:

    auto layout = new QGridLayout;
       layout->setSpacing(0);
    
       for(int i = 0; i < mCells.size(); ++i) {
           auto column = static_cast<int>(i %  mFieldWidth);
           auto row = static_cast<int>(i /  mFieldWidth);
    
           layout->addWidget(mCells[i], row, column);
       }
    
       setLayout(layout);
    

  • Lifetime Qt Champion

    @sandro4912

    But you dont seem to call setContentsMargins(0,0,0,0);
    so maybe that is the space ?



  • @mrjj said in Drawing Frames arround Widgets:

    setContentsMargins(0,0,0,0);

    thats it!

    d4167070-a480-4188-9923-57d57cb94d35-image.png

    I thought i tryed it before but i think i tryed:

    setContentsMargins(0,0,0,0);
    

    and not

    layout->setContentsMargins(0,0,0,0);
    

Log in to reply