Qt布局子项浮动

3

我有一个空的水平布局,动态填充了三个子项。这是一款卡牌游戏,因此该布局会动态填充QLabel子项,并设置图像。当我点击要玩的卡牌并将其移动到屏幕中央时,我希望其他卡牌的位置保持不变。但是,卡牌往往会“漂浮”到右侧。如何强制它们保持原来的位置?

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

我尝试在每个卡片之间放置一个可扩展的水平间距,但这并不起作用。我还尝试了使用网格布局替换水平布局,但这会强制我指定卡片的初始坐标,而我不太想这样做。我喜欢使用addWidget添加小部件,就像在HTML版本中一样。
在HTML版本中,我使用一些包装器div围绕卡片并设置固定大小。如何在Qt中实现类似的效果?
编辑
当播放一张卡片(B)时,布局应该如何呈现得更加清晰。
+-----------------+
|                 |
| [A] -     - [C] |
|                 |
+-----------------+

正如我所提到的,我成功地用空的QWidget填充了布局,并把卡片放在它们的顶部(而不是内部)。我还摆脱了水平间隔器,因为它们不再需要。这似乎按照我的预期工作,尽管我仍然没有完全验证这种方法。


你在使用哪种布局?“动态地”是什么意思? - UmNyobe
我正在使用水平布局。动态地指的是布局最初为空,然后我使用layout.addWidget(card)来填充它。 - Lorenzo
你能展示一张卡片和两张卡片的布局应该是什么样子吗?是不是只有 [A][B] 保持在同一个位置? - Avaris
2个回答

3
简单算法步骤以实现您所需的功能:
  • 用户点击
  • 选择单击发生的标签
  • 如果有图像,请从标签中删除图像
  • 不要从布局中删除标签,并确保布局不会调整标签的大小
  • 将图像添加到棋盘游戏中心的标签中。
  • 当用户单击没有任何内容的标签时,请忽略该单击。

对于每个玩家,您可以知道在您的布局中可以显示的最大卡片数量。此外,我认为卡片的大小是固定的。因此,每次为一个玩家创建一副牌时,请创建空标签,每个标签都具有固定的大小。

编辑:其他建议

  • 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;
     }
    
每当整个应用程序需要重新绘制时,所有小部件属性都会被检查。我的建议是,在您打出一张牌时修改大小属性,然后布局将适应此修改。告诉我这个大小提示技巧是否有效(它应该有效)。

这可能是一个可行的解决方案。我可以使用QLabel的QPixmap属性,在原始的QLabel上将其设置为None,并在棋盘中心创建一个新的QLabel。我会测试它并让你知道它的效果如何。 - Lorenzo
实际上经过很多的尝试,这个方案最终成为了胜利者。无论我怎么做,QLabels 都会滑动。我将接受这个解决方案。 - Lorenzo
请使用我的新建议再试一次。 - UmNyobe

1
在Qt中,您可以使用包装器QWidget和Fixed sizePolicy。

你的意思是一个 QWidget 可以包含另一个 QWidget 吗?我的 Card 类继承自 QLabel(它是一个 QWidget)。也许这可以通过代码完成,但在 Qt Designer 中我看不到任何方法可以实现这一点。 - Lorenzo
是的,QWidget可以托管其他QWidgets。在Qt Designer中,您可以执行以下操作:右键单击小部件,选择“提升到...”,在“提升类名称”中键入MyCard,并在“头文件”中键入适当的头文件名称。按添加,然后选择添加的条目并按提升。 - Paul
您可能还想查看 QGraphicsSceneQGraphicsView,也许使用它们来实现您的游戏比传统小部件更容易。 - Paul
保罗,我制作了你建议的方法的变体,我不确定它为什么有效,但它确实有效。我采用了水平布局>右键单击>变形为>QWidget的方式。然后我将它们设置为固定大小策略,具有固定的最小值和最大值。然后将这3个QWidget添加到网格布局中,当我只需使用GridLayout.addWidget(card, 0, column, QtCore.Qt.AlignLeft)时,它就神奇地工作并在我删除Card widget实例以将其添加到板的中心时保持在那里。 - Lorenzo
好的,我现在明白为什么这个可以工作了:因为我添加的这些空的QWidgets保留了用于放置在它们上面的卡片的空间,而不是内部。由于我可以在网格布局中指定要添加卡片的列,所以当我用牌堆中的新卡片替换该空槽时,这也适用。 - Lorenzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接