PySide2/Qt for python : 当我点击按钮时 GUI 冻结

PySide2/Qt for python : The GUI freezes when i click the button

我为英雄联盟制作了一个自动接受队列程序。但是当我点击按钮时 GUI 冻结了。该按钮连接到函数队列。我猜 while 循环是问题所在。因为它在没有 while 循环的情况下有效。

import pyautogui as pag
import time
import telegram
import sys
from PySide2.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QPushButton, QSizePolicy, QLabel, QApplication
from PySide2.QtCore import *

# telegram

api_key = "xxxxxxxx"

bot = telegram.Bot(token = api_key)

chat_id = 111111111

# PySide2

class Form(QWidget):
    def __init__(self):
        super(Form, self).__init__()
        self.setWindowTitle("Auto Accept Queue-1.0.0")
        self.resize(480, 270)

        self.vb = QVBoxLayout()
        self.hbMid = QHBoxLayout()
        self.gl = QGridLayout()

        self.vb.addStretch()
        self.vb.addLayout(self.hbMid)
        self.vb.addStretch()

        self.hbMid.addStretch()
        self.hbMid.addLayout(self.gl)
        self.hbMid.addStretch()

        self.btn = QPushButton("자동 수락 시작")
        self.btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.btn.setFixedSize(140, 80)
        self.btn.setStyleSheet("font-size: 16px; font-family: 맑은 고딕;")
        self.lblHotkey = QLabel("단축키 : F8")
        self.lblHotkey.setAlignment(Qt.AlignCenter)
        self.lblHotkey.setStyleSheet("font-size: 14px; font-family: 맑은 고딕;")

        self.gl.addWidget(self.btn, 0, 0)
        self.gl.addWidget(self.lblHotkey, 2, 0)

        self.btn.clicked.connect(self.queue)

        self.setLayout(self.vb)

    def queue(self):
        self.btn.setText("자동 수락 중...")
        while 1:
            i = pag.locateCenterOnScreen("img.png")
            if i:
                pag.click(i)
                print("Accepted queue! The program will exit.")
                bot.sendMessage(chat_id=chat_id, text="Accepted queue!")
                break
            else:
                time.sleep(1)
                print("Accepting queue...")

if __name__ == '__main__':
    app = QApplication([])
    form = Form()
    form.show()
    sys.exit(app.exec_())

问题是在"queue"方法中执行的循环消耗了大量时间,导致GUI无法正常工作,解决方法是在另一个线程中执行:

import sys
import threading
import time

from PySide2.QtWidgets import (
    QWidget,
    QVBoxLayout,
    QHBoxLayout,
    QGridLayout,
    QPushButton,
    QSizePolicy,
    QLabel,
    QApplication,
)
from PySide2.QtCore import Qt

import pyautogui as pag

import telegram


api_key = "xxxxxxxx"
bot = telegram.Bot(token=api_key)
chat_id = 111111111


def process():
    while True:
        i = pag.locateCenterOnScreen("img.png")
        if i:
            pag.click(i)
            print("Accepted queue! The program will exit.")
            bot.sendMessage(chat_id=chat_id, text="Accepted queue!")
            break
        else:
            time.sleep(1)
            print("Accepting queue...")


class Form(QWidget):
    def __init__(self):
        super(Form, self).__init__()
        self.setWindowTitle("Auto Accept Queue-1.0.0")
        self.resize(480, 270)

        self.vb = QVBoxLayout(self)
        self.hbMid = QHBoxLayout()
        self.gl = QGridLayout()

        self.vb.addStretch()
        self.vb.addLayout(self.hbMid)
        self.vb.addStretch()

        self.hbMid.addStretch()
        self.hbMid.addLayout(self.gl)
        self.hbMid.addStretch()

        self.btn = QPushButton("자동 수락 시작")
        self.btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.btn.setFixedSize(140, 80)
        self.btn.setStyleSheet("font-size: 16px; font-family: 맑은 고딕;")
        self.lblHotkey = QLabel("단축키 : F8")
        self.lblHotkey.setAlignment(Qt.AlignCenter)
        self.lblHotkey.setStyleSheet("font-size: 14px; font-family: 맑은 고딕;")

        self.gl.addWidget(self.btn, 0, 0)
        self.gl.addWidget(self.lblHotkey, 2, 0)

        self.btn.clicked.connect(self.queue)

    def queue(self):
        self.btn.setText("자동 수락 중...")
        threading.Thread(target=process, daemon=True).start()


if __name__ == "__main__":
    app = QApplication([])
    form = Form()
    form.show()
    sys.exit(app.exec_())