Canvas leaves scrollregion if scrolled with mouswh

2019-09-18 10:21发布

问题:

Problem: you can scroll upwards even though the first item should be at the very top of the canvas

How to reproduce the problem: have at least one item on the canvas and scroll using the mouse ( press space to make an item )

Note: the problem ceases once the items are wider than the canvas itself

Sample code

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.bind("<MouseWheel>", self.scroll)
        self.bind("<KeyPress>", self.keypressed)
        self.TargetCanvas = None
        self.makeui()

    def makeui(self):
        self.Canvas = tk.Canvas(self, bg = "white")
        self.Canvas.grid(row = 0, column = 0, sticky = "W")
        sby = tk.Scrollbar(self, orient = "vertical", command  = self.Canvas.yview)
        sby.grid(row = 0, column = 1, sticky = "ns")
        self.Canvas.configure(yscrollcommand = sby.set)
        self.CanvFrame = tk.Frame(self.Canvas, bg = "white")
        self.Canvas.create_window((0, 0), window = self.CanvFrame, anchor = "nw")
        self.CanvFrame.bind("<Configure>", lambda event: self.Canvas.configure(scrollregion = self.Canvas.bbox("all")))
        self.Canvas.bind("<Enter>", lambda event: self.settarget(event, True))
        self.Canvas.bind("<Leave>", lambda event: self.settarget(event, False))
        tk.Label(self, text = "space = add item, c = clear all").grid(row = 1, column = 0)



    def settarget(self, event, check):
        if check:
            self.TargetCanvas = event.widget
        else:
            self.TargetCanvas = None

    def scroll(self, event):
        if self.TargetCanvas is not None:
            direction = 0
            if event.num == 5 or event.delta == -120:
                direction = 1
            if event.num == 4 or event.delta == 120:
                 direction = -1
            self.TargetCanvas.yview_scroll(direction, tk.UNITS)

    def keypressed(self, event):
        if event.keysym == "space":
           self.additem()
        elif event.keysym == "c":
            self.clearall()

    def clearall(self):
        for i in self.CanvFrame.winfo_children():
            i.destroy()
        x = tk.Label(self.CanvFrame)
        #kick in frame resizing
        x.pack()
        self.update()
        self.Canvas.configure(scrollregion = self.Canvas.bbox("all"))
        x.destroy()


    def additem(self):
        tk.Label(self.CanvFrame, text = "asd").pack(side = tk.TOP)


def main():
    App().mainloop()

if __name__ == "__main__":
   main()