< Сильный > [ ПРОБЛЕМА ] Если я нажму на кнопку, которая запускает функцию, графический интерфейс будет зависать, пока функция не завершится.

< Сильный > [ CODE ]

import wx
app = wx.App(redirect=False)
top = wx.Frame(None)
top.Maximize(True) # Set to maximize the application
sizer = wx.GridBagSizer()

def testFunction(event):
    import pyautogui
    import time
    pyautogui.FAILSAFE = False
    for i in range(2):
            pyautogui.hotkey('win','r')
            time.sleep (0.5)
            pyautogui.typewrite('cmd.exe')
            time.sleep (0.5)
            pyautogui.hotkey('enter')
            time.sleep (0.5)
            time.sleep (3)


addButton = wx.Button( top, -1, "Start", style=wx.BU_EXACTFIT )
sizer.Add(addButton, (6, 8), (2, 14), wx.EXPAND)
top.Bind(wx.EVT_BUTTON, testFunction, addButton)
top.Sizer = sizer
top.Sizer.Fit(top)
top.Show()
app.MainLoop()

[CURRENT] графический интерфейс останавливается до тех пор, пока функция не завершится.

[Желаемый] Gui не должен зависать. Примечание: я думаю, что это связано с потоками, но я не могу полностью понять эту концепцию.

1
george 14 Дек 2015 в 15:22

3 ответа

Лучший ответ

Ну, это сработало для меня:

# -*- coding: utf-8 -*-
import wx
app = wx.App(redirect=False)
top = wx.Frame(None)
top.Maximize(False) # Set to maximize the application
sizer = wx.GridBagSizer()

def testFunction(event):
    import time
    for i in range(2):
        print ('win','r')
        time.sleep (0.5)
        print ('cmd.exe')
        time.sleep (0.5)
        print ('enter')
        time.sleep (0.5)
        print 'sleep'
        time.sleep (3)
        print u"Iteración %d".format(i+1)

def thread_start(event):
    import threading
    th = threading.Thread(target=testFunction, args=(event,))
    th.start()



addButton = wx.Button( top, -1, "Start", style=wx.BU_EXACTFIT )
sizer.Add(addButton, (6, 8), (2, 14), wx.EXPAND)
# top.Bind(wx.EVT_BUTTON, testFunction, addButton)
top.Bind(wx.EVT_BUTTON, thread_start, addButton)
top.Sizer = sizer
top.Sizer.Fit(top)
top.Show()
app.MainLoop()

У вас есть неблокирующий графический интерфейс. Вы можете начать с этого и добавить входные переменные (например, получить и идентифицировать ваш поток, чтобы вы могли определить, какой поток вызывается).

Я удалил библиотеку py2autogui, потому что она не установлена (и не нужна для примера).

1
tglaria 14 Дек 2015 в 13:09

Я не очень знаком с бывшим, но, возможно, это помогает

import wx
import threading
app = wx.App(redirect=False)
top = wx.Frame(None)
top.Maximize(True) # Set to maximize the application
sizer = wx.GridBagSizer()

def testFunction(event):
    import pyautogui
    import time
    pyautogui.FAILSAFE = False
    for i in range(2):
            pyautogui.hotkey('win','r')
            time.sleep (0.5)
            pyautogui.typewrite('cmd.exe')
            time.sleep (0.5)
            pyautogui.hotkey('enter')
            time.sleep (0.5)
            time.sleep (3)

t1 = threading.Thread(target=testFunction, args=[])    

addButton = wx.Button( top, -1, "Start", style=wx.BU_EXACTFIT )
sizer.Add(addButton, (6, 8), (2, 14), wx.EXPAND)
top.Bind(wx.EVT_BUTTON, t1, addButton)
top.Sizer = sizer
top.Sizer.Fit(top)
top.Show()
app.MainLoop()
-1
IDontEven 14 Дек 2015 в 12:44

Используйте wx.CallLater, который будет вызывать данный вызываемый объект с аргументом по истечении указанного времени. Структура функции testFunction должна быть изменена:

def testFunction(event):
    import pyautogui
    pyautogui.FAILSAFE = False

    def step1(i):
        pyautogui.hotkey('win','r')
        wx.CallLater(500, step2, i)
    def step2(i):
        pyautogui.typewrite('cmd.exe')
        wx.CallLater(500, step3, i)
    def step3(i):
        pyautogui.hotkey('enter')
        if i <= 1:
            return
        wx.CallLater(3500, step1, i-1)

    step1(2)
0
falsetru 14 Дек 2015 в 12:42