Tkinter (41) 定製和建立 ttk 主題和樣式

Jason990420發表於2020-08-28

三個抽象級別

  • 元素 element, 可能是部件的某些類似的選項, 如外框, 聚焦的顏色, 部件的間隔, 標籤等等
  • 樣式 style 用來說明某一類部件的外觀, 類別基本上就是部件的 class 分類, 由各個元素所組成.
  • 主題 theme 代表著所有部件的外觀與感覺, 由各個樣式所組成.
>>> from tkinter import ttk
>>> s=ttk.Style()
>>> s.theme_names() # 列出所有現有的主題
('clam', 'alt', 'default', 'classic')
>>> s.theme_use() # 現在所使用的主題 (預設主題)
'default'
>>> s.theme_use('alt') # 使用主題
>>> s.theme_use()
'alt'


ttk 元素 element

  1. 使用部件的winfo_class() 方法, 返回部件類別名稱, 再以物件ttk.Style()layout() 方法, 部件類別名稱為引數, 返回該類別的佈局內容, 某些部件沒有佈局, 會產生tk.TclError 異常.

  2. 佈局的內容為 tuple (eltName, d) 的列表, eltName 為元素名稱, d 為元素的說明字典. 字典中可能有三個鍵

  • 'sticky' 說明該元素的貼近方向, 可以是 'n'/'s'/'w'/'e' 的組合
  • 'side' 說明各個元素的位置, 可以是 'left'/'right'/'top'/'bottom'
  • 'children' 說明下層的元素, 其格式同上層的佈局一樣, 為 tuple (eltName, d) 的列表
  1. 樣式的選項可以使用物件 ttk.Style()element_options(styleName) 方法返回前有 '-' 的選項字串 tuple.
>>> from tkinter import ttk
>>> s = ttk.Style()
>>> d = s.element_options('Button.highlight')
>>> d
('-highlightcolor', '-highlightthickness')
  1. 元素的選項值可以使用物件 ttk.Style()lookup(layoutName, optName) 查詢.
>>> from tkinter import ttk
>>> s = ttk.Style()
>>> s.lookup('Button.highlight', 'highlightcolor')
'#d9d9d9'
  1. 以下例說明, 在使用主題為 'classic', 佈局為TButton, 由外至內共分四層:
第一層為 'Button.hightlight', 'sticky':'nswe', 內層 'children'
第二層為 'Button.border', 'sticky':'nswe', 'border':'1', 內層 'children'
第三層為 'Button.padding', 'sticky':'nswe', 內層 'children'
第四層為 'Button.label', 'sticky':'nswe'
>>> from tkinter import ttk
>>> s = ttk.Style()
>>> s.theme_use('classic')
>>> b = ttk.Button(None, text='Yo')
>>> bClass = b.winfo_class()
>>> bClass
'TButton'
>>> layout = s.layout('TButton')
>>> layout
[
    (
        'Button.highlight',
        {
            'children':
                [
                    (
                        'Button.border',
                        {
                            'border':'1',
                            'children':
                                [
                                    (
                                        'Button.padding',
                                        {
                                            'children':
                                                [
                                                    (
                                                        'Button.label',
                                                        {
                                                            'sticky': 'nswe'
                                                        }
                                                    )
                                                ],
                                            'sticky': 'nswe'
                                        }
                                    )
                                ],
                            'sticky': 'nswe'
                        }
                    )
                ],
            'sticky': 'nswe'
        }
    )
]


ttk 樣式 ttk.Style

  1. 預設的樣式名稱為部件名稱前加一個 'T', 除了以下幾個不同.
  • TPanedwindow
  • Horizo​​ntal.TProgressbar / Vertical.TProgressbar
  • Horizo​​ntal.TScale / Vertical.TScale
  • Horizo​​ntal.TScrollbar / Vertical.TScrollbar
  • Treeview
>>> b=ttk.Button(None)
>>> b.winfo_class()
'TButton'
>>> t=ttk.Treeview(None)
>>> t.winfo_class()
'Treeview'

注: 根樣式名稱為 '.', 可以更改每一個部件預設的外觀.

s = ttk.Style()
s.configure('.', font=('Helvetica', 12))
  1. 樣式的名稱有兩種
  • 單一字名稱, 如 'TFrame'
  • 由舊樣式匯出新樣式的名稱 'new_name.old_name', 如 'Date.TEntry'
  1. 設定樣式的新選項值
s = ttk.Style()
s.configure('Kim.TButton', foreground='maroon') # 同時也建立了新樣式名稱 Kim.TButton
  1. 使用樣式
button = ttk.Button(root, text='Friday', style='Kim.TButton', command=self._fridayHandler)


部件動態外觀的改變

  1. 通常部件都有一些狀態旗號如下
旗號 說明
active 滑鼠是否正在部件上方
alternate 保留使用
background 在 Window 或 MacOS 中, 部件是否, 在視窗中, 但不在前景視窗中
disabled 部件是否正停用中, 不會對使用者有任何反應
focus 部件是否正在聚焦中
invalid 部件的內容是否無效
pressed 部件是否正被點選
readonly 部件內容是否不允許被修改
selected 部件是否被選擇, 比如在 'on' 的狀況
  1. 取得或設定樣式元素的動態行為, 可以使用 s.map(styleName, *p, **kw) 方法, 取得使用 p 引數, 設定使用 kw 引數.
>>> s.map('TCheckbutton', 'indicatorcolor')
[('pressed', '#ececec'), ('selected', '#4a6984')]
>>> s.map('TCheckbutton', indicatoron=[('pressed', '#ececec'), ('selected', '#4a6984')])


待續

本作品採用《CC 協議》,轉載必須註明作者和本文連結
Jason Yang

相關文章