繁体   English   中英

PySimpleGUI 冻结

[英]PySimpleGUI Freezes

我在带有 PySimpleGui 4.15.1 的 python 3.8.1 中的游戏冷拳击模拟器 2 中编写了一个黑客代码,如果我尝试单击开始/停止按钮,gui 冻结但脚本与开始/停止按钮连接仍在运行。 但是,如果我将连接到“开始/停止”按钮的脚本更改为 Print('Chicken') 之类的东西,那么它完全可以完美运行

这是代码:

import PySimpleGUI as sg
import ctypes
import time
import pynput

sg.theme('DarkBrown1')

layout = [  [sg.Text('BOXING SIMULATOR 2 HACK', size=(20, 2), justification='center')],
            [sg.Text('', size=(10, 2), font=('Helvetica', 20), justification='center', key='_OUTPUT_')],
            [sg.T(' ' * 5), sg.Button('Start/Stop', focus=True), sg.Quit()]]

window = sg.Window('BOXING SIMULATOR 2 HACK', layout)

SendInput = ctypes.windll.user32.SendInput

PUL = ctypes.POINTER(ctypes.c_ulong)
class KeyBdInput(ctypes.Structure):
    _fields_ = [("wVk", ctypes.c_ushort),
                ("wScan", ctypes.c_ushort),
                ("dwFlags", ctypes.c_ulong),
                ("time", ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class HardwareInput(ctypes.Structure):
    _fields_ = [("uMsg", ctypes.c_ulong),
                ("wParamL", ctypes.c_short),
                ("wParamH", ctypes.c_ushort)]

class MouseInput(ctypes.Structure):
    _fields_ = [("dx", ctypes.c_long),
                ("dy", ctypes.c_long),
                ("mouseData", ctypes.c_ulong),
                ("dwFlags", ctypes.c_ulong),
                ("time",ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class Input_I(ctypes.Union):
    _fields_ = [("ki", KeyBdInput),
                 ("mi", MouseInput),
                 ("hi", HardwareInput)]

class Input(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("ii", Input_I)]


def PressKeyPynput(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = pynput._util.win32.INPUT_union()
    ii_.ki = pynput._util.win32.KEYBDINPUT(0, hexKeyCode, 0x0008, 0, ctypes.cast(ctypes.pointer(extra), ctypes.c_void_p))
    x = pynput._util.win32.INPUT(ctypes.c_ulong(1), ii_)
    SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

def ReleaseKeyPynput(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = pynput._util.win32.INPUT_union()
    ii_.ki = pynput._util.win32.KEYBDINPUT(0, hexKeyCode, 0x0008 | 0x0002, 0, ctypes.cast(ctypes.pointer(extra), ctypes.c_void_p))
    x = pynput._util.win32.INPUT(ctypes.c_ulong(1), ii_)
    SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))


HACK_running, counter = False, 0

while True:                                 
    event, values = window.read(timeout=10) 
    if event in (None, 'Quit'):            
        break
    elif event == 'Start/Stop':
        HACK_running = not HACK_running
    if HACK_running:
            PressKeyPynput(0x02)
            time.sleep(0.08)
            ReleaseKeyPynput(0x02)
            PressKeyPynput(0x11)
            time.sleep(0.5)
            ReleaseKeyPynput(0x11)
            PressKeyPynput(0x1F)
            time.sleep(0.6)
            ReleaseKeyPynput(0x1F)
            PressKeyPynput(0x02)
            time.sleep(0.08)
            ReleaseKeyPynput(0x02)
            time.sleep(300)

如果没有某种刷新或读取操作,您将无法在 GUI 中执行真正长时间运行的任务。

我回答了与此相同的上一篇文章,指出问题在于永远不会退出的内部 while 循环。

如果您必须让内部循环永远执行,那么您至少需要刷新 GUI。 您可以通过调用window.refresh来执行此操作,如下所示。

while True:                                 
    event, values = window.read(timeout=10) 
    if event in (None, 'Quit'):            
        break
    elif event == 'Start/Stop':
        HACK_running = not HACK_running
    if HACK_running:
            PressKeyPynput(0x02)
            time.sleep(0.08)
            ReleaseKeyPynput(0x02)
            PressKeyPynput(0x11)
            time.sleep(0.5)
            ReleaseKeyPynput(0x11)
            PressKeyPynput(0x1F)
            time.sleep(0.6)
            ReleaseKeyPynput(0x1F)
            PressKeyPynput(0x02)
            time.sleep(0.08)
            ReleaseKeyPynput(0x02)
            time.sleep(300)
            window.refresh()

您永远不应该在 PySimpleGUI 事件循环中全部休眠。

更好的方法是调用window.read(timeout=400)而不是time.sleep(0.4) 这将使操作系统不会认为您的程序已挂起。


[编辑 2022 年 7 月]

提醒读者,PySimpleGUI 与许多项目一样,是活跃的并且在不断发展。 在 StackOverflow 上找到的答案特别危险,因为它们永远不会“死亡”......也没有“关闭”状态......或指定“不再推荐”

几年前提供的一些关于 PySimpleGUI 的答案现在根本不是推荐的执行相同操作的方法。 发生了很大的变化... PySimpleGUI Windows 可以更加动态化,有一整套 API 用于处理子进程,另一组新的 API 有助于管理 JSON 和 INI 文件,还有一个是线程支持。

对于这个问题,我不再推荐如下所示的“轮询”解决方案。 现在我将启动一个线程并让window.read()调用不再有超时。 轮询是一种非常非常浪费的架构。 如果可能的话,不要使用超时......而是依靠发生某事时发生的事件。 在嵌入式系统中,这被称为“中断驱动”,并且由于多种原因是比“轮询”更好的解决方案。

您要研究的方法是:|

  • Window.start_thread
  • Window.window.write_event_value

##imports 你需要添加##

导入线程

为函数创建线程被冻结

thread1 = threading.Thread(target= your_func)

从循环中调用线程

线程1.start()

为我解决问题 GL

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM