

### 前提

TkinterでCanvasとScrollbarを使用してCheckbutton入りのリストボックスを作成しています。

### 実現したいこと

Scrollbarのスクロール有効範囲を広げたいです。  
現状はスクロールバー上にカーソルがある場合のみスクロールが効きます。  
CanvasやCheckbutton上にカーソルがあってもスクロールが効くようにしたいです。

### 該当のソースコード

[code]

    import tkinter as tk
    from tkinter import ttk
    
    class ItemListFrame(tk.Frame):
        
        def __init__(self, master):
            tk.Frame.__init__(self, master, width=100, height=100,
                              borderwidth=1, relief=tk.GROOVE)
            
            #ウィジェット配置
            self.place_widget()
            
        def place_widget(self):
            
            #Canvas作成
            canvas = tk.Canvas(master=self, width=300, height=200, bg='white')
            canvas.grid(row=0, column=0)
            
            #スクロールバー
            vbar = ttk.Scrollbar(master=self, orient=tk.VERTICAL) #縦方向
            vbar.grid(row=0, column=1, sticky=tk.NS)
            
            #スクロールバーの制御をCanvasに通知する処理
            vbar.config(command=canvas.yview)
            
            #Canvasの可動域をスクロールバーに通知する処理
            canvas.config(yscrollcommand=vbar.set)
            
            #スクロール可動域
            canvas.config(scrollregion=(0,0, 300, 5000))
            
            #Frameを作成しcanvasに配置
            frame = tk.Frame(master=canvas, bg='white')
            canvas.create_window((0,0), window=frame, anchor=tk.NW, width=canvas.cget('width'))
            
            self.vars = []
            for i in range(50):
                var = tk.BooleanVar()
                self.vars.append(var)
                check_button = tk.Checkbutton(master=frame, text=i, variable=var)
                check_button.grid(row=i, column=0)
                
    root = tk.Tk()
    frame = ItemListFrame(root)
    frame.pack()
    root.mainloop()
    
[/code]

### 補足情報（FW/ツールのバージョンなど）

Python3.10  
Windows 10  
VScode


CC BY-SA 4.0
2022-07-11T01:04:02.843
89895
2022-07-11T01:54:40.097
2022-07-11T01:07:16.407
3060
53469
question
python tkinter
tkinterでスクロールバー(Scrollbar)の有効範囲を広げたい


ソースコードが意図通りだという前提で、マウスホイールスクロールを対応すると、以下のようになります。

このケースの場合、canvas,frame,各チェックボタンに""イベントをバインドして、スクロール移動量に反映します。

[code]

    import tkinter as tk
    from tkinter import ttk
    
    
    class ItemListFrame(tk.Frame):
    
        def __init__(self, master):
            tk.Frame.__init__(self, master, width=100, height=100,
                              borderwidth=1, relief=tk.GROOVE)
    
            # ウィジェット配置
            self.place_widget()
    
        def place_widget(self):
            inframe = tk.Frame(master=self, bg='white')
            inframe.grid(row=0, column=0)
    
            # Canvas作成
            canvas = tk.Canvas(master=inframe, width=300, height=200, bg='white')
            canvas.grid(row=0, column=0)
    
            # スクロールバー
            vbar = ttk.Scrollbar(master=inframe, orient=tk.VERTICAL)  # 縦方向
            vbar.grid(row=0, column=1, sticky=tk.NS)
    
            # スクロールバーの制御をCanvasに通知する処理
            vbar.config(command=canvas.yview)
    
            # Canvasの可動域をスクロールバーに通知する処理
            canvas.config(yscrollcommand=vbar.set)
    
            # スクロール可動域
            canvas.config(scrollregion=(0, 0, 300, 5000))
    
            # Frameを作成しcanvasに配置
            frame = tk.Frame(master=canvas, bg='white')
            canvas.create_window((0, 0), window=frame,
                                 anchor=tk.NW, width=canvas.cget('width'))
            frame.bind("<MouseWheel>",
                       lambda event: self._mousewheel_(event, canvas))
            canvas.bind("<MouseWheel>",
                        lambda event: self._mousewheel_(event, canvas))
    
            self.vars = []
            for i in range(50):
                var = tk.BooleanVar()
                self.vars.append(var)
                check_button = tk.Checkbutton(master=frame, text=i, variable=var)
                check_button.grid(row=i, column=0)
                check_button.bind("<MouseWheel>",
                                  lambda event: self._mousewheel_(event, canvas))
    
        def _mousewheel_(self, event, canvas):
            canvas.yview_scroll(int(-1*(event.delta/120)), "units")
            print(event)
    
    
    root = tk.Tk()
    frame = ItemListFrame(root)
    frame.pack()
    root.mainloop()
    
    
[/code]


CC BY-SA 4.0
2022-07-11T01:54:40.097
89900
2022-07-11T01:54:40.097
32891
89895
answer