Search code examples
qtpyqtqt-designer

Qt layout children float


I have an empty horizontal layout that I dynamically populate with three children. This is a card game so this layout gets dynamically populated with children that are QLabel which have an image set. When I click on a card to play it and move it at the center of the screen I'd like the positions of the other cards to stay the same. Instead the cards tend to "float" to the right. How can I force them to stay in their original position?

+-----------------+
|                 |
| [A] - [B] - [C] |
|                 |
+-----------------+

I tried putting an expandable horizontal spacer in between each card but it doesn't really work. I also tried with replacing the horizontal layout with a grid layout but this forces me to specify the initial coordinates of the cards which I'd rather not. I like the fact that I can append widgets with addWidget pretty much like I do in the HTML version.

In the HTML version I use some wrapper divs with a fixed size around the cards. How can I do something similar in Qt?

EDIT

A little clarification on how the layout should look when one card (B) is played.

+-----------------+
|                 |
| [A] -     - [C] |
|                 |
+-----------------+

As I mentioned I managed to fill the layout with empty QWidget and put cards on top of them (not inside them). I actually got also rid of the horizontal spacers I had as they are not needed anymore. This seems to work as I expect, although I still didn't fully validate this approach.


Solution

  • Simple algorithm steps to do what you want :

    • User clicks
    • Select the label where the click happened
    • If there is an image, Remove the image from the label
    • Don't remove the label from the layout, and make sure that the layout don't resize the label
    • Add the image to a label in the center of the board game.
    • When the user clicks on a label which has nothing, just ignore the click.

    For each player you know the maximum numbers of cards which can be shown in your layout. Moreover, I don't think the size of the card is variable. So each time you create a deck for one player, create empty labels, each one having a fixed size.

    EDIT: SOME OTHER PROPOSITIONS

    • fix size of labels using QWidget::setFixedSize();
    • Don't hide your label to remove your pixmap . Don't set an empty pixmap. Rather, set a pixmap which is transparent or filled with some neutral color...
    • Alternatively subclass QLabel such that you can indicate a minimum size hint. The layout must and will respect anything you set. Example:

      class MyQLabel : public QLabel {
      
        MyQLabel(QSize cardSize, //remaining qlabel args) 
          :QLabel(//label args)
          {_cardsize = cardcardSize;}
      
        //only method to re-implement
        virtual QSize minimumSizeHint () const {return _cardsize;}
      private:
           final QSize _cardsize;
       }
      

    Each time your whole application need to be painted again, all widgets properties are checked. My two cents is that a size property is modified when you play a card, and the layout adapt to this modification. Tell me if the size hint trick work (it should).