如何在 PyQt5 中更新窗口



我正在尝试使用 PyQt5 编写深度优先递归回溯迷宫生成器。从功能上讲,一切正常,但并非所有内容都已实现,因此结果可能看起来很奇怪:)。我应该说我对Python和PyQt很陌生。我在图形更新时遇到了问题。我希望窗口根据算法的结果更新图形,该算法在 App 类go函数中的while循环中运行。我做了一些研究,但没有任何效果。人们告诉我只添加像self.show()self.update()这样的行,但这些都不起作用。

我知道我可能在概念上做错了什么,例如,我应该将代码的某些部分放在其他地方,或者类似的东西。或者也许有一两行可以放在某个地方以使其工作。

无论哪种情况,请帮助我。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow
from PyQt5.QtGui import QPainter, QPen, QColor
from PyQt5.QtCore import *
import math
import random
import pygame
w = 40
grid = []
qp = QPainter()
clock = pygame.time.Clock()
class Cell(QMainWindow):
    def __init__(self, i, j):
        # super().__init__()
        self.i = i
        self.j = j
        self.walls = [1, 1, 1, 1]  # top, right, bottom, left
        self.visited = 0
        self.currentCell = 0
    def index(self, i, j, cols, rows):
        if (i < 0) or (j < 0) or (i > (cols - 1)) or (j > (rows - 1)):
            return None
        else:
            return i + j * cols
    def checkNeighbors(self, cols, rows):
        neighbors = []
        if not (self.index(self.i, self.j - 1, cols, rows) is None):
            top    = grid[self.index(self.i, self.j - 1, cols, rows)]
        if not (self.index(self.i + 1, self.j, cols, rows) is None):
            right  = grid[self.index(self.i + 1, self.j, cols, rows)]
        if not (self.index(self.i, self.j + 1, cols, rows) is None):
            bottom = grid[self.index(self.i, self.j + 1, cols, rows)]
        if not (self.index(self.i - 1, self.j, cols, rows) is None):
            left   = grid[self.index(self.i - 1, self.j, cols, rows)]
        if 'top' in locals() and not top.visited:
            neighbors.append(top)
        if 'right' in locals() and not right.visited:
            neighbors.append(right)
        if 'bottom' in locals() and not bottom.visited:
            neighbors.append(bottom)
        if 'left' in locals() and not left.visited:
            neighbors.append(left)
        if neighbors.__len__() > 0:
            r = math.floor(random.uniform(0, neighbors.__len__()))
            return neighbors[r]
        else:
            return None

class App(QWidget):
    def __init__(self):
        super().__init__()
        self.left = 100
        self.top = 100
        self.width = 400
        self.height = 400
        self.cols = math.floor(self.width/w)
        self.rows = math.floor(self.height/w)
        self.init_cells()
        self.initui()
        self.go()
    def init_cells(self):
        for j in range(self.rows):
            for i in range(self.cols):
                cell = Cell(i, j)
                grid.append(cell)
    def go(self):
        current = grid[0]
        current.visited = 1
        current.currentCell = 1
        next = current.checkNeighbors(self.cols, self.rows)
        while not (next is None):
            next = current.checkNeighbors(self.cols, self.rows)
            if not (next is None):
                next.visited = 1
                next.currentCell = 1
                current.currentCell = 0
                current = next
            # I WANT TO UPDATE WINDOW HERE!
    def initui(self):
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.lightGray)
        self.setPalette(p)
        self.show()
    def paintEvent(self, e):
        for i in grid:
            self.draw_cell(i)
        self.show()
    def draw_cell(self, cell):
        x = cell.i*w
        y = cell.j*w
        # LINES
        qp.begin(self)
        qp.setPen(QPen(Qt.black, 1, Qt.SolidLine))
        if cell.walls[0]:  # top
            qp.drawLine(x    , y    , x + w, y)
        if cell.walls[1]:  # right
            qp.drawLine(x + w, y    , x + w, y + w)
        if cell.walls[2]:  # bottom
            qp.drawLine(x + w, y + w, x    , y + w)
        if cell.walls[3]:  # left
            qp.drawLine(x    , y + w, x    , y)
        if cell.visited:
            qp.setBrush(QColor(255, 0, 255, 100))
            qp.drawRect(x, y, w, w)
            if cell.currentCell:
                qp.setBrush(QColor(0, 255, 0, 255))
                qp.drawRect(x, y, w, w)
        qp.end()
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

