0

I'm trying to create a couple of functions which do things in a sequential order. First they need to open a new window and display a label, then they need to wait for some seconds, then they need to call another function. However, I'm struggling to get the functions to wait, all the methods I've tried (.after, .sleep, .wait_visibility) seem to be ignored and it just skips to the next function call without pausing.

Here's what I have (sorry if it's messy, I'm new to python):

from tkinter import *
import time

root =Tk()
root.geometry('600x600')

def scale_screen(event = None):
    global s_screen
    s_screen = Toplevel(root)
    s_screen.title('Residual Inhibition Tester')
    s_screen.geometry('600x600')
    s_screen.transient(root) 
    s_screen.bind('<Return>', sel)
    global var 
    var = IntVar()
    scale = Scale(s_screen, variable = var, orient = HORIZONTAL, length = 1000)
    scale.focus_set()
    scale.pack(anchor=CENTER) 
    button = Button(s_screen, text="Select", command=sel)
    button.pack(anchor=CENTER)

def sel(event = None):
    label = Label(s_screen)
    selection = "Value = " + str(var.get())
    label.config(text = selection)   
    interval_screen()

def interval_screen():
    global i_screen
    i_screen = Toplevel(root)
    i_screen.geometry('600x600')
    i_screen.transient(root)
    i_label = Label(i_screen, text = "Please Wait")
    i_label.pack(anchor = CENTER)
    s_screen.destroy()
    i_screen.after(3000, masker_screen) 
    #time.sleep(3)
    #i_screen.after(300,i_label.configure(text="Playing New Masker Noise")) 
    #root.wait_visibility(window = i_screen) 




def masker_screen():
    global m_screen
    m_screen = Toplevel(root)
    m_screen.geometry('600x600')
    m_screen.transient(root) 
    m_label = Label(m_screen, text = "Playing New Masker Noise").pack(anchor = CENTER)
    m_screen.after(3000, lambda: scale_screen(event = None))
    i_screen.destroy()

b1 = Button(root, command = scale_screen).pack(anchor=CENTER)
root.bind('<Return>', scale_screen)
root.mainloop()

In this example, the program will run but just skip the interval_screen entirely and just do the masker_screen. I'm also not averse to just using one screen and using the .configure methods to change the label text if that's easier.

Thanks!

1
  • Please post a runnable code sample. I don't think it's possible to answer your question the way it is now. Commented Jan 12, 2015 at 16:57

1 Answer 1

2

Without seeing all the ways you tried it, it's impossible to know what you did wrong. In general you should never call time.sleep and you should never call after with just a single argument. Also, when you use after with two arguments, the second argument must be a reference to a function.

The proper way to do this is to have your first function call your second function via after:

def interval_screen():
    ...
    i_screen.after(3000, maker_screen)

def masker_screen():
    ...
    m_screen.after(3000, lambda: scale_screen(event = None))

Note that in your updated question you're using after incorrectly:

m_screen.after(3000, scale_screen(event = None))

You're calling the function scale_screen(...) immediately, and giving the result of that to the after function. If you need to pass arguments to your function you must create another function that does not require arguments. The simplest way to do this is with lambda, though you can also use functools.partial or you can create your own function.

Sign up to request clarification or add additional context in comments.

5 Comments

Hi Bryan thanks for your answer! Unfortunately, I've tried this (I updated the question to show what I've done) and it's still skipping the waiting functions.
@Yoddlenod: if you look at your code you'll see you've done something wrong. See this line of code: m_screen.after(3000, scale_screen(event = None)). You're immediately calling scale_screen(...), and the result of that is being called by after. Look at the use of lambda in the last part of my example.
Ah, I see! That solves half the problem, thank you. But it still appears to be skipping over the interval_screen function. Even if I use the lambda function within the interval_screen.
@Yoddlenod: based on the code in the question now it can't possibly skip over interval_screen because you're directly calling it, so I don't understand your comment. Also, you 're calling masker_screen twice - once directly, once via after.
Ahh! On a second run through and look, that seems to have solved the problem. Thank you very much for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.