1. 程式人生 > 其它 >Tkinter元件scrollbar高階特性一:自動隱藏

Tkinter元件scrollbar高階特性一:自動隱藏

技術標籤:圖形使用者介面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()

ttk



特性實現:


佈局管理器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()**方法,實現自動隱藏滾動條。如下圖所示:

ttk2

滾動條可以看做一個在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圖展示

效果展示gif


佈局管理器pack的實現方式

如果你說你就喜歡使用 **pack **方法實現這個功能,那麼也是可以不過麻煩了一些。因為 pack 中沒有類似於 **grid.remove() **這樣既可以移除元件同時又儲存元件的位置資訊的方法(可能之後的版本會有)。

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

pack展示

很顯然在這裡是行不通的。


兩種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()

使用 canvascanvas.create_window 來實現存在一些小問題,特別是內部使用 tk.Text 元件時。有機會再講,畢竟和本文主題不搭。

推薦使用 grid 方式實現,如果就是要用 pack 實現的話建議使用 **pack **的第一種實現方式。



結尾

有疑問歡迎留言詢問