2015-12-14 2 views
1

[PROBLEM] Если я нажму кнопку, которая запускает функцию, тогда gui замерзнет, ​​пока функция не завершится.Как предотвратить зависание gui в wxpython?

[КОД]

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() 

[Ток] Графический интерфейс замерзает, пока функция не заканчивается.

[ЖЕЛАЕМ] Гви не следует замерзать. Примечание: Я думаю, что это связано с потоками, но я не могу понять эту концепцию.

+0

Используйте темы. Здесь у вас есть пример для добавления их в GUI в wxPython: http://wiki.wxpython.org/Non-Blocking%20Gui – tglaria

ответ

1

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

# -*- 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() 

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

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

0

Используйте 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

Это действительно не разблокирует графический интерфейс, который вы просто заменяете 'time.sleep' (который может быть симуляцией некоторого вычисления) с помощью этой функции «CallLater», не так ли? – tglaria

+0

@tglaria, вызывая 'wx.CAllLater', элемент управления передается в цикл событий. – falsetru

+0

, но он не поддерживает функцию, она звучит как поток с задержкой запуска, не так ли? Перечитав вопрос, он работает для этого приложения, но это не должен быть общий ответ для неблокирующего графического интерфейса, верно? – tglaria

-1

Я не знаком с WX но mabye это помогает

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() 
+0

Это не работает, вы связываете поток с событием, но когда начинается этот поток? И как только потоки заканчиваются, вы должны их воссоздать (что здесь не делается) – tglaria

+0

@tglaria. да. Я прочитал эту статью, в то же время я не совсем понял, что именно поэтому я попросил намек на то, чтобы начать меня. Я буду копать еще немного ..... – george

+0

@tglaria. работает. оценили. пытаясь приспособить его к моей реальной функции. – george

Смежные вопросы