0

i want that the frame comes back after it moves to right. how can i do that? or the frames goes to the right side and comes from the left side, to have a slide effect?


def move(steps=10, distance=0.10, distance2=0.10):
    if steps > 10:
        # get current position
        relx = float(frame.place_info()['relx'])

        # set new position
        frame.place_configure(relx=relx+distance)
                # repeate it after 10ms
        window.after(10, move, steps-1, distance)

def on_click():
    # start move
    move(50, 0.02) # 50*0.02 = 1


frame = Frame(window, bg="red", width=400, height=400)
frame.place(relx=0.192, rely=0.001, relwidth=0.81, relheight=0.992)

i tried a few options but i can't find a way, to bring the frame back in the old postion after it's moving. have someone any ideas?

enter image description here enter image description here

bangKok
  • 332
  • 2
  • 13
  • Why don't you use a canvas instead. Create a `tk.Canvas` and put the object you want to move in there? – TheLizzard Mar 14 '21 at 21:23
  • hmm. i haven't use canvas before. i started with python before few weeks. what is the advantage of canvas? – bangKok Mar 14 '21 at 21:32
  • I think that is it faster and easier to use. What are you actually trying to do? Are you trying to make a frame move from the left to the right and immediately teleport on the left side again? – TheLizzard Mar 14 '21 at 21:33
  • yes the frame should move to right and then appear again at the old postion. its for a quiz app. – bangKok Mar 14 '21 at 21:48

2 Answers2

1

Something like the below would work. The concept is simple: The relx or rely of place keeps changing until the Frame has reached it's ultimate "rel-position". We use a little ratio math to make sure the frame is pushed completely out of the display and brought back to the desired "rel-position". I was bored so I made it work in every direction.

import tkinter as tk

class SlideFrame(tk.Frame):
    def __init__(self, master, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        self.__slide = None
        
    def slide_in(self, ult_rel=0, steps=20, side='left', inc=None):
        #force everything to be perfect no matter what
        if inc is None:
            self.update_idletasks()
            #determine the ratio of self to master in the proper direction
            if side in ('left', 'right'):
                r = self.winfo_width()/self.master.winfo_width()
            elif side in ('top', 'bottom'):
                r = self.winfo_height()/self.master.winfo_height()
            #determine the extra amount to move beyond ratio     
            ex = ult_rel if side in ('left', 'top') else r-ult_rel
            #divide the sum by steps to get a move increment
            inc = (r+ex)/steps
        
        #get the proper polarity to multiply by
        s = -steps if side in ('left', 'top') else steps
        #get new position
        p = ult_rel+(s*inc)
        
        #determine which property to apply the move to
        self.place_configure(relx=p) if side in ('left', 'right') else self.place_configure(rely=p)
        
        #as long as there are steps left, keep running this method
        if steps > 0:
            self.slide = self.after(20, self.slide_in, ult_rel, steps-1, side, inc)
            
    def place_(self, ult_rel=0, side='left', steps=20, **kwargs):
        #use this little trick and you can do everything on one line
        self.place(**kwargs)
        self.slide_in(ult_rel, steps, side)
        return self
        

root = tk.Tk()
root.geometry('800x600+100+100')
root.configure(background='#111111')
root.update_idletasks()

dims=dict(relwidth=.5, relheight=.5)

#demo
frame1 = SlideFrame(root, bg='#ff0000').place_( 0,           rely= 0, **dims)
frame2 = SlideFrame(root, bg='#00ff00').place_( 0, 'top'   , relx=.5, **dims)
frame3 = SlideFrame(root, bg='#0000ff').place_(.5, 'right' , rely=.5, **dims)
frame4 = SlideFrame(root, bg='#ff8800').place_(.5, 'bottom', relx= 0, **dims)

if __name__ == '__main__':
    root.mainloop()
OneMadGypsy
  • 4,640
  • 3
  • 10
  • 26
1

Try this:

import tkinter as tk

def move_frame(event=None):
    # 1 is the change in x and the 0 is the change in y
    canvas.move(frame_id, 1, 0)
    # Look at: https://stackoverflow.com/a/2679823/11106801
    x, *_ = canvas.coords(frame_id)
    # Note 400 is the width of the canvas
    if x > 400:
        canvas.move(frame_id, -400, 0)
    else:
        # To adjust the speed change the 3 (it's the time in ms)
        # It calls `move_frame` after 3 ms
        canvas.after(3, move_frame)

root = tk.Tk()
# Create the canvas
canvas = tk.Canvas(root, width=400, height=400, bg="black")
canvas.pack()

frame = tk.Frame(canvas, width=100, height=100, bg="grey")
# Look at: https://stackoverflow.com/a/11981214/11106801
frame_id = canvas.create_window(0, 150, anchor="nw", window=frame)

# If you want it to move when clicked:
frame.bind("<Button-1>", move_frame)
# To just start the movement:
canvas.after(0, move_frame)

# Make sure you start the mainloop otherwise the loop woudn't work
root.mainloop()

It uses a tkinter loop to move the object on the canvas.

TheLizzard
  • 7,248
  • 2
  • 11
  • 31