2015-07-23 4 views
1

Я сделал двойной таймер обратного отсчета с помощью python и tkinter, но казалось, что он не может быть запущен, если окно tkinter не находится на переднем плане и не может одновременно запускаться. Это мой код:Ошибка секундомера Python Tkinter

import tkinter as tk 
import tkinter.ttk as ttk 
import time 
class app: 

def __init__(self): 
    self = 0 

def mainGUIArea(): 
    def count_down_1(): 
     for i in range(79, -1, -1): 
      timeCount = "{:02d}:{:02d}".format(*divmod(i, 60)) 
      time_str.set(timeCount) 
      root.update() 
      time.sleep(1) 

    def count_down_2(): 
     for j in range(10, -1, -1): 
      timeCount = "{:02d}:{:02d}".format(*divmod(j, 60)) 
      time_str1.set(timeCount) 
      root.update() 
      time.sleep(1) 

    #Main Window 
    root = tk.Tk() 
    root.title("Super Timer V1.0") 
    root.minsize(300,300) 
    root.geometry("500x300") 

    #Timer1 
    time_str = tk.StringVar() 
    label_font = ('Courier New', 40) 
    tk.Label(root, textvariable = time_str, font = label_font, bg = 'white', fg = 'blue', relief = 'raised', bd=3).pack(fill='x', padx=5, pady=5) 
    tk.Button(root, text=' Start Timer! ',bg='lightgreen',fg='black', command=count_down_1).pack() 
    tk.Button(root, text='Stop and Exit',bg='red',fg='white', command=root.destroy).pack() 

    #Timer2 
    time_str1 = tk.StringVar() 
    label_font = ('Courier New', 40) 
    tk.Label(root, textvariable = time_str1, font = label_font, bg = 'white', fg='blue', relief='raised', bd=3).pack(fill='x', padx=5, pady=5) 
    tk.Button(root, text=' Start Timer! ',bg='lightblue',fg='black', command=count_down_2).pack() 
    tk.Button(root, text='Stop and Exit',bg='red',fg='white', command=root.destroy).pack() 


def main(): 
    app.mainGUIArea() 

main() 

У вас есть предложение? Спасибо!

+0

Используйте метод 'root.after'. –

ответ

1

Звонки на time.sleep являются, по крайней мере, частью проблемы. Когда вы вызываете сон, это буквально так - это заставляет приложение спать. Никакие события не могут быть обработаны, и графический интерфейс зависает. Это неправильный способ сделать таймер обратного отсчета.

Другой проблемой является вызов update внутри петель вместе с вызовами time.sleep. Этот вызов будет обрабатывать события, а это означает, что когда один из циклов запущен, и вы нажимаете кнопку, вы можете в конечном итоге вызвать другую функцию, перемежая ваши две петли.

Правильный способ сделать что-то периодически - использовать after для повторного вызова функции. Общая картина такова:

def update_display(self): 
    <do whatever code you want to update the display> 
    root.after(1000, self.update_display) 

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

Вот краткий пример:

class Countdown(tk.Label): 
    def __init__(self, parent): 
     tk.Label.__init__(self, parent, width=5, text="00:00") 
     self.value = 0 
     self._job_id = None 

    def tick(self): 
     self.value -= 1 
     text = "{:02d}:{:02d}".format(*divmod(self.value, 60)) 
     self.configure(text=text) 
     if self.value > 0: 
      self._job_id = self.after(1000, self.tick) 

    def start(self, starting_value=60): 
     if self._job_id is not None: return 

     self.value = starting_value 
     self.stop_requested = False 
     self.after(1000, self.tick) 

    def stop(self): 
     self.after_cancel(self._job_id) 
     self._job_id = None 
1

Это простой Tkinter (графический интерфейс) Секундомер я сделал, который прекрасно работает. Проверьте это

__author__ = 'Surya' 
from tkinter import * 
import time 
class StopWatch(Frame): 
    def __init__(self, parent = None, ** kw): 
     Frame.__init__(self, parent, kw) 
     self._timeelapsed = 0.0 
     self._start = 0.0 
     self._run = 0 
     self.timestr = StringVar() 
     self.makeWidgets() 
    def makeWidgets(self): 
     l = Label(self, textvariable=self.timestr) 
     self._setTime(self._timeelapsed) 
     l.pack(fill=X, expand=NO, pady=2, padx=2) 

    def _update(self): 
     self._timeelapsed = time.time() - self._start 
     self._setTime(self._timeelapsed) 
     self._timer = self.after(50, self._update) 

    def _setTime(self, elap): 
     minutes = int(elap/60) 
     seconds = int(elap - minutes*60.0) 
     hseconds = int((elap - minutes*60.0 - seconds)*100) 
     self.timestr.set('%02d:%02d:%02d' % (minutes, seconds, hseconds)) 

    def Start(self): 
     if not self._run: 
      self._start = time.time() - self._timeelapsed 
      self._update() 
      self._run = 1 

    def Stop(self): 
     if self._run: 
      self.after_cancel(self._timer) 
      self._timeelapsed = time.time() - self._start 
      self._setTime(self._timeelapsed) 
      self._run = 0 

    def Reset(self): 
     self._start = time.time() 
     self._timeelapsed = 0.0 
     self._setTime(self._timeelapsed) 


def main(): 
    root = Tk() 
    sw = StopWatch(root) 
    sw.pack(side=TOP) 
    Button(root, text='Start!', command=sw.Start).pack(side=LEFT) 
    Button(root, text='Stop!', command=sw.Stop).pack(side=LEFT) 
    Button(root, text='Reset!!!', command=sw.Reset).pack(side=LEFT) 
    Button(root, text='Quit!!!', command=root.quit).pack(side=LEFT) 

    root.mainloop() 

if __name__ == '__main__': 
     main() 
Смежные вопросы