Получить нажал шахматную фигуру с шахматной доски SVG
Я разрабатываю шахматный графический интерфейс в Python 3.6.3
с помощью PyQt5 5.9.1
(GUI Framework) и python-chess 0.21.1
(шахматная библиотека) на Windows 10
, Я хочу получить значение фигуры, которая была нажата на шахматной доске SVG (предоставлена python-chess
), чтобы я мог переместить этот кусок на другой квадрат.
После первого щелчка левой кнопкой мыши и получения куска, я хочу получить второй щелчок левой кнопкой мыши от пользователя и получить квадрат, по которому щелкнул пользователь. Тогда мой шахматный графический интерфейс должен переместить фигуру из исходного квадрата в целевой квадрат.
Итак, вот мой полный рабочий код. Любые советы или фактические дополнения кода очень приветствуются.
#! /usr/bin/env python3
import chess
import chess.svg
from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import QApplication, QWidget
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Chess Titan")
self.setGeometry(300, 300, 800, 800)
self.widgetSvg = QSvgWidget(parent=self)
self.widgetSvg.setGeometry(10, 10, 600, 600)
self.chessboard = chess.Board()
@pyqtSlot(QWidget)
def mousePressEvent(self, event):
if event.buttons() == Qt.LeftButton:
## How to get the clicked SVG chess piece?
# Envoke the paint event.
self.update()
@pyqtSlot(QWidget)
def paintEvent(self, event):
self.chessboardSvg = chess.svg.board(self.chessboard).encode("UTF-8")
self.widgetSvg.load(self.chessboardSvg)
if __name__ == "__main__":
chessTitan = QApplication([])
window = MainWindow()
window.show()
chessTitan.exec()
2 ответа
Если известен размер шахматной доски, вы можете найти координаты щелчка мышью в событиях.pos() resp.event.x(), event.y() в зависимости от ширины поля и площади, см. Строку chess.svg.py 129 и далее.
редактировать 25 ноября: event.pos()
в этом примере в координатах MainWindow, чтобы найти координаты на шахматной доске, все должно быть рассчитано из верхнего левого угла, представленного self.svgX
а также self.svgY
:
import chess
import chess.svg
from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import QApplication, QWidget
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Chess Titan")
self.setGeometry(300, 300, 800, 800)
self.widgetSvg = QSvgWidget(parent=self)
self.svgX = 50 # top left x-pos of chessboard
self.svgY = 50 # top left y-pos of chessboard
self.cbSize = 600 # size of chessboard
self.widgetSvg.setGeometry(self.svgX,self.svgY, self.cbSize, self.cbSize)
self.coordinates = True
# see chess.svg.py line 129
self.margin = 0.05*self.cbSize if self.coordinates == True else 0
self.squareSize = (self.cbSize - 2 * self.margin) / 8.0
self.chessboard = chess.Board()
self.pieceToMove = [None, None]
@pyqtSlot(QWidget)
def mousePressEvent(self, event):
if self.svgX < event.x() <= self.svgX + self.cbSize and self.svgY < event.y() <= self.svgY + self.cbSize: # mouse on chessboard
if event.buttons() == Qt.LeftButton:
# if the click is on chessBoard only
if self.svgX + self.margin < event.x() < self.svgX + self.cbSize - self.margin and self.svgY + self.margin < event.y() < self.svgY + self.cbSize - self.margin:
file = int((event.x() - (self.svgX + self.margin))/self.squareSize)
rank = 7 - int((event.y() - (self.svgY + self.margin))/self.squareSize)
square = chess.square(file, rank) # chess.sqare.mirror() if white is on top
piece = self.chessboard.piece_at(square)
coordinates = '{}{}'.format(chr(file + 97), str(rank +1))
if self.pieceToMove[0] is not None:
move = chess.Move.from_uci('{}{}'.format(self.pieceToMove[1], coordinates))
self.chessboard.push(move)
print(self.chessboard.fen())
piece = None
coordinates= None
self.pieceToMove = [piece, coordinates]
else:
print('coordinates clicked')
# Envoke the paint event.
self.update()
else:
QWidget.mousePressEvent(self, event)
@pyqtSlot(QWidget)
def paintEvent(self, event):
self.chessboardSvg = chess.svg.board(self.chessboard, size = self.cbSize, coordinates = self.coordinates).encode("UTF-8")
self.widgetSvg.load(self.chessboardSvg)
if __name__ == "__main__":
chessTitan = QApplication([])
window = MainWindow()
window.show()
chessTitan.exec()
перемещайте белые и черные фигуры попеременно, они меняют цвет, если один и тот же цвет перемещается дважды.
Ниже Python
, PyQt5
а также python-chess
код полностью функционального шахматного графического интерфейса, в котором встроено легальное обнаружение движения, поэтому движение шахматной фигуры ведется в соответствии с правилами шахмат.
#! /usr/bin/env python
"""
This module is the execution point of the chess GUI application.
"""
import sys
import chess
from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import QApplication, QWidget
class MainWindow(QWidget):
"""
Create a surface for the chessboard.
"""
def __init__(self):
"""
Initialize the chessboard.
"""
super().__init__()
self.setWindowTitle("Chess GUI")
self.setGeometry(300, 300, 800, 800)
self.widgetSvg = QSvgWidget(parent=self)
self.widgetSvg.setGeometry(10, 10, 600, 600)
self.boardSize = min(self.widgetSvg.width(),
self.widgetSvg.height())
self.coordinates = True
self.margin = 0.05 * self.boardSize if self.coordinates else 0
self.squareSize = (self.boardSize - 2 * self.margin) / 8.0
self.pieceToMove = [None, None]
self.board = chess.Board()
self.drawBoard()
@pyqtSlot(QWidget)
def mousePressEvent(self, event):
"""
Handle left mouse clicks and enable moving chess pieces by
clicking on a chess piece and then the target square.
Moves must be made according to the rules of chess because
illegal moves are suppressed.
"""
if event.x() <= self.boardSize and event.y() <= self.boardSize:
if event.buttons() == Qt.LeftButton:
if self.margin < event.x() < self.boardSize - self.margin and self.margin < event.y() < self.boardSize - self.margin:
file = int((event.x() - self.margin) / self.squareSize)
rank = 7 - int((event.y() - self.margin) / self.squareSize)
square = chess.square(file, rank)
piece = self.board.piece_at(square)
coordinates = "{}{}".format(chr(file + 97), str(rank + 1))
if self.pieceToMove[0] is not None:
move = chess.Move.from_uci("{}{}".format(self.pieceToMove[1], coordinates))
if move in self.board.legal_moves:
self.board.push(move)
piece = None
coordinates = None
self.pieceToMove = [piece, coordinates]
self.drawBoard()
def drawBoard(self):
"""
Draw a chessboard with the starting position and then redraw
it for every new move.
"""
self.boardSvg = self.board._repr_svg_().encode("UTF-8")
self.drawBoardSvg = self.widgetSvg.load(self.boardSvg)
return self.drawBoardSvg
if __name__ == "__main__":
chessGui = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(chessGui.exec_())
A _manthey_67 и Boštjan Mejak, я объединил функции обоих ваших решений: https://github.com/vtad4f/chess-ui/blob/master/board.py
Полная версия интегрирует ИИ-игрока (-ов) с интерфейсом вашей доски:
- Запустите make, чтобы собрать https://github.com/vtad4f/chess-ai/
- Запустите main.py, чтобы сыграть в игру https://github.com/vtad4f/chess-ui/