Drawing Chess Pieces On A Qlabel Type Chessboard In A Qlayout Pyqt 5
Solution 1:
Dealing with widgets that have a fixed aspect ratio is not an easy task, and some precautions must be taken in order to ensure that having an "incompatible" parent size doesn't prevent proper display.
In this case, a possible solution is to use a widget for the chessboard that uses a grid layout for all the squares and pieces. Note that a QLabel isn't a good choice for the chessboard, as it doesn't allow a size smaller than the QPixmap, so a QWidget should be subclassed instead.
The trick is to override the resizeEvent()
, ignore the base implementation (which by default adapts the geometry of the layout) and manually set the geometry based on the minimum extent between width and height.
In order to ensure that the layout has proper equal spacings even when a row or column is empty, setRowStretch()
and setColumnStretch()
must be called for the whole grid size.
Then, you add the pieces directly to the layout, and whenever you need to move them you can just create a helper function that uses addWidget()
with the correct row/column (which will automatically "move" the widget to the new position).
Here is a possible implementation.
from PyQt5 import QtCore, QtGui, QtWidgets
class Pawn(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.image = QtGui.QPixmap('whitepawn.png')
self.setMinimumSize(32, 32)
def paintEvent(self, event):
qp = QtGui.QPainter(self)
size = min(self.width(), self.height())
qp.drawPixmap(0, 0, self.image.scaled(
size, size, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation))
class Board(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QGridLayout(self)
layout.setSpacing(0)
layout.setContentsMargins(0, 0, 0, 0)
self.background = QtGui.QPixmap('chessboard.png')
for i in range(8):
layout.setRowStretch(i, 1)
layout.setColumnStretch(i, 1)
for col in range(8):
layout.addWidget(Pawn(), 1, col)
def minimumSizeHint(self):
return QtCore.QSize(256, 256)
def sizesHint(self):
return QtCore.QSize(768, 768)
def resizeEvent(self, event):
size = min(self.width(), self.height())
rect = QtCore.QRect(0, 0, size, size)
rect.moveCenter(self.rect().center())
self.layout().setGeometry(rect)
def paintEvent(self, event):
qp = QtGui.QPainter(self)
rect = self.layout().geometry()
qp.drawPixmap(rect, self.background.scaled(rect.size(),
QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation))
class ChessGame(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
central = QtWidgets.QWidget()
self.setCentralWidget(central)
layout = QtWidgets.QHBoxLayout(central)
self.board = Board()
layout.addWidget(self.board)
self.table = QtWidgets.QTableWidget(1, 3)
layout.addWidget(self.table)
import sys
app = QtWidgets.QApplication(sys.argv)
game = ChessGame()
game.show()
sys.exit(app.exec_())
Note that you should also consider using the Graphics View Framework, which provides much more control and features that can be very useful for this kind of interfaces. Be aware that it's as powerful as it's hard to get accustomed to, and it takes a long time to understand all of its aspects.
Post a Comment for "Drawing Chess Pieces On A Qlabel Type Chessboard In A Qlayout Pyqt 5"