2010-10-31 4 views
1

Je suis en train de me débrouiller avec Tkinter et Python. J'ai un gui de base avec quelques boutons, un bouton s'en va et fait quelque chose qui prend du temps, ce qui est variable. Le problème est que quand je tape sur ce bouton, l'ensemble de mon interface graphique se bloque/ne s'affiche pas correctement - je suppose que c'est parce qu'il essaye de faire ces choses qui prennent du temps et bloquent l'interface graphique.Bouton tkinter python exécuté en arrière-plan commande

J'ai regardé dans le filetage et les files d'attente, mais je ne peux pas le comprendre. Je pense que j'ai besoin de déclencher ma méthode de recherche sur un fil, puis mettre en file d'attente les résultats à mesure qu'ils reviennent et mettre à jour la liste en revenant?

Je suis sur Windows si cela fait une différence dans la façon dont j'utilise les threads.

Cordialement

david

Code de base ci-dessous.

class Search: 

     def __init__(self, master): 

      self.seeds = [] 

      frame = Frame(master, width=700, height=500) 
      frame.pack_propagate(0) 
      frame.pack(expand=YES, fill=BOTH) 

      # 
      # Search results 
      # 
      l2 = Label(frame, text="results") 
      l2.pack(anchor=W) 
      self.resultfield = Listbox(frame, selectmode=BROWSE) 
      self.resultfield.grid(row=3, column=1, sticky=N+W+S+E, columnspan=3) 
      self.resultfield.pack(fill=BOTH) 

      frame1 = Frame(frame) 
      frame1.pack() 


      # Button to action the search 
      self.getSearchbut = Button(frame1, text="Do Search", command=self.getSearch) 
      self.getSearchbut.grid(row=1, column=2) 
      self.getSearchbut.pack() 

     def getSearch(self): 


      sa = SearchApi(self.seeds) 

      results = sa.lookup(self) 


      for result in results: 
       self.resultfield.insert(END, user) 

     def putCSV(self): 
      print "put the csv files" 

class SearchApi: 

     def __init__(self, seeds): 
      self.seeds = seeds 

     def lookup(self): 
      results = [] 
       # I do something here that takes a while 
       return results 




if __name__ == "__main__": 

    root = Tk() 
    root.title("Search") 

    app = Search(root) 

    root.mainloop() 
+0

Pourriez-vous poster le code que vous avez essayé? Au-dessus de ma tête et de mon expérience, une fois que vous éteignez le fil, les problèmes se centrent généralement soit ne programmant pas le fil pour rester autour ou le fil lui-même se bloque et n'a pas le moyen d'abandonner et de renoncer au contrôle GUI. – spade78

+0

Ce n'est pas lié à TKinter de toute façon ... – juancarlospaco

Répondre

1

J'ai eu ce même problème jusqu'à aujourd'hui! Votre problème est que la boucle principale de Tkinter interfère avec votre boucle de tâches. Je devais retirer toutes les classes de mon programme et n'utiliser que des fonctions. Le bouton que vous utilisez permet de basculer une variable qui démarre ensuite la tâche de boucle.

Puis la solution est simple, au bout d'environ une semaine de recherche (ce qui est une version condensée de mon code):

scnBtn = Button(Frame, text="Update", command=readIt) 
    scnBtn.pack() 


def readIt(): ## this is the variable the button changes 
    global read 

    read = 1 
    TK.after(0, readFile) ##this is how you make sure the GUI doesn't freeze up 

def readFile(): ## this is the task you want the button to do 
    global read 

    if read == 1: 

     "your task" 

     if "task is over" 

      read = 0 

    if read == 1: 
     TK.after(0, readFile) ## this will keep the task going until its done. 

Hope this aidé!

5

L'utilisation de threads est simple, vraiment. Tout ce que vous avez à faire est d'importer la classe Thread:

from threading import Thread 

et changer la fonction getSearch pour ressembler à ceci:

def getSearch(self): 
    t= Thread(target=self.search)#this should work, in case it doesn't, try "t= Thread(target=Search.getSearch,args=[self])" instead. 
    t.start() 

def search(self): 
    sa = SearchApi(self.seeds) 
    results = sa.lookup(self) 
    for result in results: 
     self.resultfield.insert(END, user) 

Cela devrait être tout ce que vous devez faire, puisque je suis Bien sûr, Tkinter est sûr pour les threads. Dans le cas contraire, vous devrez créer un thread insérant les résultats de l'autre thread dans le widget de texte.

En outre, ceci est Python. Peu importe que vous soyez sous Windows ou non: D