Satyajit
Satyajit

Reputation: 115

How to make a tkinter scrollable canvas with background image?

I have created a class that makes a Scrollable canvas with scrollbar in Tkinter:

class ScrollableFrame(ttk.Frame):
    def __init__(self, container, *args, **kwargs):
        super().__init__(container, *args, **kwargs)
        self.canvas = tk.Canvas(self)
        scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.scrollable_frame = ttk.Frame(self.canvas)

        self.scrollable_frame.bind(
            "<Configure>",
            lambda e: self.canvas.configure(
                scrollregion=self.canvas.bbox("all")
            )
        )

        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")

        self.canvas.configure(yscrollcommand=scrollbar.set)

        self.canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")

    def scroll_to_end(self):
        self.canvas.yview_moveto(1)

Then I created a frame in it and placed widgets in it:

root = tk.Tk()
frame = ScrollableFrame(root)


# Frame to place messages on
scrollable_frame = tk.Frame(frame.scrollable_frame, height=80, width=900)
scrollable_frame.pack()
img1 = ImageTk.Photo
Image(Image.open(r'./chat_bg.jpg'))
panel1 = tk.Label(scrollable_frame, image=img1)
panel1.place(x=0, y=0)

# Text box to send message
message_entry = tk.Entry(root, bg='grey')
message_entry.pack(side='bottom', fill='x')
message_entry.focus_set()

message_placing_height = 5  # Variable to specify the height where message to be placed

# Sending button
send_button = tk.Button(root, text="Send", activebackground="pink")
send_button.pack(side='bottom', anchor='ne')

#THIS LOOP IS ONLY FOR REFERENCE 
#BUT IN REAL WIDGETS WILL BE PLACED ONE AFTER ANOTHER AFTER TIME INTERVALS
for i in range(20):
    y = message_placing_height
    msg_label = tk.Label(scrollable_frame, text='Hello World'+ str(i), fg="red", font="Times 12")
    msg_label.place(x=170, y=y)
    message_entry.delete(0, 'end')
    message_placing_height += 25
    scrollable_frame.configure(height=message_placing_height)

frame.pack()

# __MAIN__
root.mainloop()

This code places the background Image on the frame and as I scroll the frame eventually the image ends and background is white again.

I want the image to be static. To solve this I want the image to be placed on the canvas (and probably the frame should be transparent - correct me if I am wrong)

I placed the image on the canvas but image wasn't shown at all(Probably because frame was above the canvas)

Please help me.

Upvotes: 0

Views: 901

Answers (1)

acw1668
acw1668

Reputation: 46786

You can chain another callback on <Configure> event of frame.scrollable_frame and move the background image inside that callback:

def on_scroll(event):
    # get the canvas (x, y) of the top-left corner of current viewable area
    x, y = frame.canvas.canvasx(0), frame.canvas.canvasy(0)
    # move the background image
    panel1.place(x=x, y=y)

frame.scrollable_frame.bind('<Configure>', on_scroll, '+') # chain another callback

Add the above code below the line panel1.place(x=0, y=0).

Upvotes: 2

Related Questions