下面是一个脚本版本,展示了如何使用QApplication.processEvents、计时器和睡眠来制作一些简单的动画。我冒昧地添加了用于开始新运行的 F5 快捷方式,并整理了其他一些内容:

import sys, math, random
from PyQt5.QtWidgets import QApplication, QWidget, QShortcut
from PyQt5.QtGui import QPainter, QPen, QColor, QKeySequence
from PyQt5.QtCore import Qt, QTimer, QThread
WIDTH = 40
grid = []
class Cell():
    def __init__(self, i, j):
        self.i = i
        self.j = j
        self.walls = [1, 1, 1, 1]  # top, right, bottom, left
        self.visited = 0
        self.currentCell = 0
    def index(self, i, j, cols, rows):
        if (i < 0) or (j < 0) or (i > (cols - 1)) or (j > (rows - 1)):
            return None
        else:
            return i + j * cols
    def checkNeighbors(self, cols, rows):
        neighbors = []
        if not (self.index(self.i, self.j - 1, cols, rows) is None):
            top    = grid[self.index(self.i, self.j - 1, cols, rows)]
        if not (self.index(self.i + 1, self.j, cols, rows) is None):
            right  = grid[self.index(self.i + 1, self.j, cols, rows)]
        if not (self.index(self.i, self.j + 1, cols, rows) is None):
            bottom = grid[self.index(self.i, self.j + 1, cols, rows)]
        if not (self.index(self.i - 1, self.j, cols, rows) is None):
            left   = grid[self.index(self.i - 1, self.j, cols, rows)]
        if 'top' in locals() and not top.visited:
            neighbors.append(top)
        if 'right' in locals() and not right.visited:
            neighbors.append(right)
        if 'bottom' in locals() and not bottom.visited:
            neighbors.append(bottom)
        if 'left' in locals() and not left.visited:
            neighbors.append(left)
        if len(neighbors) > 0:
            r = math.floor(random.uniform(0, len(neighbors)))
            return neighbors[r]
        else:
            return None

class App(QWidget):
    def __init__(self):
        super().__init__()
        self.left = 100
        self.top = 100
        self.width = 400
        self.height = 400
        self.cols = math.floor(self.width / WIDTH)
        self.rows = math.floor(self.height / WIDTH)
        self.active = False
        self.initui()
        self.init_cells()
    def init_cells(self):
        if not self.active:
            del grid[:]
            for j in range(self.rows):
                for i in range(self.cols):
                    cell = Cell(i, j)
                    grid.append(cell)
            QTimer.singleShot(1, self.go)
    def go(self):
        self.active = True
        current = grid[0]
        current.visited = 1
        current.currentCell = 1
        while True:
            self.update()
            QApplication.processEvents()
            QThread.msleep(150)
            next = current.checkNeighbors(self.cols, self.rows)
            if next is not None:
                next.visited = 1
                next.currentCell = 1
                current.currentCell = 0
                current = next
            else:
                break
        self.active = False
    def initui(self):
        QShortcut(QKeySequence('F5'), self, self.init_cells)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.lightGray)
        self.setPalette(p)
        self.show()
    def paintEvent(self, e):
        for i in grid:
            self.draw_cell(i)
    def draw_cell(self, cell):
        x = cell.i * WIDTH
        y = cell.j * WIDTH
        # LINES
        qp = QPainter(self)
        qp.setPen(QPen(Qt.black, 1, Qt.SolidLine))
        if cell.walls[0]:  # top
            qp.drawLine(x    , y    , x + WIDTH, y)
        if cell.walls[1]:  # right
            qp.drawLine(x + WIDTH, y    , x + WIDTH, y + WIDTH)
        if cell.walls[2]:  # bottom
            qp.drawLine(x + WIDTH, y + WIDTH, x    , y + WIDTH)
        if cell.walls[3]:  # left
            qp.drawLine(x    , y + WIDTH, x    , y)
        if cell.visited:
            if cell.currentCell:
                qp.setBrush(QColor(0, 255, 0, 255))
            else:
                qp.setBrush(QColor(255, 0, 255, 100))
            qp.drawRect(x, y, WIDTH, WIDTH)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

相关内容

  • 没有找到相关文章

最新更新