How to prevent background scrolling in canvas?

2019-03-03 08:57发布

问题:

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()

回答1:

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,"))