2017-12-27 521 views
0

此代碼很好,但我想使用鼠標滾輪滾動頁面,就像我們使用Chrome一樣,當鼠標指針鼠標位於頁面中間。 enter image description here如何在窗口中心使用鼠標滾輪在python中使用tkinter滾動GUI

import tkinter as tk 
from random import randint 


class ScrolledFrame(tk.Frame): 

    def __init__(self, parent, vertical=True, horizontal=False): 
     super().__init__(parent) 
     self._canvas = tk.Canvas(self) 
     self._canvas.grid(row=0, column=0, sticky='news') # changed 
     self._vertical_bar = tk.Scrollbar(self, orient='vertical', command=self._canvas.yview) 
     if vertical: 
      self._vertical_bar.grid(row=0, column=1, sticky='ns') 
     self._canvas.configure(yscrollcommand=self._vertical_bar.set) 
     self._horizontal_bar = tk.Scrollbar(self, orient='horizontal', command=self._canvas.xview) 
     if horizontal: 
      self._horizontal_bar.grid(row=1, column=0, sticky='we') 
     self._canvas.configure(xscrollcommand=self._horizontal_bar.set) 
     self._vertical_bar.config(command=self._canvas.yview) 
     self.inner = tk.Frame(self._canvas, bg='red') 
     self._window = self._canvas.create_window((0, 0), window=self.inner, anchor='nw') 
     self.columnconfigure(0, weight=1) # changed 
     self.rowconfigure(0, weight=1) # changed 
     self.inner.bind('<Configure>', self.resize) 
     self._canvas.bind('<Configure>', self.frame_width) 

    def frame_width(self, event): 
     canvas_width = event.width 
     self._canvas.itemconfig(self._window, width=canvas_width) 

    def resize(self, event=None): 
     self._canvas.configure(scrollregion=self._canvas.bbox('all')) 


class Question: 
    def __init__(self, parent, question, answer): 
     self.parent = parent 
     self.question = question 
     self.answer = answer 
     self.create_widgets() 

    def get_input(self): 
     value = self.entry.get() 
     print('value:', value) 
     if value == self.answer: 
      print("Right it's " + self.answer) 
      self.label['text'] = self.question + "Right it's " + self.answer 
     else: 
      self.label['text'] = "Sorry, it was " + self.answer 

    def create_widgets(self): 
     self.labelframe = tk.LabelFrame(self.parent, text="Domanda:") 
     self.labelframe.pack(fill="both", expand=True) 
     self.label = tk.Label(self.labelframe, text=self.question) 
     self.label.pack(expand=True, fill='both') 
     self.entry = tk.Entry(self.labelframe) 
     self.entry.pack() 
     self.entry.bind("<Return>", lambda x: self.get_input()) 


root = tk.Tk() 
root.title("Quiz") 
root.geometry("400x300") 
window = ScrolledFrame(root) 
window.pack(expand=True, fill='both') 

for i in range(10): 
    one = randint(1, 10) 
    two = randint(1, 10) 
    Question(window.inner, "How is the result of {} + {} ?".format(one, two), str(one + two)) 

root.mainloop() 
+0

我不想只是滾動條,但我想要的頁面,當您使用鼠標滾輪在畫布上滾動。 –

+0

