首页 > 解决方案 > 多次运行和退出 PyQt 应用程序

问题描述

上下文

我正在使用 PyQt创建自己的棋盘游戏Battleship版本。PyQt 主窗口包含自己的和敌人的板。棋盘由玩家“开火”的可点击图块组成。该实现支持 HUMANvsAI 和 AIvsAI 游戏。我想通过模拟测试我的人工智能算法的强度。例如,我想循环运行 1,000 场 AIvsAI 游戏,并获得胜利百分比、平均准确率等的统计数据。游戏截图

主要问题

我正在努力多次运行 PyQt 应用程序以收集游戏数据,例如在 for 循环中。具体来说,我找不到运行应用程序、退出它并重新运行它的方法。从概念上讲,我正在寻找这样的东西:

# conceptual snippet
  for i in range(n):
    app = QApplication([])
    window = MainWindow(b_size, boat_dict, players)
    app.exec_()

调用退出应用程序并在每次游戏结束时调用:

# conceptual snippet
  if is_game_over():
    sys.exit(app.exec_())

但是这个简单的解决方案打破了 for 循环。欢迎任何关于如何多次运行和退出 PyQt 应用程序的反馈,无论是顺序(例如 for 循环方法)还是并行线程。

标签: pythonloopsfor-looppyqtpyqt5

解决方案


您不应该使用sys.exit()该指令,因为该指令用于终止程序的执行,如果您想终止您必须使用的 Qt 应用程序QCoreApplication::quit()(或QCoreApplication::exit(0))。此外,另一个改进是使用多处理:

import random
from multiprocessing import Pool

from PyQt5 import QtCore, QtWidgets


def create_app(i):
    app = QtWidgets.QApplication([])
    w = QtWidgets.QMainWindow()
    w.setWindowTitle("Game-{}".format(i))
    w.show()

    # emulate end-game
    def end_game():
        QtCore.QCoreApplication.quit()

    timeout = random.randint(1000, 2000)  # 1000-2000 milliseconds
    QtCore.QTimer.singleShot(timeout, end_game)
    app.exec_()

    # emulate results
    o = {"victory": random.randint(0, 101), "average": random.randint(0, 101)}
    return o


def main():
    results = []
    pool = Pool(processes=8)
    for i in range(1000):
        r = pool.apply_async(create_app, args=(i,))
        results.append(r)
    pool.close()
    pool.join()
    print([result.get() for result in results])


if __name__ == "__main__":
    main()

推荐阅读