PyQt5 - 将 AbstractButton 添加到布局

PyQt5 - add AbstractButton to layout

我正在制作纸牌纸牌游戏来练习 OOP 和 PyQt5,但我无法将继承 QAbstractButton 的纸牌添加到布局(QGridLayoutQHBoxLayout,或 QVBoxLayout)。这是 Card 对象的一部分:

class Card(QAbstractButton):    

    def __init__(self, rank=None, suit=None, parent=None):
        super().__init__(parent)
        self.rank = rank
        self.suit = suit
        self.visibility = False

    def paintEvent(self, e):
        painter = QPainter()
        painter.begin(self)
        if self.visibility == True:
            self.draw_card_front(painter)
        else:
            self.draw_card_back(painter)
        painter.end()

    def draw_card_back(self, painter):
        painter.setPen(COLOR_OUTLINE)
        painter.setBrush(COLOR_BACK)
        painter.drawRoundedRect(0, 0, CARD_WIDTH-1, CARD_HEIGHT-1, 10, 10)

    def draw_card_front(self, painter):
        painter.setPen(COLOR_OUTLINE)
        painter.setBrush(COLOR_FRONT)
        painter.drawRoundedRect(0, 0, CARD_WIDTH-1, CARD_HEIGHT-1, 10, 10)

        self.draw_rank(painter)
        self.draw_suit(painter)

    ...

这是游戏的 class:

class Solitaire(QWidget):

    def __init__(self):
        super().__init__()
        self.score = 0

        self.initUI()


    def initUI(self):
        grid = QGridLayout()
        self.setLayout(grid)

        self.card1 = Card(rank=1, suit=2, parent=self)
        self.card2 = Card(rank=1, suit=2, parent=self)

        grid.addWidget(self.card1, 0, 0)
        grid.addWidget(self.card2, 1, 0)

        self.setWindowTitle('Yay')
        self.setGeometry(300, 300, 400, 400)
        self.show()

    ...

if __name__ == '__main__':
    app = QApplication(sys.argv)
    game = Solitaire()
    app.exec_()

当我运行程序时,Card没有出现。但是如果我不使用布局,Card 会正常显示。如果我尝试将 QPushButton 添加到布局中,它也能正常工作。我觉得我在 parent 属性 中遗漏了一些东西,或者我可能没有在 Card class 中重载 QAbstractButton 中的函数。有人可以建议吗?

根据 docs:

To subclass QAbstractButton, you must reimplement at least paintEvent() to draw the button's outline and its text or pixmap. It is generally advisable to reimplement sizeHint() as well, and sometimes hitButton() (to determine whether a button press is within the button). For buttons with more than two states (like tri-state buttons), you will also have to reimplement checkStateSet() and nextCheckState().

从上面我们得出结论,您必须实现负责绘制按钮的paintEvent()方法,这取决于您要绘制什么,以及sizeHint()方法是大小由布局使用。

例如:

import sys

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class Card(QAbstractButton):    

    def __init__(self, rank=None, suit=None, parent=None):
        super().__init__(parent)
        self.rank = rank
        self.suit = suit
        self.visibility = False

    def sizeHint(self):
        return QSize(100, 100)

    def paintEvent(self, e):
        painter = QPainter(self)
        if self.visibility:
            self.draw_card_front(painter)
        else:
            self.draw_card_back(painter)

    ...

class Solitaire(QWidget):

    def __init__(self):
        super().__init__()
        self.score = 0

        self.initUI()


    def initUI(self):
        grid = QGridLayout()
        self.setLayout(grid)

        self.card1 = Card(rank=1, suit=2, parent=self)
        self.card2 = Card(rank=1, suit=2, parent=self)

        grid.addWidget(self.card1, 0, 0)
        grid.addWidget(self.card2, 1, 0)

        self.setWindowTitle('Yay')
        self.setGeometry(300, 300, 400, 400)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    game = Solitaire()
    app.exec_()