ext grid隐藏的列不能修改_Tkinter组件scrollbar高级特性一:自动隐藏
程序员文章站
2022-07-13 23:04:33
...
Tkinter组件scrollbar高级特性一:自动隐藏
本文旨在实现 tk.Scrollbar(ttk..Scrollbar)本身没有且实用的特性:比如 自动隐藏和显示
简单示例:
示例1 简单滚动条的实现代码
# -*- coding:utf-8 -*-
# Date: 2020/3/13
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
except 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!n"*50)
hscrollbar.config(command=test_text.yview)
root.mainloop()
特性实现:
布局管理器grid的实现方式
实现的代码如下:
# -*- coding:utf-8 -*-
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
except ImportError:
import tkinter.ttk as ttk
class 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!n"*30)
yscrollbar.config(command=test_text.yview)
root.mainloop()
注释❶:继承ttk.Scrollbar (tk.Scrollbar),重写覆盖父类的set()方法,实现自动隐藏滚动条。如下图所示:
滚动条可以看做一个在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_forget
def grid_remove(self):
"""Unmap this widget but remember the grid options."""
self.tk.call('grid', 'remove', self._w)
效果GIF图展示
布局管理器pack的实现方式
如果你说你就喜欢使用 pack 方法实现这个功能,那么也是可以不过麻烦了一些。因为 pack 中没有类似于 grid.remove() 这样既可以移除组件同时又保存组件的位置信息的方法(可能之后的版本会有)。
如果使用之前的思路的话,效果如下:
很显然在这里是行不通的。
两种pack实现方法
一:在旁边放置一个 tk.Frame 组件来装 滚动条组件。
# -*- coding:utf-8 -*-
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
except ImportError:
import tkinter.ttk as ttk
class 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!n"*26)
root.mainloop()
二:使用canvas 组件来实现
# -*- coding:utf-8 -*-
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
except ImportError:
import tkinter.ttk as ttk
class 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!n"*26)
canvas.create_window(0, 0, anchor=tk.NW, window=frame)
frame.update_idletasks()
canvas.config(scrollregion=canvas.bbox("all"))
root.mainloop()
使用 canvas 、canvas.create_window 来实现存在一些小问题,特别是内部使用 tk.Text 组件时。有机会再讲,毕竟和本文主题不搭。
推荐使用 grid 方式实现,如果就是要用 pack 实现的话建议使用 pack 的第一种实现方式。
结尾
有疑问欢迎留言询问
请不要转载,或者先询问我
请不要转载,或者先询问我