【问题标题】:Double Scrollbars in Tkinter PythonTkinter Python 中的双滚动条
【发布时间】:2020-11-09 01:15:21
【问题描述】:

我无法让 x 和 y 滚动条在 Tkinter 中与 Python 一起工作,尽管我遵循了多个示例:

  1. How to add 2 scrollbars with tkinter in python 3.4
  2. Adding a scrollbar to a group of widgets in tkinter
  3. How to make a proper double scrollbar frame in tkinter
  4. Vertical and Horizontal Scrollbars on Tkinter Widget
  5. Scrolling a Canvas widget horizontally and vertically

滚动条出现,但在窗口小于框架时不会激活。我怎样才能让它工作(见下图)?

下面是产生我的问题的最小代码(Python 3.7)

import tkinter as tk
from tkinter import ttk

big_font = ("Arial", 50)

class DoubleScrollbarFrame(ttk.Frame):

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

        super().__init__(self.parent,
                         *args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        self.canvas = tk.Canvas(self)
        self.frame = ttk.Frame(self.canvas)
        self.scroll_x = ttk.Scrollbar(self,
                                      orient = tk.HORIZONTAL,
                                      command = self.canvas.xview)
        self.scroll_y = ttk.Scrollbar(self,
                                      orient = tk.VERTICAL,
                                      command = self.canvas.yview)
        self.canvas.config(xscrollcommand = self.scroll_x.set,
                           yscrollcommand = self.scroll_y.set)
        self.canvas.create_window((0,0),
                                  window = self.frame,
                                  anchor = 'nw')
        self.frame.bind('<Configure>',
                        self.set_scrollregion)
        self.sizegrip = ttk.Sizegrip(self)

        #Test
        self.test1 = tk.Label(self.frame,
                              text = 'Test 1',
                              font = big_font)
        self.test2 = tk.Label(self.frame,
                              text = 'Test 2',
                              font = big_font)
        self.test3 = tk.Label(self.frame,
                              text = 'Test 3',
                              font = big_font)

    def position_widgets(self,
                         **kwargs):
        self.test1.grid(row = 0,
                        column = 0,
                        sticky = 'w')
        self.test2.grid(row = 1,
                        column = 0,
                        sticky = 'w')
        self.test3.grid(row = 2,
                        column = 0,
                        sticky = 'w')
        
        self.scroll_x.grid(row = 1,
                           column = 0,
                           sticky = 'ew')

        self.scroll_y.grid(row = 0,
                           column = 1,
                           sticky = 'ns')

        self.canvas.grid(row = 0,
                         column = 0,
                         sticky = 'nsew')
        
        self.frame.grid(row = 0,
                        column = 0,
                        sticky = 'nsew')

        self.sizegrip.grid(row = 1,
                           column = 1,
                           sticky = 'se')

    def set_scrollregion(self,
                         event):
        print('Frame Dimensions: {} x {}'.format(self.frame.winfo_width(),
                                                 self.frame.winfo_height()))
        print('Canvas Dimensions: {} x {}'.format(self.canvas.winfo_width(),
                                                  self.canvas.winfo_height()))
        self.canvas.configure(scrollregion = self.canvas.bbox('all'))

class MainApp(tk.Tk):

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

        super().__init__(*args,
                         **kwargs)

        #Set widgets to fill main window such that they are
        #all the same size
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.create_widgets()
        self.position_widgets()

    def create_widgets(self):
        self.frame = DoubleScrollbarFrame(self)

    def position_widgets(self):
        self.frame.grid(row = 0,
                        column = 0,
                        sticky = 'nsew')

    def exit(self):
        self.destroy()

if __name__ == '__main__':

    #Create GUI
    root = MainApp()

    #Run program
    root.mainloop()

【问题讨论】:

  • 你做了什么来调试这个?例如,您是否验证了 scrollregion 正在更新为正确的值?
  • 请不要问“奖励”问题——一个好的问题只针对一个问题。
  • @BryanOakley 我删除了附加问题,添加了对我已查看的链接的引用,并在set_scrollregion 中添加了打印输出。该方法仅输出:Frame Dimensions: 193 x 243 Canvas Dimensions: 1 x 1,并且在我调整窗口大小时不会重新打印。
  • 您没有回答您是否已验证scrollregion 正在正确更新的问题。
  • @BryanOakley 如何验证scrollregion 是否已正确更新?请告诉我该怎么做。

标签: python tkinter scrollbar


【解决方案1】:

问题出在DoubleScrollbarFrame.position_widgets里面的这几行代码中:

self.frame.grid(row = 0,
                column = 0,
                sticky = 'nsew')

这会从画布上移除对小部件的控制,并将控制权交给grid。它不再是一个画布对象,所以self.canvas.bbox("all") 正在返回(0, 0, 1, 1)。如果滚动区域设置不正确,滚动条不知道要滚动多少。

解决方法很简单:不要在self.frame 上调用grid

【讨论】:

  • 太棒了!谢谢!这现在完美无缺。我读了Alejandro RodasTkinter GUI Application Development Cookbook,他说“......我们没有调用任何几何管理器来绘制框架,因为create_window() 方法为我们做了这个。”我不知道调用几何管理器会将控制权从画布传递到网格!我希望有人在书或教程中提到这一点!
猜你喜欢
  • 2016-11-23
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-13
  • 2017-03-24
相关资源
最近更新 更多