[英]ttk, How to position heading inside Labelframe instead of on the border?
我正在嘗試根據我公司的 CI 創建自己的 ttk 主題。 我以Sun Valley 主題為起點並交換了圖形 fonts 和 colors。
但是我被困在 Label 框架上。 我正在嘗試在框架內顯示 position Label,有點像標題。 即頂部邊緣和 label 之間應該有一些邊距,並且內容(子部件)有適當的頂部填充。
現在:
+-- Label ------
| ...
期望:
+---------------
| Label
| ...
我試圖設置padding
選項:
但是 label 沒有移動一個像素。 如何做到這一點?
一般來說,我對ttk:style layout
、 ttk:style element
和ttk:style configure
中哪些標識符和選項是合法的感到非常困惑,因為文檔模糊不清,散布在 .net 各處,並且沒有任何錯誤消息。 有什么有用的提示嗎?
編輯:發布后我發現了什么:
TLabelframe.Label
完全是一個單獨的小部件。Frame
子類完全替換Labelframe
。 但這意味着要在很多地方更改“客戶端”代碼。 :-/這可以通過更改布局定義來完成,以便文本元素由 Labelframe 布局保留並且 Layoutframe.Label 不再繪制文本元素。 添加一點填充可確保包含的小部件使 label 保持清晰。
示例代碼:
import sys
import tkinter as tk
import tkinter.ttk as ttk
class CustomLabelframe(ttk.Labelframe):
def __init__(self, master, **kwargs):
"""Initialize the widget with the custom style."""
kwargs["style"] = "Custom.Labelframe"
super(CustomLabelframe, self).__init__(master, **kwargs)
@staticmethod
def register(master):
style = ttk.Style(master)
layout = CustomLabelframe.modify_layout(style.layout("TLabelframe"), "Custom")
style.layout('Custom.Labelframe.Label', [
('Custom.Label.fill', {'sticky': 'nswe'})])
style.layout('Custom.Labelframe', [
('Custom.Labelframe.border', {'sticky': 'nswe', 'children': [
('Custom.Labelframe.text', {'side': 'top'}),
('Custom.Labelframe.padding', {'side': 'top', 'expand': True})
]})
])
if (style.configure('TLabelframe')):
style.configure("Custom.Labelframe", **style.configure("TLabelframe"))
# Add space to the top to prevent child widgets overwriting the label.
style.configure("Custom.Labelframe", padding=(0,12,0,0))
style.map("Custom.Labelframe", **style.map("TLabelframe"))
master.bind("<<ThemeChanged>>", lambda ev: CustomLabelframe.register(ev.widget))
@staticmethod
def modify_layout(layout, prefix):
"""Copy a style layout and rename the elements with a prefix."""
result = []
for item in layout:
element,desc = item
if "children" in desc:
desc["children"] = HistoryCombobox.modify_layout(desc["children"], prefix)
result.append((f"{prefix}.{element}",desc))
return result
class App(ttk.Frame):
"""Test application for the custom widget."""
def __init__(self, master, **kwargs):
super(App, self).__init__(master, **kwargs)
self.master.wm_geometry("640x480")
frame = self.create_themesframe()
frame.pack(side=tk.TOP, fill=tk.BOTH)
for count in range(3):
frame = CustomLabelframe(self, text=f"Frame {count}", width=160, height=80)
frame.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
button = ttk.Button(frame, text="Test")
button.pack(side=tk.LEFT)
self.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
def create_themesframe(self):
frame = ttk.Frame(self)
label = ttk.Label(frame, text="Theme: ")
themes = ttk.Combobox(frame, values=style.theme_names(), state="readonly")
themes.current(themes.cget("values").index(style.theme_use()))
themes.bind("<<ComboboxSelected>>", lambda ev: style.theme_use(ev.widget.get()))
label.pack(side=tk.LEFT)
themes.pack(side=tk.LEFT)
return frame
def main(args=None):
global root, app, style
root = tk.Tk()
style = ttk.Style(root)
CustomLabelframe.register(root)
app = App(root)
try:
import idlelib.pyshell
sys.argv = [sys.argv[0], "-n"]
root.bind("<Control-i>", lambda ev: idlelib.pyshell.main())
except Exception as e:
print(e)
root.mainloop()
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
將ttk.Labelframe
文本放置在浮雕圖形下方、上方或上方相對容易。 此示例使用文本屬性,但也可以使用labelwidget
。 為了使浮雕可見, Labelframe.Label
的背景顏色必須設置為“”。
import tkinter as tk
from tkinter import font
from tkinter import ttk
message = "Hello World"
master = tk.Tk()
style = ttk.Style(master)
style.theme_use(themename = "default")
actualFont = font.Font(
family = "Courier New", size = 20, weight = "bold")
style.configure(
"TLabelframe.Label", background = "", font = actualFont)
frame = ttk.LabelFrame(
master, labelanchor = "n", text = message)
frame.grid(sticky = tk.NSEW)
frame.rowconfigure(0, weight = 1)
frame.columnconfigure(0, weight = 1)
def change_heading():
if frame["text"][0] == "\n":
frame["text"] = f"{message}\n"
else:
frame["text"] = f"\n{message}"
button = tk.Button(
frame, text = "Change", command = change_heading)
button.grid(sticky = "nsew")
master.mainloop()
查看Labelframe 小部件的源代碼,我發現:
-labeloutside
配置選項。 (對於默認NW
錨點)我現在使用 labeloutside 選項制作一個“類似制表符”的標題。
# ... (define $images array much earlier) ...
ttk::style element create Labelframe.border image $images(card2) \
-border 6 -padding 6 -sticky nsew
ttk::style configure TLabelframe -padding {8 8 8 8} -labeloutside 1 -labelmargins {2 2 2 0}
ttk::style element create Label.fill image $images(header2) -height 31 -padding {8 0 16 0} -border 1
有了合適的圖像,這幾乎就是我的目標,只是 header 沒有延伸到整個幀寬度。 Tkinter 元素對圖像使用類似“9-patch”的細分策略,因此您可以使用element create
的-border
參數制作可拉伸的框架。
結果大概是這樣的:
+-------------+
| Heading |
+-------------+----------------+
| ... |
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.