2015-08-23 9 views
-1

Следующий код должен обновлять графический интерфейс пользователя и одновременно выполнять расчет. В этом случае self.after() не является решением, так как расчет будет продолжаться в течение длительного времени (а также должен быть time.sleep (n) в расчете, но это не должно останавливать работу графического интерфейса (т. Е. пользователь по-прежнему может настроить ползунки). Таким образом, это должно быть сделано с помощью нескольких потоков. следующий код, что я хотел бы предложить, но он не работает. Любые предложения, что я ошибалась?Tkinter с несколькими потоками

import Tkinter as tk 
import ttk 
import time 
import threading 

class GUI(tk.Frame): 
    def __init__(self, master=None): 
     tk.Frame.__init__(self, master) 
     self.pack() 
     self.i=0 
     self.var1 = tk.StringVar() 
     self.var2 = tk.StringVar() 
     self.var3 = tk.StringVar() 
     self.var4 = tk.StringVar() 
     self.var5 = tk.StringVar() 
     self.var6 = tk.StringVar() 
     self.var7 = tk.StringVar() 
     tk.Label(self, textvariable=self.var1,justify='left').pack() 
     tk.Label(self, textvariable=self.var2).pack() 
     tk.Label(self, textvariable=self.var3).pack() 
     tk.Label(self, textvariable=self.var4).pack() 
     tk.Label(self, textvariable=self.var5).pack() 
     tk.Label(self, textvariable=self.var6).pack() 
     tk.Label(self, textvariable=self.var7).pack() 


     p1 = tk.Scale(master, from_=1, to=20, orient=tk.HORIZONTAL).pack() 
     p2 = tk.Scale(master, from_=1, to=20, orient=tk.HORIZONTAL).pack() 
     p3 = tk.Scale(master, from_=1, to=20, orient=tk.HORIZONTAL).pack() 
     p4 = tk.Scale(master, from_=1, to=20, orient=tk.HORIZONTAL).pack() 
     p5 = tk.Scale(master, from_=1, to=20, orient=tk.HORIZONTAL).pack() 

     self.progress = ttk.Progressbar(self, orient="horizontal",length=100, mode="determinate") 
     self.progress.pack() 

    def calculation(self): 
     while True: 
      # complex calculations that last 30 minutes in total 
      self.i += 1 
      time.sleep(1) 
      max=1000 
      self.var1.set("Value1: "+str(self.i)) 
      self.var2.set("Value2: "+str(self.i+100)) 
      self.var3.set("Value3: "+str(self.i+100)) 
      self.var4.set("Value4: "+str(self.i+100)) 
      self.var5.set("Value5: "+str(self.i+100)) 
      self.var6.set("Value6: "+str(self.i+100)) 
      self.var7.set("Value7: "+str(self.i+100)) 
      self.progress["value"] = int(round(self.i*100/max)) 
      #self.update() # no need, will be automatic as mainloop() runs 
      #self.after(1, self.calculation) not necessary anymore as everything is in a main loop 


app=GUI() 

t1 = threading.Thread(target=app.calculation, args=[]) 
t2 = threading.Thread(target=app.mainloop, args=[]) 
t1.start() 
t2.start() 
t1.join() 
t2.join() 
print ("thread finished...exiting") 
+0

Несколько потоков не могут взаимодействовать с объектами Tkinter. Ваше утверждение о необходимости вызова 'time.sleep()' в вычислении является полной бессмыслицей. Хорошим способом безопасного многопоточности в приложении Tkinter является использование объектов (Queue) для передачи (передачи данных) из вспомогательных потоков в основной. Обычно 'self.after()' используется для планирования периодического извлечения данных, которые генерирует другой поток (ы). – martineau

+0

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

+0

Если вам действительно нужно поставьте временную задержку в «вычислении», документы говорят, что вы можете использовать 'self.after()' вместо 'time.sleep()', но передавать только один аргумент значения времени. – martineau

ответ

1

Первых всего вам нужно научиться СУХОЙ правило.

вы должны запустить app.mainloop() непосредственно. Что-то вроде

t1 = threading.Thread(target=app.calculation, args=[]) 
t1.start() 
app.mainloop() 
+0

Спасибо, что работает. Любое предложение, как я могу закончить программу, когда графический интерфейс закрыт? То есть прекратить другой поток? – Nickpick

+0

Твердый раствор делает нить бесконечной. Простое решение - убить как gui, так и thread с помощью sys.exit –

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