Ali Bayat Mokhtari
Ali Bayat Mokhtari

Reputation: 187

Label variable does not set in function

Why when i click on sign in button, the label immediately gets 'Not Verified' value and it doesn't show 'Recording' and 'Ended'. when i comment self.messageBoxText.set('Not Verified'), label shows 'Ended' and does not show 'Recording'. code is like below:

import time


class SampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.geometry('1250x400')
        self.title('Speaker Verification System')
        self._frame = None
        self.switch_frame(StartPage)

    def switch_frame(self, frame_class):
        new_frame = frame_class(self)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.pack(fill='both')


class StartPage(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.messageBoxText = tk.StringVar()
        self.messageBoxText.set('Click on "Sign In" button to enter.')
        tk.Label(self, text="Locked", font=('courier new', 48, "bold")).pack(side="top", fill="x", pady=5)
        tk.Label(self, textvariable=self.messageBoxText, font=('courier new', 24), borderwidth=2,
                 relief='groove', width=70, height=5).pack(pady=30)
        tk.Button(self, text='Sign in', width=20, height=2, command=lambda: self.verify_login(master)).pack()

    def verify_login(self, master):
        verify = 2
        self.messageBoxText.set('Recording...') # it doesn't set
        self.messageBoxText.set('Ended...') # it doesn't set
        if verify == 1:
            self.messageBoxText.set('Login Successful')
            master.switch_frame(PageOne)
            return
        self.messageBoxText.set('Not Verified')


class PageOne(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        tk.Frame.configure(self, width=1250, height=400)
        self.monitorText = tk.StringVar()
        self.monitorText.set('Welcome to the Speaker Verification System')
        tk.Button(self, text='Linear SVC', command=self.btn_linear_svc_clicked).place(x=10, y=50, width=150, height=30)
        tk.Button(self, text='Sign Out', command=lambda: master.switch_frame(StartPage)).place(x=10, y=100, width=150, height=30)
        tk.Button(self, text='Quit', command=quit).place(x=10, y=150, width=150, height=30)
        tk.Label(self, textvariable=self.monitorText, borderwidth=2, relief='groove').place(x=200, y=10, width=400, height=380)

    def btn_linear_svc_clicked(self):
        self.monitorText.set('Linear SVC Button Clicked...')


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

Upvotes: 2

Views: 76

Answers (1)

furas
furas

Reputation: 143231

GUI doesn't redraw widgets directly when you change value but when you exit from function. After you exit function it may have more elements to redraw and it can redraw all of them in one moment so it use less time and don't blink.

You may use self.update() to force GUI to redraw widgets and time.sleep() to wait before you change text in label and use another update()

def verify_login(self, master):
    verify = 2

    self.messageBoxText.set('Recording...') # it doesn't set
    self.update() # force GUI to redraw widgets
    time.sleep(1)

    self.messageBoxText.set('Ended...') # it doesn't set
    self.update() # force GUI to redraw widgets
    time.sleep(1)

    if verify == 1:
        self.messageBoxText.set('Login Successful')
        master.switch_frame(PageOne)
        return

    self.messageBoxText.set('Not Verified')

But when you use this method then it blocks mainloop which checks key/mouse events and you may see that other elements are frozen.

To resolve problem with frozen widget you can use after(milliseconds, function_name) to ask mainloop to execute another function with delay. And then mainloop will have time to check key/mouse events.

def verify_login(self, master):
    verify = 2

    self.messageBoxText.set('Recording...') # it doesn't set
    self.after(1000, self.verify_2, verify) # 1000ms = 1s

def verify_2(self, verify):    
    self.messageBoxText.set('Ended...') # it doesn't set
    self.after(1000, self.verify_3, verify) # 1000ms = 1s

def verify_3(self, verify):    

    if verify == 1:
        self.messageBoxText.set('Login Successful')
        master.switch_frame(PageOne)
        return

    self.messageBoxText.set('Not Verified')

But this method may seems strange.

Upvotes: 1

Related Questions