Issue
I am trying to design a chess board GUI with PyQt. The board is comprised of frames. When I place a transparent PNG of a chess piece, the PNG is colored with the background of the window, thus covering the frame underneath. When there is no background color set to the window, the piece, and the square beneath it display properly. How could I set the image to not cover the frame square underneath it with the window background color?
Here is a screenshot of the output:
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()
Solution
The problem is that you're setting a general background for the top level widget, and since stylesheets are propagated to children, the result is that the piece inherits that background.
The solution is to always avoid such general declarations and properly use selectors instead.
In this case, you can use the class selector:
class MainWindow(qtw.QWidget):
def __init__(self):
# ...
self.setStyleSheet("MainWindow {background-color: indigo;}")
Unrelated considerations:
- be careful when iterating over a list that is being modified within the iteration itself, and be aware that you're not properly taking advantage of it anyway: you already have the inner list, so use
row.append(square)
instead; - you're creating a layout, but you're not using it; this can become an issue, as resizing the main window will not allow the board to adapt its size or position: if the window is made bigger, the board will occupy only part of the interface, but if the size is smaller, it can become completely invisible; see this related answer for a possible implementation that takes into account window resizing while keeping the correct aspect ratio;
- the
mw.show()
at the end will never be called (at least, not usefully), since you placed it after entering the application event loop (app.exec_()
);
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.