[Tutor] please help me with after method
Alan Gauld
alan.gauld at yahoo.co.uk
Thu Nov 17 17:07:49 EST 2016
Always use REply-All or Reply-List to the tutor list.
On 17/11/16 18:34, Freedom Peacemaker wrote:
> Thank you Alan for answer but i still cant make it. I have improved my
> program but it still uses root.update() and now my app looks
> professional :) It is my first program. I am self learning Python
> since july this year but still i need a lot of knowledge. Could you
> help me improve my app with root.after?
OK, I'll try.
> And there is problem - when im closing app with X button after using
> app it shows two windows. One with messagebox i wrote, and second
> blank new tk window. I dont know where im doing mistake, or it is
> caused by root.update maybe? Maybe with using root.after problem will
> be no more.
Maybe, but I'll need to look at the code more closely.
There are a couple of things that could cause this....
Having looked, I think you need to bind the window
manager close button to root.quit Take a look at
the wm_xxxx methods in the Tkinter docs.
>
> def displayCountdown():
> lcd = "{:02d}:{:02d}".format(*divmod(t, 60))
> timeString.set(lcd)
> setTime -= 1
> if setTime > 0:
> root.after(1000,displayCountdown)
>
Where is 't' (used in the divmod) defined? Looking below I think
it should use setTime?
Otherwise it looks like it should work. All you need to do is insert
a call to displayCountdown() in your START button event handler.
> There are problems with my app but im so proud that i wrote myself
Its rare that anything is ever perfect but the buzz of getting
something to work more or less as you want it to is always good. :-)
> import sys, time, os
> import tkinter as tk
> from tkinter import *
>
You should probably only ose one of the tkinter imports.
And the first is the preferred method for production code.
> def change_1():
> B1['state'] = tk.DISABLED
> B2['state'] = tk.NORMAL
>
> def change_2():
> B1['state'] = tk.NORMAL
> B2['state'] = tk.DISABLED
>
> def change_3():
> B1['state'] = tk.DISABLED
> B2['state'] = tk.DISABLED
Add the displayCountdown() definition here
>
> def startCount():
> setTime = setMinutes.get() * 60
> strTime = str(setTime)
> timeSet = ("\""+"shutdown /s /f /t " +strTime+"\"")
> os.system(timeSet)
> change_1()
displayCountdown() # uses the after() method.
This removes the need for all of the code below.
> for t in range(setTime, -1, -1):
> lcd = "{:02d}:{:02d}".format(*divmod(t, 60))
> timeString.set(lcd)
> try:
> root.update()
> except TclError:
> messagebox.showinfo('Info', 'Closing app wont stop timer.')
> return
> time.sleep(1)
> return
>
The rest of your code is unchanged.
But note I haven't tested this! :-)
> def stopCount():
> passwd = "science"
> passwdGet = getPass.get()
> if passwd != passwdGet:
You could make this more secure.
You should probably do some reading about best [practice
for handling passwords. But for now it probably meets your needs.
> messagebox.showinfo('Wrong', 'It wasnt correct password')
> change_3()
> else:
> messagebox.showinfo('Good', 'Shutdown canceled')
> os.system("shutdown /a")
> change_2()
> return
>
> root = tk.Tk()
> setMinutes = IntVar()
> getPass = StringVar()
> timeString = StringVar()
> label_font = ('Verdana', 30)
> root.geometry('260x150+200+200')
> root.title('Timer v1.4')
> root.resizable(0, 0)
>
> L1 = tk.Label(root, text='How much time you have?')
> L1.grid(row=0, columnspan=3, sticky='WE')
>
> L2 = tk.Label(root, textvariable=timeString, font=label_font, bg='white',
> fg='orange', relief='raised', bd=3)
> L2.grid(row=1, columnspan=3, sticky='WE', padx=5, pady=5)
>
> E1 = tk.Entry(root, textvariable=setMinutes, bg='lightgreen')
> E1.grid(row=2, column=1, padx=5, pady=5)
>
> B1 = tk.Button(root, text='S T A R T', fg='green', bg='black',
> command=startCount)
> B1.grid(row=2, rowspan=2, sticky='NS', column=0, padx=5, pady=5)
>
> E2 = tk.Entry(root, textvariable=getPass, bg='red')
> E2.grid(row=3, column=1, padx=5, pady=5)
>
> B2 = tk.Button(root, text='S T O P', fg='red', bg='black',
> command=stopCount,
> state=tk.DISABLED)
> B2.grid(row=2, rowspan=2, sticky='NS', column=2, padx=5, pady=5)
>
> root.mainloop()
>
>
>
> 2016-11-17 1:03 GMT+01:00 Alan Gauld via Tutor <tutor at python.org
> <mailto:tutor at python.org>>:
>
> On 16/11/16 18:48, Freedom Peacemaker wrote:
> > Hi, i need help. I am using Python 3.4 and I have wrote little
> app for
> > windows only ( windows 7 and higher). Its timer and my app
> working but not
> > good. Some people said that i should use after method instead of
> update()
>
> after() executes a function after a delay.
> In your case you could use it to trigger an
> immediate shutdown after the delay elapses.
> But I'm not sure that would be much better
> than doing what you are doing.
>
> The other use of after is to avoid loops in
> event handlers such as the one you have here.
> This allows control to return to the GUI window.
>
> See below...
>
> > When you run app first enter minutes in entry then press start.
> If you
> > first press start your pc will shutdown with no time to stop it
>
> You can fix that by setting a default value for the time.
> But you still need to write some code to cancel the shutdown
> (by killing the process perhaps?)
>
> > def startCount():
> > setTime = setMinutes.get() * 60
> > strTime = str(setTime)
> > timeSet = ("\""+"shutdown /s /f /t " +strTime+"\"")
> > os.system(timeSet)
>
> Up to here is fine but you don't want a long running loop
> inside an event handler. Although, in this case, it probably
> doesn't run for long, it just counts down very quickly.
>
> Instead you want it to count down every second or so.
>
> So you want to call a function that displays the time
> remaining then calls after() with a delay of 1 second.
> The call to after should have the same function in it.
> Like so:
>
> def displayCountdown():
> # display the time here
> # decrement the time by 1 second
> # if any time remains:
> # call after(1000,displayCountdown) # 1000ms = 1s
>
> Note that after only needs the function name, don't
> include any parentheses.
>
> > for t in range(setTime, -1, -1):
> > lcd = "{:02d}:{:02d}".format(*divmod(t, 60))
> > timeString.set(lcd)
> > try:
> > root.update()
> > except TclError:
> > messagebox.showinfo('Info', 'Closing app wont stop
> timer.')
> > return
> > time.sleep(1)
> > return
>
>
> HTH
> --
> Alan G
> Author of the Learn to Program web site
> http://www.alan-g.me.uk/
> http://www.amazon.com/author/alan_gauld
> <http://www.amazon.com/author/alan_gauld>
> Follow my photo-blog on Flickr at:
> http://www.flickr.com/photos/alangauldphotos
> <http://www.flickr.com/photos/alangauldphotos>
>
>
> _______________________________________________
> Tutor maillist - Tutor at python.org <mailto:Tutor at python.org>
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
> <https://mail.python.org/mailman/listinfo/tutor>
>
>
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos
More information about the Tutor
mailing list