class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): """The main window containing everything.""" super().__init__(*args, **kwargs) self.init_ui() def init_ui(self): self.resize(800, 600) self.setWindowTitle("Mathjax Qt test") self.input_widget = QLineEdit(self) self.input_widget.setPlaceholderText("Enter math here and press enter") self.input_widget.returnPressed.connect(self.input_widget_validate) self.svg = QSvgWidget() central_widget = QWidget() self.setCentralWidget(central_widget) layout = QVBoxLayout(central_widget) layout.addWidget(self.input_widget) layout.addWidget(self.svg) def input_widget_validate(self): math = self.input_widget.text() data = {"format": "TeX", "math": math, "svg": True} r = requests.post('http://localhost:8003', data=json.dumps(data)) self.svg.load(r.content)
class Forecast: def __init__(self): self.layout = QGridLayout() self.wrapper = QFrame() self.wrapper.setLayout(self.layout) self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.icon = QSvgWidget() self.day = QLabel() self.min_temp = QLabel() self.max_temp = QLabel() self.precip = QLabel() self.wind = QLabel() self.layout.addWidget(self.icon, 0, 0, 1, 1) self.layout.addWidget(self.day, 1, 0, 1, 1) self.layout.addWidget(self.min_temp, 1, 1, 1, 1) self.layout.addWidget(self.max_temp, 0, 1, 1, 1) self.layout.addWidget(self.wind, 0, 2, 1, 1) self.layout.addWidget(self.precip, 1, 2, 1, 1) def update(self, values): self.icon.load(values.icon) self.day.setText(values.day) self.min_temp.setText(values.min_temp) self.max_temp.setText(values.max_temp) self.precip.setText(values.precip) self.wind.setText(values.wind)
def __init__(self, parent=None): super().__init__(parent) logo = QSvgWidget() logo.load(":/icons/apps/22/tabulator.svg") name = QLabel( self.tr( "<strong style=\"font-size:large;\">{0}</strong> v{1}").format( QApplication.applicationName(), QApplication.applicationVersion())) description = QLabel( self. tr("An editor tool for documents with character-separated values")) labels = QVBoxLayout() labels.addWidget(name) labels.addWidget(description) # Main layout self._layout = QHBoxLayout(self) self._layout.addWidget(logo) self._layout.addLayout(labels) # Set logo size height = name.sizeHint().height() + labels.layout().spacing( ) + description.sizeHint().height() logo.setFixedSize(height, height)
class Current: def __init__(self): self.layout = QGridLayout() self.wrapper = QFrame() self.wrapper.setLayout(self.layout) self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.time = QLabel() self.icon = QSvgWidget() self.temp = QLabel() self.precip = QLabel() self.wind = QLabel() self.layout.addWidget(self.time, 0, 0, 1, 2) self.layout.addWidget(self.icon, 1, 0, 3, 1) self.layout.addWidget(self.temp, 1, 1, 1, 1) self.layout.addWidget(self.wind, 2, 1, 1, 1) self.layout.addWidget(self.precip, 3, 1, 1, 1) def update(self, values): self.icon.load(values.icon) self.time.setText(values.time) self.temp.setText(values.temp) self.wind.setText(values.wind) self.precip.setText(values.precip)
def get_q_svg_component_widget(self, parent=None): label = QSvgWidget(parent) label.parent = parent # TODO this is overkill, recreating the SVG Widget way too often. self.create( config_controller.box_size[0] * self.properties.w, config_controller.box_size[1] * self.properties.h, ) string_image = self.rendered_img.to_str() array = QByteArray(string_image) label.load(array) label.uid = self.uid return label
def renderPages(self, start, stop): """ draw the given page range [start, stop] of PDFContext on the widgets """ self.directory = self.myPDFContext.directory self.myPDFContext.loadPages(range(start, stop + 1)) for page in range(start, stop): # range function is not inclusive pagePath = os.path.join(self.directory, f"{page}.svg") print(f"attempted to access page at path: {pagePath}") pageWid = QSvgWidget() pageWid.setObjectName(f"page{page}") pageWid.setFixedHeight(400) pageWid.load(pagePath) self.collection.append(pageWid) self.initUI() # re-init the UI after updating collection size
class DatasheetView(QMainWindow): def __init__(self, pdfPath=None, pageNumber=1): super().__init__() # initialize data files # self.fileStore = path.join(path.curdir, "/files") # mkdir(self.fileStore) self.svgFiles = [] # window dimensions self.top = 300 self.left = 800 self.width = 860 self.height = 980 self.setGeometry(self.left, self.top, self.width, self.height) # window title self.setWindowTitle("Hello") # sets up main layout -- splitters self.initUILayout() self.initUIToolbar() self.populatePDF(pdfPath, pageNumber) self.show() def initUILayout(self): # set left-side, Dynamic View self.dynamicViewDisplay = QLabel() self.vBoxA = QVBoxLayout() self.vBoxA.addWidget(self.dynamicViewDisplay) self.groupA = QGroupBox() self.groupA.setTitle("Dynamic Veiw") self.groupA.setLayout(self.vBoxA) # set left-side, Static View self.staticViewDisplay = QLabel() self.vBoxB = QVBoxLayout() self.vBoxB.addWidget(self.staticViewDisplay) self.groupB = QGroupBox() self.groupB.setTitle("Static View") self.groupB.setLayout(self.vBoxB) # add Dynamic and Static Views to resizeable left-side Splitter self.altViewSplit = QSplitter(Qt.Vertical) self.altViewSplit.addWidget(self.groupA) self.altViewSplit.addWidget(self.groupB) # set up Tools View section self.toolsTabView = QTabWidget() self.toolsTabView.setTabsClosable(True) self.toolsTabView.setMovable(True) self.toolsTabView.setDocumentMode(True) # self.toolsTabView.setTabBarAutoHide(True) # add attribute for storing page notes self.notesDB = [] self.notesDisplay = QListWidget(self) self.notesDisplay.setMaximumHeight(200) # add ToC to Tools View self.ToCListView = QListWidget() self.toolsTabView.addTab(self.ToCListView, "Table of Contents") # add notes list to tools view self.toolsTabView.addTab(self.notesDisplay, "Notes") # add tools view to the left-side splitter self.altViewSplit.addWidget(self.toolsTabView) # set right-side view -- SVG Viewer self.mainDisplay = QSvgWidget() self.vBoxMain = QVBoxLayout() self.vBoxMain.addWidget(self.mainDisplay) self.notesArea = QLineEdit() self.notesArea.setPlaceholderText("Add a note about this page...") self.notesArea.returnPressed.connect(self.onAddNote) self.vBoxMain.addWidget(self.notesArea) self.mainViewGroup = QGroupBox() self.mainViewGroup.setTitle("Main View") self.mainViewGroup.setLayout(self.vBoxMain) # join both sides together self.leftRightSplit = QSplitter(Qt.Horizontal) self.leftRightSplit.addWidget(self.altViewSplit) self.leftRightSplit.addWidget(self.mainViewGroup) self.setCentralWidget(self.leftRightSplit) def initUIToolbar(self): mainMenu = self.menuBar() # get the menu bar already in use by this QMainWindow class fileMenu = mainMenu.addMenu("File") editMenu = mainMenu.addMenu("Edit") LayoutMenu = mainMenu.addMenu("Layout") AboutMenu = mainMenu.addMenu("About") saveAction = fileMenu.addAction("Save") quitAction = fileMenu.addAction("Exit Bettersheets") quitAction.triggered.connect(self.quitApp) copyAction = editMenu.addAction("Copy") resetAction = LayoutMenu.addAction("Reset Default Layout") # mainMenu.setNativeMenuBar(True) # mainMenu.show() self. toolBar = self.addToolBar("Tools") self.toolBar.addAction(saveAction) self.toolBar.addAction(copyAction) def contextMenuEvent(self, event): # return super().contextMenuEvent(event) contextMenu = QMenu() selectAction = contextMenu.addAction("Select Area") extractAction = contextMenu.addAction("Extract Content") openAction = contextMenu.addAction("Open PDF") closeAction = contextMenu.addAction("Close PDF") quitAction = contextMenu.addAction("Quit") triggered_action = contextMenu.exec_(self.mapToGlobal(event.pos())) if triggered_action == quitAction: self.quitApp() def quitApp(self): self.close() def onAddNote(self): print("note added") text = self.notesArea.text() if text: self.notesDB.append(text) self.notesDisplay.clear() self.notesDisplay.addItems(self.notesDB) self.notesArea.clear() def populatePDF(self, pdfPath, pageNumber): if pdfPath: self.document = PDFContext(pdfPath, pageNumber) ToC = self.document.getToC() ToC_headings_list = [x[1] for x in ToC] self.ToCListView.clear() self.ToCListView.addItems(ToC_headings_list) # display page in main view self.document.openPDF(pdfPath, pageNumber) self.SVGString = self.document.getRender(self.document.currentPageNumber) # set filename of current PDF self.pdfName = path.split(pdfPath)[1].split('.')[0] # write current page to .svg file file_loc = self._writeSVGToFile_(self.pdfName, pageNumber, self.SVGString) # open the file we just wrote to self.mainDisplay.load(file_loc) @staticmethod def _writeSVGToFile_(pdfName: str, pageNumber: int, svg_string: str) -> str: """ return the full file path we just wrote """ file_loc = f"./src/main/files/{pdfName}-page-{pageNumber}.svg" with open(file_loc , 'w') as f: f.write(svg_string) print("File_loc: ", file_loc) return file_loc
class Form(QMainWindow): def __init__(self, parent=None): super(Form, self).__init__(parent) self.svg_style = SvgStyle() self.temp_svg_file = QTemporaryFile() if not self.temp_svg_file.open(): # need to obtain temp file name raise RuntimeError('Cannot create temporary file for svg object') self.temp_svg_file.close() self.setWindowTitle(u'Круговая диаграмма') self.model = CustomTableModel() self.table_view = QTableView() self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) self.table_view.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) self.widget_svg = QSvgWidget() self.widget_style = StyleWidget() self.widget_style.style_changed.connect(self.style_updated) # central widget layout layout = QHBoxLayout() # size = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) # size.setHorizontalStretch(1) # self.table_view.setSizePolicy(size) layout.addWidget(self.table_view) layout.addWidget(self.widget_svg) layout.addWidget(self.widget_style) self.widget_svg.setFixedSize(500, 500) widget_central = QWidget() widget_central.setLayout(layout) self.setCentralWidget(widget_central) # main menu self.menu = self.menuBar() self.menu_file = self.menu.addMenu("File") # load QAction action_load = QAction('Open', self) action_load.setShortcut(QKeySequence.Open) action_load.triggered.connect(self.load_data) self.menu_file.addAction(action_load) self.statusBar() # exit QAction action_exit = QAction('Exit', self) action_exit.setShortcut(QKeySequence.Quit) action_exit.triggered.connect(self.close) self.menu_file.addAction(action_exit) # window dimensions # geometry = qApp.desktop().availableGeometry(self) # self.setFixedSize(geometry.width() * 0.5, geometry.height() * 0.5) def load_data(self) -> None: filename, _ = QFileDialog.getOpenFileName(self, "Load data", dir="./tests", filter="Text files (*.txt);;Excel data (*csv)") if filename: country_data: CountryData = read_data(filename) self.model = CustomTableModel(country_data) self.table_view.setModel(self.model) self.statusBar().showMessage("Data loaded and plotted") self.draw_diagram() def load_svg(self, filename) -> None: self.widget_svg.load(filename) def draw_diagram(self) -> None: n_countries: int = self.model.rowCount() if n_countries > 0: style: SvgStyle = self.svg_style delta_angle: float = 2.0*math.pi/n_countries max_value: float = max(self.model.values) dwg = Drawing(self.temp_svg_file.fileName(), profile='tiny', viewBox='-250 -250 500 500') for idx, v in enumerate(self.model.values): x: float = style.line_length * v/max_value * math.sin(idx * delta_angle) y: float = -style.line_length * v/max_value * math.cos(idx * delta_angle) dwg.add(shapes.Line(start=(0, 0), end=(x, y), stroke=style.line_color, stroke_width=style.line_width)) radius: float = style.circle_rad if style.circle_rad_normalization: radius *= v/max_value dwg.add(shapes.Circle(center=(x, y), r=radius, stroke=style.circle_stroke_color, stroke_width=style.circle_stroke_width, fill=style.circle_fill_color)) dwg.save(pretty=True) self.load_svg(self.temp_svg_file.fileName()) @Slot() def style_updated(self, style: SvgStyle): self.svg_style = style self.draw_diagram()
class MainWindow(QWidget): """ Main UI Window """ def __init__(self, parent=None): """ Initialize the chess board. """ super().__init__(parent) ## NN param set self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print('Processing device: ',self.device) self.path = "best_policy.model" self.learning_rate = 0.0001 self.mcts_iteration = 100 #self.Chess_read = CHESS_READ() ## self.setWindowTitle("GrandmasterFLEX") self.resize(1280, 720) self.svgWidget = QSvgWidget(parent=self) self.svgWidget.setGeometry(10, 10, 700, 700) self.boardSize = min(self.svgWidget.width(), self.svgWidget.height()) self.margin = 0.05 * self.boardSize self.squareSize = (self.boardSize - 2*self.margin)/8 self.board = chess.Board() self.lastmove = None self.pieceToMove = [None, None] self.drawBoard() self.enginePath = "./stockfish.exe" self.time = 0.1 self.pbar = QProgressBar(self) self.pbarlabel = QLabel('Training Progress: ') self.maxtimelabel = QLabel("Max number of examples from ./Training Games") self.engineLabel = QLabel("Selfplay games#") self.engineButton = QPushButton("Find move") self.moveButton = QPushButton("Make move") self.undoButton = QPushButton("Undo move") self.testButton = QPushButton("Selfplay") self.gendataButton = QPushButton("Generate Dataset") self.trainButton = QPushButton("Train AI") self.newgameButton = QPushButton("New Game") self.undoButton.setMaximumWidth(175) self.pathField = QLineEdit() self.pathField1 = QLabel("0") self.examples = QLineEdit() self.engineResult = QLineEdit() self.pathField.setText("5") self.examples.setText('10000000') self.pbar.setValue(0) self.main_layout = QHBoxLayout() self.tool_layout = QGridLayout() ### widget design ##QT top row self.tool_layout.addWidget(self.engineLabel, 0, 0) self.tool_layout.addWidget(self.pathField, 0, 1) self.tool_layout.addWidget(self.pathField1, 0, 2) self.tool_layout.addWidget(self.testButton, 0, 3) #second row self.tool_layout.addWidget(self.maxtimelabel, 1, 0) self.tool_layout.addWidget(self.examples, 1, 1) self.tool_layout.addWidget(self.gendataButton, 1, 2) self.tool_layout.addWidget(self.trainButton, 1, 3) #third row self.tool_layout.addWidget(self.pbarlabel, 2, 0) self.tool_layout.addWidget(self.pbar, 2, 1) #4th row self.tool_layout.addWidget(self.engineButton, 3, 0) self.tool_layout.addWidget(self.moveButton, 3, 1) self.tool_layout.addWidget(self.engineResult, 3, 2) self.tool_layout.addWidget(self.undoButton, 3, 3) self.tool_layout.addWidget(self.newgameButton, 3, 4) ### self.main_layout.addWidget(self.svgWidget, 55) self.main_layout.addLayout(self.tool_layout, 45) self.setLayout(self.main_layout) self.engineButton.clicked.connect(self.find_move) self.moveButton.clicked.connect(self.make_move) self.undoButton.clicked.connect(self.undo_move) self.testButton.clicked.connect(self.selfplay) self.gendataButton.clicked.connect(self.gendata) self.trainButton.clicked.connect(self.trainnet) self.newgameButton.clicked.connect(self.newgame) #self.NN = NEURAL_NETWORK(self.learning_rate, self.path, self.device) #self.mcts_tree = MCTS(self.mcts_iteration, self.NN, self.Chess_read, self.device) def updarepbar(epoch1): self.pbar.setValue(epoch1) def gendata(self): numexamples = int(self.examples.text()) gendata.get_dataset(numexamples) print(colored('Model saved','green')) def trainnet(self): with open("train.py") as f: code = compile(f.read(), "train.py", 'exec') exec(code) def selfplay(self): x = self.pathField.text() if x == '': print('no games') return else: self.itr = 1 while self.itr <= int(x): while not self.board.is_game_over(): self.pathField1.setText('#games played: '+ str(self.itr)) go = self.make_move() if go =='gameover': self.post() self.itr += 1 return print("GAME OVER: game: ",str(self.itr)) self.newgame() def newgame(self): moves = [] x1 = np.array([0]) y1 = np.array([0]) viz.line(x1,y1,update='replace',opts=layoutb,name='GrandmasterFlex - BLACK',win='GrandmasterFlex3') viz.line(x1,y1,update='replace',opts=layoutw,name='GrandmasterFlex - WHITE',win='GrandmasterFlex2') self.board.reset() s.board.reset() with open('si.pickle', 'wb') as p: pickle.dump(s, p) i = 0 with open('rnd.pickle','wb') as rnd: pickle.dump(i,rnd) with open('g.pickle','wb')as g: moves = [] pickle.dump(moves, g) @Slot(QWidget) def mousePressEvent(self, event): """ Handles the left mouse click and enables moving the chess pieces by first clicking on the chess piece and then on the target square. """ if not self.board.is_game_over(): if event.x() <= self.boardSize and event.y() <= self.boardSize: if self.margin<event.x()<self.boardSize-self.margin and self.margin<event.y()<self.boardSize-self.margin: if event.buttons()==Qt.LeftButton: 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) s.board.push(move) self.lastmove = str(self.pieceToMove[1]) + str(coordinates) print('Last Move: ',self.lastmove) piece = None coordinates = None with open('rnd.pickle','rb') as rnd: i = pickle.load(rnd) i = 1 + i with open('rnd.pickle','wb') as rnd: pickle.dump(i,rnd) print(colored("move: " + str(i),'yellow')) self.pieceToMove = [piece, coordinates] self.drawBoard() go = self.make_move() if go == 'gameover': print(colored(Style.BRIGHT + "********************* GAME IS OVER *********************",'red')) self.post() def drawBoard(self): """ Draw a chess board for the starting position and then redraw it for every move. """ self.svgBoard = self.board._repr_svg_().encode("UTF-8") self.svgDrawBoard = self.svgWidget.load(self.svgBoard) return self.svgDrawBoard def find_move(self,lastmove): """ Calculate the best move according to Stockfish """ #spinner = Halo(text='SEARCHING MINDSTATE',text_color='cyan', spinner='simpleDotsScrolling',color='cyan') #spinner.start() with open('si.pickle', 'rb') as f: s = pickle.load(f) try: times = float(self.engineTime.text()) except: times = float(1) self.time = times #engine = chess.engine.SimpleEngine.popen_uci(self.enginePath) #result = engine.play(self.board, chess.engine.Limit(time=self.time)) print(self.board,'\n',self.lastmove) #move, prob = self.mcts_tree.play(self.board, self.lastmove) move,s,prob = computer_move(s, v) self.engineResult.setText(str(move)) #engine.quit() #spinner.stop() return move,s, prob def make_move(self): """ Finds and plays the best move """ try: with open('rnd.pickle','rb') as rnd: i = pickle.load(rnd) i = 1 + i except: i = 0 with open('rnd.pickle','wb') as rnd: pickle.dump(i,rnd) try: move,s,prob = self.find_move(self.lastmove) print(colored('move: ' + str(i),'yellow')) if (i % 2) == 0: prob1 = np.array([float(prob)]) i1 = np.array([(i/2)]) #viz.line(prob1,i1,update='append',opts=layoutb,name='GrandmasterFlex - BLACK',win='GrandmasterFlex3') plotter.plot('Round', 'Prob', 'Win Probability - Black' , i1, prob) else: prob1 = np.array([float(prob)]) i1 = np.array([(i/2)]) #viz.line(prob1,i1,update='append',opts=layoutw,name='GrandmasterFlex - WHITE',win='GrandmasterFlex2') plotter.plot('Round', 'Prob', 'Win Probability - White' , i1, prob) #print(move) nf3 = chess.Move.from_uci(move) #print('uci eq: ',nf3) #x = input('waiting') with open('g.pickle','rb')as g: moves = pickle.load(g) moves.append(move) with open('g.pickle','wb')as g: pickle.dump(moves, g) print(colored(moves,'cyan')) self.board.push(nf3) s.board.push(nf3) self.drawBoard() time.sleep(0.2) QApplication.processEvents() self.lastmove = move with open('si.pickle', 'wb') as p: pickle.dump(s, p) except: print(colored(Style.BRIGHT + "********************* GAME IS OVER *********************",'red')) #self.post() return 'gameover' def undo_move(self): """ Undo the last move played on the board """ self.board.pop() s = self self.drawBoard() def post(self): game = chess.pgn.Game() game.headers["Event"] = "GMFLEX" game.headers["Site"] = "local" game.headers["Date"] = datetime.now() game.headers["White"] = "White" game.headers["Black"] = "Black" with open('g.pickle','rb')as g: moves = pickle.load(g) i = 0 for move in moves: i += 1 if i == 1: print(move) node = game.add_variation(chess.Move.from_uci(move)) else: node = node.add_variation(chess.Move.from_uci(move)) with open('si.pickle', 'rb') as f: si = pickle.load(f) b = si.board # game over values if b.result() == "1-0": game.headers["Result"] = "1-0" winner = "WHITE" elif b.result() == "0-1": game.headers["Result"] = "0-1" winner = "BLACK" else: winner = "BLACK" win = open('winner.txt', 'a') stamp = str(datetime.now()).replace(":","_") log = open('TrainingGames/'+ stamp +".pgn", 'w') print(game, file=log, end="\n\n") try: sgame = "Final Board:\n" + str(game) except: print(colored(Style.BRIGHT + "Save Game Fail",'red')) win.write(winner + ":\n" + sgame) if winner == "BLACK": res1 = 0 res2 = 1 else: res1 = 1 res2 = 0 with open('w.pickle','rb')as w: wins = pickle.load(w) win1 = pd.DataFrame({'W':[res1],'B':[res2],'Winner':[winner]}) pd.DataFrame.append(wins,win1) with open('w.pickle','wb')as w: pickle.dump(wins,w) with open('rnd.pickle','wb') as rnd: pickle.dump(i,rnd) with open('g.pickle','wb')as g: moves = [] pickle.dump(moves, g) def update(self): """Update the gui with the current value.""" self.drawBoard()
class MainWindow(QWidget): """ Main UI Window """ def __init__(self, parent=None): """ Initialize the chess board. """ super().__init__(parent) self.setWindowTitle("PyChess") self.resize(1280, 720) self.svgWidget = QSvgWidget(parent=self) self.svgWidget.setGeometry(10, 10, 700, 700) self.boardSize = min(self.svgWidget.width(), self.svgWidget.height()) self.margin = 0.05 * self.boardSize self.squareSize = (self.boardSize - 2 * self.margin) / 8 self.board = chess.Board() self.pieceToMove = [None, None] self.drawBoard() self.enginePath = "Use double \ instead of \ when on Windows system." self.time = 0.1 self.maxtimelabel = QLabel("Max. time per move(in s):") self.engineLabel = QLabel("Enter path to engine:") self.engineButton = QPushButton("Find move") self.moveButton = QPushButton("Make move") self.undoButton = QPushButton("Undo move") self.undoButton.setMaximumWidth(175) self.pathField = QLineEdit() self.engineTime = QLineEdit() self.engineResult = QLineEdit() self.pathField.setText( "Use double \ instead of \ when on Windows system.") self.main_layout = QHBoxLayout() self.tool_layout = QGridLayout() self.tool_layout.addWidget(self.engineLabel, 0, 0) self.tool_layout.addWidget(self.pathField, 0, 1) self.tool_layout.addWidget(self.maxtimelabel, 1, 0) self.tool_layout.addWidget(self.engineTime, 1, 1) self.tool_layout.addWidget(self.engineButton, 2, 0) self.tool_layout.addWidget(self.engineResult, 2, 1) self.tool_layout.addWidget(self.moveButton, 3, 0) self.tool_layout.addWidget(self.undoButton, 3, 1) self.main_layout.addWidget(self.svgWidget, 55) self.main_layout.addLayout(self.tool_layout, 45) self.setLayout(self.main_layout) self.engineButton.clicked.connect(self.find_move) self.moveButton.clicked.connect(self.make_move) self.undoButton.clicked.connect(self.undo_move) @Slot(QWidget) def mousePressEvent(self, event): """ Handles the left mouse click and enables moving the chess pieces by first clicking on the chess piece and then on the target square. """ if event.x() <= self.boardSize and event.y() <= self.boardSize: if self.margin < event.x( ) < self.boardSize - self.margin and self.margin < event.y( ) < self.boardSize - self.margin: if event.buttons() == Qt.LeftButton: 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 chess board for the starting position and then redraw it for every move. """ self.svgBoard = self.board._repr_svg_().encode("UTF-8") self.svgDrawBoard = self.svgWidget.load(self.svgBoard) return self.svgDrawBoard def find_move(self): """ Calculate the best move according to Stockfish """ self.enginePath = self.pathField.text() self.time = float(self.engineTime.text()) engine = chess.engine.SimpleEngine.popen_uci(self.enginePath) result = engine.play(self.board, chess.engine.Limit(time=self.time)) self.engineResult.setText(str(result.move)) engine.quit() return result.move def make_move(self): """ Finds and plays the best move """ move = self.find_move() self.board.push(move) self.drawBoard() def undo_move(self): """ Undo the last move played on the board """ self.board.pop() self.drawBoard()