如何在Linux的tkinter.Canvas.create_window()小部件中为ttk.Frame启用MouseWheel滚动?

时间:2018-09-12 17:49:06

标签: python tkinter tkinter-canvas

预期的行为: 我希望能够使用鼠标滚轮滚动画布。

问题: 当我的图像粘贴到位于ttk.Label中的self.loadImage()的{​​{1}}小部件(请参阅ttk.Frame方法2 )上时,鼠标滚轮滚动停止工作。 tk.Canvas.create_window()小部件。但是,使用方法tk.Canvas.create_image()将图像粘贴到画布上时,鼠标滚轮才能工作(请参阅self.loadImage()方法1 )。在Linux上使用Python 3.6.5和Tk.TkVersion 8.6遇到的问题。

问题:为什么方法2不起作用?如何使其工作?

我编写了以下测试脚本来说明我的问题:

import tkinter as tk
import tkinter.ttk as ttk
import platform

from PIL import Image, ImageTk


class App(ttk.Frame):

    def __init__( self, parent, *args, **kwargs ):

        super().__init__( parent, style='App.TFrame', borderwidth=10,
                          relief='raised', width=390, height=390 )
        self.style = None
        self.vscrollbar = None
        self.canvas = None
        self.canvas_window = None
        self.interior = None

        self.setStyle()
        self.createWidgets()
        self.loadImage()
        self.createBinding()

        self.rowconfigure( 0, weight=1 )
        self.columnconfigure( 0, weight=1 )


    def setStyle(self):
        self.style = ttk.Style()
        self.style.configure( 'App.TFrame', background='pink' )
        self.style.configure( 'interior.TFrame', background='red' )


    def createWidgets(self):
        self.vscrollbar = ttk.Scrollbar(self, orient='vertical')
        self.vscrollbar.pack( side='right', fill='y', expand='false' )

        self.canvas = tk.Canvas( self,
                                 bd=0, #no border
                                 highlightthickness=0, #no focus highlight
                                 yscrollcommand=self.vscrollbar.set,#use self.vscrollbar
                                 background='blue', #improves resizing appearance
                               )
        self.canvas.pack( side='left', fill='both', expand='true' )
        self.vscrollbar.config( command=self.canvas.yview )

        self.canvas.xview_moveto( 0 )
        self.canvas.yview_moveto( 0 )

        self.interior = ttk.Frame( self.canvas,
                                   style='interior.TFrame',
                                   borderwidth=10,
                                   relief=tk.SUNKEN )

        self.canvas_window = self.canvas.create_window(
            0, 0, window=self.interior, anchor='nw' )


    def loadImage(self):
        image = './test_image.png'
        image = Image.open(image)
        self.image = ImageTk.PhotoImage(image)
        width, height = image.size
        print(width, height)
        self.canvas.config( scrollregion=(0, 0, width, height) )

        #Method 1
        #self.canvas_obj_id = self.canvas.create_image( 0, 0, image=self.image,
        #                                               anchor=tk.NW )

        #Method 2
        self.label = ttk.Label(self.interior, image=self.image )
        self.label.grid(row=0, column=0, sticky='nsew')


    def createBinding(self):
        if platform.system() == 'Linux':
            self.canvas.bind('<Button-4>', self._on_mousewheel_linux)
            self.canvas.bind('<Button-5>', self._on_mousewheel_linux)
            print('Binded <Button-4> and <Button-5>')
        elif platform.system() == 'Windows':
            self.canvas.bind('<MouseWheel>', self._on_mousewheel_windows)


    def _on_mousewheel_linux(self, event):
        if event.num == 4: self.canvas.yview_scroll( -1, "units" )
        if event.num == 5: self.canvas.yview_scroll(  1, "units" )


    def _on_mousewheel_windows(self, event):
        self.canvas.yview_scroll( int(-1*(event.delta/120)), "units" )


if __name__ == '__main__':
    root = tk.Tk()
    app = App( root )
    app.grid( row=0, column=0, sticky='nsew' )
    root.rowconfigure( 0, weight=1 )
    root.columnconfigure( 0, weight=1 )

    root.mainloop()

0 个答案:

没有答案