Python/Tkinter: implementing wait within a tkinter function embedded in a class

Question:

I have created a class for an animated tk frame that can be moved across the screen. For example, the user might click a button and the frame would then slide into view, rather than simply appear at a fixed location. The effect works perfectly, but there is a problem that I will outline below. First, here is the code for the class, which I have saved as a module to be imported into the main application:

import tkinter as tk
import customtkinter as ctk

class MyFrame(ctk.CTkFrame):
  def __init__(self,master,height,width,placerow,startcol,endcol):
    super().__init__(master)

    # initialize instance variables
    self.master = master
    self.height = height
    self.width = width
    self.placerow = placerow
    self.startcol = startcol
    self.endcol = endcol
    
    # set parameters based on instance variables
    self.configure(width= width)
    self.configure(height= height)

  def MoveFrameRight(self):
    global colInt
    colInt = self.startcol
    self.ShiftFrameRight()

  def ShiftFrameRight(self):
    global colInt
    if colInt < self.endcol:
      colInt = colInt + 1
      self.place(x=colInt,y=self.placerow)
      self.master.after(1,self.ShiftFrameRight)

And here is how the class would be implemented in the main application:

import ModCtkFrameAnimated
FrameName=ModCtkFrameAnimated.MyFrame(RootWindow,300,100,10,10,300)
FrameName.MoveFrameRight()
print("Done")

I included the print("Done") statement to illustrate the problem. When FrameName.MoveFrameRight() is called, the function works fine, but it does not wait until completion before moving to the print("Done") line. So in real world code, it’s un-usable. I have had some experience with the wait_window() function. But in this case, I don’t want to destroy the frame, so that will not work here. I simply want to have the MoveFrameRight() function complete fully before moving to the next line of code in the main application. Any suggestions appreciated.

Asked By: fmex

||

Answers:

You can wait on tkinter variables to change with the wait_variable method. Do this by creating a variable, setting it to a value, resetting the value when your animation is finished, set the code in motion, then wait for the variable to be set. While tkinter is waiting it’s able to process events as normal.

class MyFrame(ctk.CTkFrame):
  def __init__(self,master,height,width,placerow,startcol,endcol):
    ...
    self.flag = tk.IntVar(value=0)
    ...

  def MoveFrameRight(self):
    ...
    self.flag.set(1)
    ...
    self.ShiftFrameRight()
    self.wait_variable(self.flag)

  def ShiftFrameRight(self):
    global colInt
    if colInt < self.endcol:
      ...
    else:
      self.flag.set(0)
Answered By: Bryan Oakley
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.