ext grid隐藏的列不能修改_Tkinter组件scrollbar高级特性一:自动隐藏

本文旨在实现 tk.Scrollbar(ttk.Scrollbar)本身没有且实用的特性:比如 自动隐藏和显示



简单示例:

示例1 简单滚动条的实现代码

# -*- coding:utf-8 -*-# Date: 2020/3/13try:    import Tkinter as tkexcept ImportError:    import tkinter as tktry:    import ttkexcept ImportError:    import tkinter.ttk as ttk    root = tk.Tk()root.geometry("200x300+500+600")hscrollbar = tk.Scrollbar(root)hscrollbar.pack(side=tk.RIGHT, fill="y")test_text = tk.Text(root, wrap=tk.NONE, yscrollcommand=hscrollbar.set)test_text.pack(side=tk.TOP, fill=tk.BOTH, expand=True)test_text.insert(tk.END, "This is tkinter or Tkinter!"*50)hscrollbar.config(command=test_text.yview)root.mainloop()
911459d3ea3f1560963eef45c00cf440.png


特性实现:


布局管理器grid的实现方式

实现的代码如下:

# -*- coding:utf-8 -*-try:    import Tkinter as tkexcept ImportError:    import tkinter as tktry:    import ttkexcept ImportError:    import tkinter.ttk as ttkclass AutoHideScrollbar(ttk.Scrollbar):    def set(self,upper,lower):  # ❶        if float(upper) <= 0.0 and float(lower) >= 1.0:            self.grid_remove() # ❷        else:            self.grid()        ttk.Scrollbar.set(self,upper,lower)    if __name__ == '__main__':    root = tk.Tk()    root.geometry("200x300+500+600")    root.rowconfigure(0, weight=1)    root.columnconfigure(0, weight=1)    yscrollbar = AutoHideScrollbar(root)    yscrollbar.grid(row=0, column=1, sticky=tk.N + tk.S)        test_text = tk.Text(root, wrap=tk.NONE, yscrollcommand=yscrollbar.set)    test_text.grid(row=0, column=0, sticky=tk.N + tk.E + tk.W + tk.S)    test_text.insert(tk.END, "This is tkinter or Tkinter!"*30)    yscrollbar.config(command=test_text.yview)    root.mainloop()

注释❶:继承ttk.Scrollbar (tk.Scrollbar),重写覆盖父类的set()方法,实现自动隐藏滚动条。如下图所示:

db027a37e07751d88003d548fe6453a2.png

滚动条可以看做一个在0到1之间从上到下的单向坐标系,upper 起始值为0,表示滚动条上方在坐标系中的值(浮点值表示);lower 表示滚动条最下方在坐标系中对应的值,最大为1。

而当upper=0,lower=1时,就表示滚动条占据了整个空间,此时就可以触发他的隐藏方法。

注释❷:需要注意的是,隐藏滚动条组件的方法是用的grid_remove(),而不能使用grid_forget()方法。

具体原因Tkinter中源码写得很清楚:

def grid_forget(self):    """Unmap this widget."""    self.tk.call('grid', 'forget', self._w)forget = grid_forgetdef grid_remove(self):    """Unmap this widget but remember the grid options."""    self.tk.call('grid', 'remove', self._w)

效果GIF图展示

7870a7218f2a4259aac8fbaad9c3c49c.gif

布局管理器pack的实现方式

如果你说你就喜欢使用 pack 方法实现这个功能,那么也是可以不过麻烦了一些。因为 pack 中没有类似于 grid.remove() 这样既可以移除组件同时又保存组件的位置信息的方法(可能之后的版本会有)。

如果使用之前的思路的话,效果如下:

b8f690c565331b1f6f3fcf5f54117408.gif

很显然在这里是行不通的。


两种pack实现方法

一:在旁边放置一个 tk.Frame 组件来装 滚动条组件。

# -*- coding:utf-8 -*-try:    import Tkinter as tkexcept ImportError:    import tkinter as tktry:    import ttkexcept ImportError:    import tkinter.ttk as ttkclass AutoHideScrollbar(ttk.Scrollbar):    def set(self,upper,lower):        if float(upper) <= 0.0 and float(lower) >= 1.0:            self.pack_forget()        else:            self.pack(side="right", fill="y")        ttk.Scrollbar.set(self,upper,lower)if __name__ == '__main__':    root = tk.Tk()    root.geometry("200x300+500+600")        frame = tk.Frame(root) # 用于放置scrollbar组件    frame.pack(side="right", fill="y")    vscrollbar = AutoHideScrollbar(frame)    vscrollbar.pack(side=tk.RIGHT, fill="y")    test_text = tk.Text(root, wrap=tk.NONE, yscrollcommand=vscrollbar.set)    test_text.pack(fill=tk.BOTH, expand=True)    vscrollbar.config(command=test_text.yview)    test_text.insert(tk.END, "This is tkinter or Tkinter!"*26)            root.mainloop()

二:使用canvas 组件来实现

# -*- coding:utf-8 -*-try:    import Tkinter as tkexcept ImportError:    import tkinter as tktry:    import ttkexcept ImportError:    import tkinter.ttk as ttkclass AutoHideScrollbar(ttk.Scrollbar):    def set(self,upper,lower):        if float(upper) <= 0.0 and float(lower) >= 1.0:            self.pack_forget()        else:            if self.cget("orient") == tk.HORIZONTAL:                self.pack(fill=tk.X, side=tk.BOTTOM)            else:                self.pack(fill=tk.Y, side=tk.RIGHT)        ttk.Scrollbar.set(self,upper,lower)            def grid(self, **kw): #        raise AttributeError("{} has no attribute {}".format(AutoHideScrollbar.__name__, "'grid'"))    def place(self, **kw):        raise AttributeError("{} has no attribute {}".format(AutoHideScrollbar.__name__, "'place'"))if __name__ == '__main__':       root = tk.Tk()    vscrollbar = AutoHideScrollbar(root)    canvas = tk.Canvas(root, yscrollcommand=vscrollbar.set)    canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)    vscrollbar.config(command=canvas.yview)        frame = tk.Frame(canvas)    test_text = tk.Text(frame, wrap=tk.NONE)    test_text.pack(fill=tk.BOTH, expand=True)    test_text.insert(tk.END, "This is tkinter or Tkinter!"*26)        canvas.create_window(0, 0, anchor=tk.NW, window=frame)    frame.update_idletasks()    canvas.config(scrollregion=canvas.bbox("all"))        root.mainloop()

使用 canvascanvas.create_window 来实现存在一些小问题,特别是内部使用 tk.Text 组件时。有机会再讲,毕竟和本文主题不搭。

推荐使用 grid 方式实现,如果就是要用 pack 实现的话建议使用 pack 的第一种实现方式。



结尾

有疑问欢迎留言询问

请不要转载,或者先询问我请不要转载,或者先询问我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值