I am using ttk.Scrollbar to scroll elements inside a Tkinter.Canvas. Unfortunately a background image of this canvas will also scroll. How can I prevent this?
Here is an example of what I use:
import Tkinter as tk
from ttk import *
# first canvas with scrollbar
root = tk.Tk()
canv1 = tk.Canvas(root, width=200, height=200, bg='green')
sbar = Scrollbar(root, orient="vertical")
sbar.config(command=canv1.yview)
sbar.pack(side="right", fill="y")
canv1.config(yscrollcommand=sbar.set)
canv1.pack(side="right", fill="y")
# background of dirst canvas
photo_content2 = tk.PhotoImage(file = './sample_image.gif')
canv1.create_image(115,300, image=photo_content2)
# scrollable second canvas insode first
canv2 = tk.Canvas(canv1, width=50, height=30, bg='red')
canv2.pack()
canv1.create_window(20,20, window=canv2)
canv1.config(scrollregion=(0,0,300,1000))
root.mainloop()
Scrolling affects everything drawn on the canvas. You can't add a background image that doesn't scroll along with everything else.
That being said, you can create a function that moves the background image after the scrolling happens, and you get the same effect as if the image didn't scroll.
You do this by connecting the scrollbar to a custom function rather than directly to the widgets yview
and/or xview
commands. In this function you can call the yview
and xview
commands as normal, and then re-position the background image.
For example, this is how you would handle vertical scrolling; horizontal scrolling would work in a similar way:
def custom_yview(*args, **kwargs):
canvas.yview(*args, **kwargs)
x = canvas.canvasx(0)
y = canvas.canvasy(0)
canvas.coords("background", x,y)
canvas = tk.Canvas(...)
vsb = tk.Scrollbar(orient="vertical", command=custom_yview)
canvas.create_image(..., tags=("background,"))