首页 > 解决方案 > 透明图像覆盖具有主窗口背景颜色的框架

问题描述

我正在尝试使用 PyQt 设计一个棋盘 GUI。该板由框架组成。当我放置棋子的透明 PNG 时,PNG 会与窗口的背景一起着色,从而覆盖下面的框架。当没有为窗口设置背景颜色时,该块及其下方的方块会正确显示。如何将图像设置为不使用窗口背景颜色覆盖其下方的框架方块?

这是输出的屏幕截图:
例子

from PyQt5 import QtWidgets
import PyQt5.QtWidgets as qtw
import PyQt5.QtGui as qtg
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

DIM = 1024
SQUARE = 70
PIECE = 60

class MainWindow(qtw.QWidget):
    def __init__(self):
        super().__init__()
        self.setLayout(qtw.QGridLayout())
        self.resize(DIM,DIM)        
        
        board = [[] for _ in range(0, 8)]
        for r, row in enumerate(board):
            for c in range(0, 8):
                square = QFrame(self)
                square.setObjectName(u"frame" + f"{r}-{c}")
                square.setGeometry(QRect(DIM // 2 - SQUARE * (c - 4),
                                        DIM - 300 - SQUARE*(r+1), SQUARE, SQUARE))
                if (r + c) % 2 == 0:
                    square.setStyleSheet(u"background-color: grey;")
                else:
                    square.setStyleSheet(u"background-color: white;")
                board[r].append(square)
        

        self.setStyleSheet("background-color: indigo;")        
        self.setWindowFlag(Qt.FramelessWindowHint)
        
        pawn = QtWidgets.QLabel(self)
        pawn.setPixmap(qtg.QPixmap("pieces/b_pawn.png"))
        pawn.setGeometry(DIM // 2 - 2 * SQUARE + 5 , DIM - 300 - SQUARE + 5, PIECE, PIECE)

        self.show()

app = qtw.QApplication([])
mw = MainWindow()

app.exec_()
mw.show()

标签: pythonpyqtpyqt5

解决方案


问题是您正在为顶级小部件设置一般背景,并且由于样式表被传播到子级,结果是该片段继承了该背景。

解决方案是始终避免此类通用声明并正确使用选择器

在这种情况下,您可以使用类选择器:

class MainWindow(qtw.QWidget):
    def __init__(self):
        # ...
        self.setStyleSheet("MainWindow {background-color: indigo;}") 

不相关的考虑:

  • 迭代一个在迭代本身中被修改的列表时要小心,并注意你没有正确地利用它:你已经有了内部列表,所以使用它row.append(square)
  • 你正在创建一个布局,但你没有使用它;这可能会成为一个问题,因为调整主窗口的大小将不允许板子调整其大小或位置:如果窗口变大,板子将只占据界面的一部分,但如果尺寸更小,它可以变成完全看不见;请参阅此相关答案以获取在保持正确纵横比的同时考虑窗口大小调整的可能实现;
  • 最后的mw.show()永远不会被调用(至少,没有用处),因为你在进入应用程序事件循环( )之后app.exec_()放置了它;

推荐阅读