夠公平的。但請參閱[Python tkinter綁定鼠標滾輪](https://stackoverflow.com/q/17355902/7032856)。 – Nae

+0

請提供[最小,完整和可驗證示例](https://stackoverflow.com/help/mcve)。 – Nae

回答

0

我發現如何使它

好吧,我遇到了一些問題,詢問如何使它,但由於https://code.activestate.com/recipes/580640-scrolling-frame-with-mouse-wheel-support/我在使鼠標滾輪工作,因爲我打算succeded。如果可以幫助,那麼這個例子就在這裏。

import tkinter as tk 
from random import randint 

# --- classes --- 
try: 
    from Tkinter import Canvas, Frame 
    from ttk import Scrollbar 

    from Tkconstants import * 
except ImportError: 
    from tkinter import Canvas, Frame 
    from tkinter.ttk import Scrollbar 

    from tkinter.constants import * 

import platform 

OS = platform.system() 


class Mousewheel_Support(object): 

    # implemetation of singleton pattern 
    _instance = None 

    def __new__(cls, *args, **kwargs): 
     if not cls._instance: 
      cls._instance = object.__new__(cls) 
     return cls._instance 

    def __init__(self, root, horizontal_factor=2, vertical_factor=2): 

     self._active_area = None 

     if isinstance(horizontal_factor, int): 
      self.horizontal_factor = horizontal_factor 
     else: 
      raise Exception("Vertical factor must be an integer.") 

     if isinstance(vertical_factor, int): 
      self.vertical_factor = vertical_factor 
     else: 
      raise Exception("Horizontal factor must be an integer.") 

     if OS == "Linux": 
      root.bind_all('<4>', self._on_mousewheel, add='+') 
      root.bind_all('<5>', self._on_mousewheel, add='+') 
     else: 
      # Windows and MacOS 
      root.bind_all("<MouseWheel>", self._on_mousewheel, add='+') 

    def _on_mousewheel(self, event): 
     if self._active_area: 
      self._active_area.onMouseWheel(event) 

    def _mousewheel_bind(self, widget): 
     self._active_area = widget 

    def _mousewheel_unbind(self): 
     self._active_area = None 

    def add_support_to(self, widget=None, xscrollbar=None, yscrollbar=None, what="units", horizontal_factor=None, vertical_factor=None): 
     if xscrollbar is None and yscrollbar is None: 
      return 

     if xscrollbar is not None: 
      horizontal_factor = horizontal_factor or self.horizontal_factor 

      xscrollbar.onMouseWheel = self._make_mouse_wheel_handler(widget, 'x', self.horizontal_factor, what) 
      xscrollbar.bind('<Enter>', lambda event, scrollbar=xscrollbar: self._mousewheel_bind(scrollbar)) 
      xscrollbar.bind('<Leave>', lambda event: self._mousewheel_unbind()) 

     if yscrollbar is not None: 
      vertical_factor = vertical_factor or self.vertical_factor 

      yscrollbar.onMouseWheel = self._make_mouse_wheel_handler(widget, 'y', self.vertical_factor, what) 
      yscrollbar.bind('<Enter>', lambda event, scrollbar=yscrollbar: self._mousewheel_bind(scrollbar)) 
      yscrollbar.bind('<Leave>', lambda event: self._mousewheel_unbind()) 

     main_scrollbar = yscrollbar if yscrollbar is not None else xscrollbar 

     if widget is not None: 
      if isinstance(widget, list) or isinstance(widget, tuple): 
       list_of_widgets = widget 
       for widget in list_of_widgets: 
        widget.bind('<Enter>', lambda event: self._mousewheel_bind(widget)) 
        widget.bind('<Leave>', lambda event: self._mousewheel_unbind()) 

        widget.onMouseWheel = main_scrollbar.onMouseWheel 
      else: 
       widget.bind('<Enter>', lambda event: self._mousewheel_bind(widget)) 
       widget.bind('<Leave>', lambda event: self._mousewheel_unbind()) 

       widget.onMouseWheel = main_scrollbar.onMouseWheel 

    @staticmethod 
    def _make_mouse_wheel_handler(widget, orient, factor=1, what="units"): 
     view_command = getattr(widget, orient + 'view') 

     if OS == 'Linux': 
      def onMouseWheel(event): 
       if event.num == 4: 
        view_command("scroll", (-1) * factor, what) 
       elif event.num == 5: 
        view_command("scroll", factor, what) 

     elif OS == 'Windows': 
      def onMouseWheel(event): 
       view_command("scroll", (-1) * int((event.delta/120) * factor), what) 

     elif OS == 'Darwin': 
      def onMouseWheel(event): 
       view_command("scroll", event.delta, what) 

     return onMouseWheel 


class Scrolling_Area(Frame, object): 

    def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed=2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, background=None, inner_frame=Frame, **kw): 
     Frame.__init__(self, master, class_="Scrolling_Area", background=background) 

     self.grid_columnconfigure(0, weight=1) 
     self.grid_rowconfigure(0, weight=1) 

     self._width = width 
     self._height = height 

     self.canvas = Canvas(self, background=background, highlightthickness=0, width=width, height=height) 
     self.canvas.grid(row=0, column=0, sticky=N + E + W + S) 

     if scroll_vertically: 
      if yscrollbar is not None: 
       self.yscrollbar = yscrollbar 
      else: 
       self.yscrollbar = Scrollbar(self, orient=VERTICAL) 
       self.yscrollbar.grid(row=0, column=1, sticky=N + S) 

      self.canvas.configure(yscrollcommand=self.yscrollbar.set) 
      self.yscrollbar['command'] = self.canvas.yview 
     else: 
      self.yscrollbar = None 

     if scroll_horizontally: 
      if xscrollbar is not None: 
       self.xscrollbar = xscrollbar 
      else: 
       self.xscrollbar = Scrollbar(self, orient=HORIZONTAL) 
       self.xscrollbar.grid(row=1, column=0, sticky=E + W) 

      self.canvas.configure(xscrollcommand=self.xscrollbar.set) 
      self.xscrollbar['command'] = self.canvas.xview 
     else: 
      self.xscrollbar = None 

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

     self.innerframe = inner_frame(self.canvas, **kw) 
     self.innerframe.pack(anchor=anchor) 

     self.canvas.create_window(0, 0, window=self.innerframe, anchor='nw', tags="inner_frame") 

     self.canvas.bind('<Configure>', self._on_canvas_configure) 

     Mousewheel_Support(self).add_support_to(self.canvas, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar) 

    @property 
    def width(self): 
     return self.canvas.winfo_width() 

    @width.setter 
    def width(self, width): 
     self.canvas.configure(width=width) 

    @property 
    def height(self): 
     return self.canvas.winfo_height() 

    @height.setter 
    def height(self, height): 
     self.canvas.configure(height=height) 

    def set_size(self, width, height): 
     self.canvas.configure(width=width, height=height) 

    def _on_canvas_configure(self, event): 
     width = max(self.innerframe.winfo_reqwidth(), event.width) 
     height = max(self.innerframe.winfo_reqheight(), event.height) 

     self.canvas.configure(scrollregion="0 0 %s %s" % (width, height)) 
     self.canvas.itemconfigure("inner_frame", width=width, height=height) 

    def update_viewport(self): 
     self.update() 

     window_width = self.innerframe.winfo_reqwidth() 
     window_height = self.innerframe.winfo_reqheight() 

     if self._width is None: 
      canvas_width = window_width 
     else: 
      canvas_width = min(self._width, window_width) 

     if self._height is None: 
      canvas_height = window_height 
     else: 
      canvas_height = min(self._height, window_height) 

     self.canvas.configure(scrollregion="0 0 %s %s" % (window_width, window_height), width=canvas_width, height=canvas_height) 
     self.canvas.itemconfigure("inner_frame", width=window_width, height=window_height) 


class Question: 

    def __init__(self, parent, question, answer): 
     self.parent = parent 
     self.question = question 
     self.answer = answer 
     self.create_widgets() 

    def get_input(self): 
     value = self.entry.get() 
     print('value:', value) 
     if value == self.answer: 
      print("Right it's " + self.answer) 
      self.label['text'] = self.question + "Right it's " + self.answer 
     else: 
      self.label['text'] = "Sorry, it was " + self.answer 

    def create_widgets(self): 
     self.labelframe = tk.LabelFrame(self.parent, text="Domanda:") 
     self.labelframe.pack(fill="both", expand=True) 

     self.label = tk.Label(self.labelframe, text=self.question) 
     self.label.pack(expand=True, fill='both') 

     self.entry = tk.Entry(self.labelframe) 
     self.entry.pack() 
     self.entry.bind("<Return>", lambda x: self.get_input()) 

     # self.button = tk.Button(self.labelframe, text="Click", command=self.get_input) 
     # self.button.pack() 

# --- main --- 


root = tk.Tk() 
root.title("Quiz") 
root.geometry("400x300") 


window = Scrolling_Area(root) 
window.pack(expand=True, fill='both') 


for i in range(10): 
    one = randint(1, 10) 
    two = randint(1, 10) 
    Question(window.innerframe, "How is the result of {} + {} ?".format(one, two), str(one + two)) 

domande = [("Qual è la prima leva del marketing mix? (prodotto o prezzo?", "prodotto")] 


for d, r in domande: 
    Question(window.innerframe, d, r) 


root.mainloop() 
相關問題