2015-07-23 2 views
-1
from Tkinter import * 
import tkFileDialog 
import tkMessageBox 
import os 
import ttk 

import serial 
import timeit 
import time 

###################################################################################### 
class MyApp: 
    def __init__(self, parent): 
######################################################## 
#Setup Frames 

     self.MiddleFrame = Frame(parent) #Middle Frame 
     self.MiddleFrame.pack() 
     #GLOBAL VARIABLES 
     self.chip_number = 0 #number of chip testing 
########################################### 
     #Middle Frame setup 
     Label(self.MiddleFrame, text='Done').grid(row=8, column=1, sticky = E) 
     self.Done = Canvas(self.MiddleFrame, bg="yellow", width=10, height=10) 
     self.Done.grid(row=8, column=2)   
     Label(self.MiddleFrame, text='Chip Number:').grid(row=9, column=1, sticky = E) 
     #start button 
     self.button1 = Button(self.MiddleFrame,state=NORMAL, command= self.start_pre) 
     self.button1["text"]= "START" 
     self.button1.grid(row=1, column=2, sticky = E) 
########################################### 
#Action of Start Button 
    def start_pre(self): 

     x = 0 
     while x<10000:   
      self.start_button() 
      x=x+1 

#Talking to Board 
    def start_button(self): 
     #increase chip count number and update 
     self.chip_number += 1 
     Label(self.MiddleFrame, text=str(self.chip_number)).grid(row=9, column=2, sticky = E) 
     #reset-yellow 
     self.reset_color()   
     print "Still Working", self.chip_number 
     self.Done.configure(background="green") 
     self.Done.update_idletasks()     

############################################################### 
#Color Boxes 
#Reset 
    def reset_color(self): 
     self.Done.configure(background="yellow") 
     self.Done.update_idletasks() 
############################################################################################################### 
#Start Programs 
root = Tk() #makes window 
root.title("Interface") 
myapp = MyApp(root) #this really runs program 
root.mainloop() #keep window open                   

С моей программой я сначала нажимаю кнопку запуска. Я буду печатать «все еще работаю», и GUI обновит номер фишки и снова начнет мигать. Кнопка «Пуск» переходит к функции, которая будет выполняться 10000 раз. Однако после 3000 итераций gui замерзает, но программа по-прежнему печатается «все еще работает». Как я могу скрыть гии?Python tkinter GUI замораживание/сбой

+0

Возможно, вы должны поместить метод в отдельный поток. См. Здесь http://stackoverflow.com/questions/16745507/tkinter-how-to-use-threads-to-preventing-main-event-loop-from-freezing –

+1

Попробуйте использовать 'after' Tkinter вместо' sleep' –

+0

FWIW, вы должны использовать 'time.time()' вместо 'timeit.default_timer()'. Оба названия относятся к одной и той же функции, но 'time.time()' будет иметь больше смысла для людей, читающих ваш код. –

ответ

2

Существует много проблем с вашим кодом. С одной стороны, это существенные недостатки:

while self.stop == True:   
    self.start_button() 
    time.sleep(0.5) 

Вы просто не можете ожидать GUI, чтобы правильно вести себя с кодом, как это. Как правило, вы никогда не должны иметь основной поток вызова GUI sleep. Причинение sleep предотвращает обработку цикла событий любых событий, включая события низкого уровня, такие как запросы на обновление экрана.

Был задан вопрос об использовании sleep и много раз ответил на stackoverflow. Вы можете найти некоторые из этих вопросов полезными. Например,

У вас есть еще одна проблема, которая относится к категории утечки памяти. Из этого цикла while вы вызываете self.start_button() на неопределенный срок. Это происходит примерно раз в секунду, из-за того, что сон вызывается на полсекунды в цикле, а еще полсекунды - в start_button.

Каждый раз, когда вы звоните start_button, вы создаете другой ярлык виджет, который стек поверх всех предыдущих виджетов в строке 9, столбец 2. В конечном счете это приведет к вашей программе аварии. Я удивлен, что это заставляет вашу программу терпеть неудачу так быстро, но это не относится к делу.

Моя рекомендация - начать с простого примера, который ничего не делает, кроме как обновлять метку каждую секунду. Получите эту работу, чтобы понять основной механизм. Затем, как только он работает, вы можете добавить свой код, который читается из последовательного порта.

+0

Есть ли пример кода в stackoverflow, который обновляет метку каждую секунду –

+0

@VemaReddy: последний вопрос, на который я ссылался, в моем ответе делает это. –

0

Могу ли я предложить начать с следующего кода? Вы можете отправить обратно на Python 2, если это необходимо, но ваша программа была переписана для использования Python 3 и была разработана для использования возможности tkinter для планирования будущих событий с помощью методов after. Надеемся, вы найдете код легче следовать.

import collections 
import timeit 
import tkinter 

def main(): 
    root = Application() 
    root.setup() 
    root.mainloop() 

class Application(tkinter.Tk): 

    def setup(self): 
     mf = self.__middle_frame = tkinter.Frame(self) 
     self.__middle_frame.grid() 
     bf = self.__bot_frame = tkinter.Frame(self) 
     self.__bot_frame.grid() 

     self.__port_set = False 
     self.__chip_number = 0 
     self.__chip_pass_num = 0 
     self.__chip_fail_num = 0 
     self.__chip_yield_num = 0 
     self.__stop = True 

     self.__widgets = collections.OrderedDict((
      ('COT', 'Continuity Test'), ('CHE', 'Chip Erase'), 
      ('ERT', 'Erase Test'), ('WRT', 'Write Test'), 
      ('WIRT', 'Wire Reading Test'), ('WIT', 'Wire Reading Test'), 
      ('WRAT', 'Write All Test'), ('DO', 'Done'))) 

     for row, (key, value) in enumerate(self.__widgets.items()): 
      label = tkinter.Label(mf, text=value+':') 
      label.grid(row=row, column=0, sticky=tkinter.E) 
      canvas = tkinter.Canvas(mf, bg='yellow', width=10, height=10) 
      canvas.grid(row=row, column=1) 
      self.__widgets[key] = label, canvas 

     self.__cn = tkinter.Label(mf, text='Chip Number:') 
     self.__cn.grid(row=8, column=0, sticky=tkinter.E) 
     self.__display = tkinter.Label(mf) 
     self.__display.grid(row=8, column=1, sticky=tkinter.E) 

     self.__button = tkinter.Button(bf, text='START', 
             command=self.__start_pre) 
     self.__button.grid(sticky=tkinter.E) 

    def __start_pre(self): 
     self.__button['state'] = tkinter.DISABLED 
     self.__start_button(0) 

    def __start_button(self, count): 
     if count < 100: 
      self.__chip_number += 1 
      self.__display['text'] = str(self.__chip_number) 
      self.__widgets['DO'][1]['bg'] = 'yellow' 
      start_time = timeit.default_timer() 
      print('Still Working:', self.__chip_number) 
      self.after(500, self.__end_button, count) 
     else: 
      self.__button['state'] = tkinter.NORMAL 

    def __end_button(self, count): 
     self.__widgets['DO'][1]['bg'] = 'green' 
     self.after(500, self.__start_button, count + 1) 

if __name__ == '__main__': 
    main() 
+0

как вы возвращаете обратно на Python 2? –

+0

@VemaReddy В случае с этим кодом вам, вероятно, просто нужно будет заменить 'import tkinter'' import Tkinter as tkinter'. –

+0

Спасибо, ваше право –