Tkinter元件scrollbar高階特性一:自動隱藏
阿新 • • 發佈:2021-01-26
技術標籤:圖形使用者介面tkintertkinterguipythoncanvas
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 **的第一種實現方式。
結尾
有疑問歡迎留言詢問