Results 1 to 4 of 4

Thread: setheightforwidth not working?

  1. #1
    Join Date
    Sep 2021
    Posts
    3
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default setheightforwidth not working?

    Hi everybody. I've poked a bit at QT before but I'm really a newbie. Now I'm attempting to put together a version of the classic minesweeper game.

    This kind of game really needs square cells in the grid. I thought I could get that by applying the "heightforwidth" property to the qpushbuttons that make up each tile.
    Here's an example of what I get:

    Screenshot_2021-09-07_11-09-44.jpg

    Here's the code for the cell:

    Qt Code:
    1. class GridCell : public QPushButton
    2. {
    3. bool Bomb;
    4. GridPos Pos;
    5.  
    6. public:
    7. GridCell() {}
    8. virtual ~GridCell() {}
    9.  
    10. GridCell (QGridLayout *GridLayout, const GridPos &P) : QPushButton ()
    11. {
    12. Pos = P;
    13. GridLayout->addWidget(this, Pos.y, Pos.x);
    14.  
    15. QSizePolicy p(sizePolicy());
    16. p.setHeightForWidth (true);
    17. p.setVerticalPolicy (QSizePolicy::Expanding);
    18. p.setHorizontalPolicy (QSizePolicy::Expanding);
    19. p.setHorizontalStretch (1);
    20. p.setVerticalStretch (1);
    21. setSizePolicy (p);
    22.  
    23. setText("K");
    24. }
    25.  
    26. void SetBomb (bool B = true)
    27. {
    28. Bomb = B;
    29. }
    30.  
    31. bool IsBomb ()
    32. {
    33. return Bomb;
    34. }
    35. };
    To copy to clipboard, switch view to plain text mode 

    I've tried a lot of different things but guess I'm misunderstanding some fundamental concept.

    A little help please?
    Last edited by d_stranz; 8th September 2021 at 01:10. Reason: missing [code] tags

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: setheightforwidth not working?

    A little help please?
    Your problem is with your grid layout. By design, all layouts expand to fill the widget (or layout) in which they are placed. In turn, they will expand the widgets inside them to occupy the same space by looking at things like size limits (min / max), size policy, stretch factors, spacing, margins, etc. Taking all this into account, the layout sets the size and position of the widgets it contains.

    So all of the things you are doing are basically not having much effect on the actual size or shape of the widgets except to ensure that they all have the same size in the grid layout.

    I'll need to think about how to implement this using widgets. It would be a lot simpler using QGraphicsScene / QGraphicsView / QGraphicsRectItem than a grid layout with push buttons. With the Graphics View architecture, you have much more control over the layout of your scene.

    I think the first step is to make your left-hand panel a QHBoxLayout with a custom QWidget in the top (representing your game board) and a QSpacerItem in the bottom half. The QSpacerItem will basically force the QWidget up. Let's call it GameBoardWidget to be clear.

    The GameBoardWidget needs a QGridLayout to hold the cells. Implement a sizeHint() method for the GridCell to return a square size. Set the size policies to "Preferred", not "Expanding". You'll probably also need to add a member variable for GridCell to hold the preferred size, and a method to set the preferred size.

    Implement a QWidget::resizeEvent() event handler for GameBoardWidget. In this handler if GameBoardWidget::isVisible() returns true, this means that the QResizeEvent::size() method will return a valid size that can be used for geometry computations. The resizeEvent can occur multiple times while Qt is laying out the initial UI -before- anything becomes visible on screen, and the sizes in these initial calculations cannot be used. It is only after the widget is shown (isVisible returns true) that the sizes are guaranteed to be valid.

    In your resize event, determine the button size based on the minimum dimension of the GameBoardWidget, the number of buttons in a row or column, and take into account the QGridLayout::horizontalSpacing() and QGridLayout::verticalSpacing(). If the new size is different from the old size, then use this number to set the size hint for your GridCell widgets, then call QWidget::updateGeometry(). Be careful you don't set up an infinite loop of resizeEvent() / updateGeometry() calls. Only change the geometry and size hints if in fact the size is different.

    I can't guarantee that this will work, and I don't have time to write code to test it. You may have to play around a bit to get it all working the way you want.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. The following user says thank you to d_stranz for this useful post:

    kcameron4456 (9th September 2021)

  4. #3
    Join Date
    Sep 2021
    Posts
    3
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: setheightforwidth not working?

    Thanks for the input. I understand now that the QGridLayout needs to fill its container.

    The QGraphicView approach seemed a little complicated. I really didn't want to keep track of pixels when placing the buttons.

    Your resizeEvent suggestion led me to me solution. Now I'm applying the QGridLayout to a frame. I adjust the width of the frame as needed to maintain the desired aspect ratio with sizeHint.

    Qt Code:
    1. // Special frame for playing grid
    2. // main feature is to keep aspect ratio based on grid y/x size
    3. class cGameGridFrame : public QFrame {
    4. public:
    5. cGameGridFrame (QHBoxLayout *LO) : QFrame () {
    6. // insert the new frame into the right side of the hbox layout
    7. LO->insertWidget(0, this);
    8.  
    9. // set properties
    10. setSizePolicy (QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
    11. setFrameShape (QFrame::Box);
    12. setFrameShadow (QFrame::Raised);
    13. setLineWidth (4);
    14. }
    15.  
    16. QSize sizeHint() const {
    17. QSize s = size();
    18. s.setWidth ((float)s.height()*GridXSize/GridYSize+0.5);
    19. return s;
    20. }
    21.  
    22. void resizeEvent(QResizeEvent * event) {
    23. QFrame::resizeEvent(event);
    24. updateGeometry();
    25. }
    26. };
    To copy to clipboard, switch view to plain text mode 

    Example output:
    Screenshot_2021-09-09_Shot1.jpg

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: setheightforwidth not working?

    I really didn't want to keep track of pixels when placing the buttons.
    You don't. You simply define your rectangle to have whatever dimensions you want, in logical coordinates. So if you choose a dimension of 10 x 10 for the cell, and you have a 10 x 10 grid, then you simply place each cell at increments of 10 in each direction. This would give you a QGraphicsScene with a 100 x 100 bounding box in logical, not pixel coordinates.

    When you place this scene in a QGraphicsView, the view will automatically scale and translate the scene so it fits in the view. You can control this to maintain a square aspect ratio by using one of the QGraphicsView::fitInView() methods.

    But it looks like you have been successful doing it with buttons and a grid layout, so whatever works. Think about the Graphics / View architecture next time you do something graphical where a grid won't work.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Qml is not working
    By sanjeet in forum Qt for Embedded and Mobile
    Replies: 7
    Last Post: 14th April 2016, 09:38
  2. Replies: 7
    Last Post: 24th September 2012, 08:17
  3. Working with map
    By naptizaN in forum Newbie
    Replies: 4
    Last Post: 28th August 2012, 13:57
  4. MVC example not working
    By yyiu002 in forum Newbie
    Replies: 1
    Last Post: 30th June 2010, 01:07
  5. My first app not working
    By Noks in forum Newbie
    Replies: 6
    Last Post: 2nd February 2010, 17:34

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.