[Python] 纯文本查看 复制代码
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import tkinter as tk
from tkinter import messagebox
from datetime import datetime
from ttkbootstrap.dialogs import Messagebox
from ttkbootstrap.tooltip import ToolTip
class ComponentShowcase(ttk.Window):
def __init__(self):
super().__init__(themename="cosmo")
self.title("组件样式展示")
# 添加搜索位置属性
self.current_search_pos = "1.0"
# 调整窗口大小和位置
window_width = 1700
window_height = 1120
screen_width = self.winfo_screenwidth()
screen_height = self.winfo_screenheight()
center_x = int((screen_width - window_width) / 2)
center_y = int((screen_height - window_height) / 2)
self.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}")
# 设置统一字体
self.font_config = ("Microsoft YaHei UI", 10)
# 创建主框架
self.main_frame = ttk.Frame(self, padding=20)
self.main_frame.pack(fill=BOTH, expand=True)
# 配置下拉框样式
style = ttk.Style()
# 设置下拉列表样式 - TCombobox是ttkbootstrap的默认下拉框样式类
style.configure("TCombobox",
selectbackground="white", # 设置选中项的背景色为白色
selectforeground="#0d6efd", # 设置选中项的文字颜色为蓝色
fieldbackground="white", # 设置输入框的背景色为白色
background="white", # 设置下拉列表的背景色为白色
foreground="black") # 设置默认文字颜色为黑色
# 设置下拉列表在不同状态下的样式
style.map("TCombobox",
# readonly状态下保持选中项背景为白色
selectbackground=[("readonly", "white")],
# readonly状态下文字为蓝色
selectforeground=[("readonly", "#0d6efd")],
# readonly状态下输入框背景保持白色
fieldbackground=[("readonly", "white")],
# readonly状态下文字为蓝色
foreground=[("readonly", "#0d6efd")],
# 鼠标悬停时背景为白色
background=[("active", "white")])
# 创建左右分栏
self.create_left_panel()
self.create_right_panel()
def create_left_panel(self):
"""创建左侧面板"""
left_frame = ttk.LabelFrame(self.main_frame, text="基础组件",
padding=10, bootstyle="primary")
left_frame.pack(side=LEFT, fill=BOTH, expand=True, padx=(0,10))
# 按钮展示区 - 使用info样式
button_frame = ttk.LabelFrame(left_frame, text="按钮样式",
padding=10, bootstyle="info")
button_frame.pack(fill=X, pady=(0,10))
# 只保留轮廓按钮
ttk.Button(button_frame, text="主要轮廓",
bootstyle="primary-outline",
padding=(20,5)).pack(side=LEFT, padx=5)
ttk.Button(button_frame, text="成功轮廓",
bootstyle="success-outline",
padding=(20,5)).pack(side=LEFT, padx=5)
ttk.Button(button_frame, text="警告轮廓",
bootstyle="warning-outline",
padding=(20,5)).pack(side=LEFT, padx=5)
ttk.Button(button_frame, text="危险轮廓",
bootstyle="danger-outline",
padding=(20,5)).pack(side=LEFT, padx=5)
# 输入框展示区 - 使用success样式
entry_frame = ttk.LabelFrame(left_frame, text="输入框样式",
padding=10, bootstyle="success")
entry_frame.pack(fill=X, pady=(0,10))
# 普通输入框
ttk.Label(entry_frame, text="普通输入:").pack(side=LEFT)
ttk.Entry(entry_frame, width=20).pack(side=LEFT, padx=5)
# 密码输入框
ttk.Label(entry_frame, text="密码输入:").pack(side=LEFT, padx=(20,0))
ttk.Entry(entry_frame, width=20, show="*").pack(side=LEFT, padx=5)
# 只读输入框
ttk.Label(entry_frame, text="只读输入:").pack(side=LEFT, padx=(20,0))
readonly_entry = ttk.Entry(entry_frame, width=20)
readonly_entry.insert(0, "只读内容")
readonly_entry.configure(state="readonly")
readonly_entry.pack(side=LEFT, padx=5)
# 下拉框展示区 - 使用warning样式
combo_frame = ttk.LabelFrame(left_frame, text="下拉框样式",
padding=10, bootstyle="warning")
combo_frame.pack(fill=X, pady=(0,10))
# 普通下拉框
ttk.Label(combo_frame, text="普通下拉:").pack(side=LEFT)
combo1 = ttk.Combobox(combo_frame, values=["选项1", "选项2", "选项3"],
width=15)
combo1.pack(side=LEFT, padx=5)
combo1.bind('<<ComboboxSelected>>', lambda e: combo1.configure(foreground="#0d6efd"))
# 只读下拉框
ttk.Label(combo_frame, text="只读下拉:").pack(side=LEFT, padx=(20,0))
combo2 = ttk.Combobox(combo_frame, values=["选项1", "选项2", "选项3"],
width=15, state="readonly")
combo2.pack(side=LEFT, padx=5)
combo2.bind('<<ComboboxSelected>>', lambda e: combo2.configure(foreground="#0d6efd"))
# 复选框和单选框展示区 - 使用danger样式
check_radio_frame = ttk.LabelFrame(left_frame, text="复选框和单选框",
padding=10, bootstyle="danger")
check_radio_frame.pack(fill=X, pady=(0,10))
# 复选框
check_var = tk.BooleanVar()
ttk.Checkbutton(check_radio_frame, text="复选框1",
variable=check_var).pack(side=LEFT, padx=5)
check_var2 = tk.BooleanVar()
ttk.Checkbutton(check_radio_frame, text="复选框2",
variable=check_var2,
bootstyle="primary").pack(side=LEFT, padx=5)
# 单选框
radio_var = tk.StringVar(value="1")
ttk.Radiobutton(check_radio_frame, text="单选1",
variable=radio_var,
value="1").pack(side=LEFT, padx=(20,5))
ttk.Radiobutton(check_radio_frame, text="单选2",
variable=radio_var,
value="2").pack(side=LEFT, padx=5)
# 进度条展示区 - 使用secondary样式
progress_frame = ttk.LabelFrame(left_frame, text="进度条样式",
padding=10, bootstyle="secondary")
progress_frame.pack(fill=X, pady=(0,10))
# 创建进度条标签框架
progress_label_frame = ttk.Frame(progress_frame)
progress_label_frame.pack(fill=X, pady=(0,5))
ttk.Label(progress_label_frame, text="基础进度条 - 75%").pack(side=LEFT)
ttk.Label(progress_label_frame, text="75%").pack(side=RIGHT)
# 基础进度条
ttk.Progressbar(progress_frame, value=75,
bootstyle="primary",
length=200,
mode='determinate').pack(fill=X, pady=(0,10))
# 创建条纹进度条标签框架
striped_label_frame = ttk.Frame(progress_frame)
striped_label_frame.pack(fill=X, pady=(0,5))
ttk.Label(striped_label_frame, text="条纹进度条 - 45%").pack(side=LEFT)
ttk.Label(striped_label_frame, text="45%").pack(side=RIGHT)
# 条纹进度条
ttk.Progressbar(progress_frame, value=45,
bootstyle="striped-success",
length=200,
mode='determinate').pack(fill=X, pady=(0,10))
# 添加动画进度条
animated_label_frame = ttk.Frame(progress_frame)
animated_label_frame.pack(fill=X, pady=(0,5))
ttk.Label(animated_label_frame, text="动画进度条").pack(side=LEFT)
# 动画进度条
ttk.Progressbar(progress_frame,
bootstyle="striped-info",
length=200,
mode='indeterminate').pack(fill=X)
# hk展示区 - 使用info样式
scale_frame = ttk.LabelFrame(left_frame, text="hk样式",
padding=10, bootstyle="info")
scale_frame.pack(fill=X)
# 水平hk
ttk.Scale(scale_frame, from_=0, to=100, value=30).pack(fill=X, pady=5)
# 垂直hk
ttk.Scale(scale_frame, from_=100, to=0, value=70,
orient="vertical").pack(side=LEFT, padx=10)
# 添加分隔线展示区
separator_frame = ttk.LabelFrame(left_frame, text="分隔线样式",
padding=10, bootstyle="info")
separator_frame.pack(fill=X, pady=(10,0))
ttk.Label(separator_frame, text="水平分隔线").pack(fill=X)
ttk.Separator(separator_frame).pack(fill=X, pady=5)
ttk.Label(separator_frame, text="垂直分隔线").pack()
ttk.Separator(separator_frame, orient="vertical").pack(fill=Y, pady=5, ipady=20)
def create_right_panel(self):
"""创建右侧面板"""
right_frame = ttk.LabelFrame(self.main_frame, text="高级组件",
padding=10, bootstyle="primary")
right_frame.pack(side=LEFT, fill=BOTH, expand=True)
# 选项卡展示
notebook = ttk.Notebook(right_frame)
notebook.pack(fill=BOTH, expand=True, pady=(0,10))
# 第一个选项卡 - 树形视图
tree_tab = ttk.Frame(notebook, padding=10)
notebook.add(tree_tab, text="树形视图")
# 添加搜索框
search_frame = ttk.Frame(tree_tab)
search_frame.pack(fill=X, pady=(0,10))
ttk.Label(search_frame, text="搜索:").pack(side=LEFT)
search_var = tk.StringVar()
search_entry = ttk.Entry(search_frame, textvariable=search_var)
search_entry.pack(side=LEFT, padx=5)
# 配置搜索框样式
style = ttk.Style()
style.configure("Search.TEntry",
selectbackground="white",
selectforeground="#0d6efd",
fieldbackground="white",
foreground="black")
search_entry.configure(style="Search.TEntry")
def on_search_change(*args):
search_text = search_var.get().lower()
# 清除之前的选择
tree.selection_remove(*tree.selection())
if search_text:
search_entry.configure(foreground="#0d6efd")
for item in tree.get_children():
values = tree.item(item)['values']
if search_text in str(values).lower():
tree.selection_add(item)
tree.see(item)
else:
search_entry.configure(foreground="black")
search_var.trace("w", on_search_change)
def search_tree():
search_text = search_var.get().lower()
if search_text:
for item in tree.get_children():
values = tree.item(item)['values']
if search_text in str(values).lower():
tree.selection_set(item)
tree.see(item)
search_entry.configure(foreground="#0d6efd")
break
ttk.Button(search_frame, text="搜索",
command=search_tree,
bootstyle="info-outline").pack(side=LEFT)
# 创建树形视图
tree = ttk.Treeview(tree_tab, show="headings",
columns=("name", "age", "email"))
# 添加滚动条
tree_scroll = ttk.Scrollbar(tree_tab, orient="vertical", command=tree.yview)
tree_scroll.pack(side=RIGHT, fill=Y)
tree.configure(yscrollcommand=tree_scroll.set)
# 设置列和对齐方式
tree.heading("name", text="姓名", anchor=CENTER)
tree.heading("age", text="年龄", anchor=CENTER)
tree.heading("email", text="邮箱", anchor=CENTER)
tree.column("name", anchor=CENTER, width=150)
tree.column("age", anchor=CENTER, width=100)
tree.column("email", anchor=CENTER, width=200)
# 添加更多测试数据
test_data = [
("张三", "25", "zhangsan@example.com"),
("李四", "30", "lisi@example.com"),
("王五", "28", "wangwu@example.com"),
("赵六", "35", "zhaoliu@example.com"),
("钱七", "27", "qianqi@example.com")
]
for data in test_data:
tree.insert("", END, values=data)
tree.pack(fill=BOTH, expand=True)
# 第二个选项卡 - 高级文本编辑器
editor_tab = ttk.Frame(notebook, padding=10)
notebook.add(editor_tab, text="文本编辑器")
# 搜索框架
search_frame = ttk.Frame(editor_tab)
search_frame.pack(fill=X, pady=(0,5))
ttk.Label(search_frame, text="查找:").pack(side=LEFT)
find_var = tk.StringVar()
find_entry = ttk.Entry(search_frame, textvariable=find_var)
find_entry.pack(side=LEFT, padx=5)
# 配置查找框样式
style = ttk.Style()
style.configure("Find.TEntry",
selectbackground="white",
selectforeground="#0d6efd",
fieldbackground="white",
foreground="black")
find_entry.configure(style="Find.TEntry")
# 添加输入变化事件
def on_find_change(*args):
if find_var.get():
find_entry.configure(foreground="#0d6efd")
else:
find_entry.configure(foreground="black")
find_var.trace("w", on_find_change)
def find_text():
search_text = find_var.get()
if search_text:
# 从头开始搜索
self.current_search_pos = "1.0"
start_pos = text_editor.search(search_text, self.current_search_pos, stopindex=END)
if start_pos:
end_pos = f"{start_pos}+{len(search_text)}c"
# 清除之前的高亮
text_editor.tag_remove("search", "1.0", END)
# 添加新的高亮
text_editor.tag_add("search", start_pos, end_pos)
text_editor.tag_config("search", background="yellow")
text_editor.see(start_pos)
# 更新当前位置为找到位置的下一个字符
self.current_search_pos = end_pos
def find_next():
search_text = find_var.get()
if search_text:
# 从当前位置开始搜索
start_pos = text_editor.search(search_text, self.current_search_pos, stopindex=END)
if not start_pos: # 如果找不到,从头开始搜索
self.current_search_pos = "1.0"
start_pos = text_editor.search(search_text, self.current_search_pos, stopindex=END)
if start_pos:
end_pos = f"{start_pos}+{len(search_text)}c"
# 清除之前的高亮
text_editor.tag_remove("search", "1.0", END)
# 添加新的高亮
text_editor.tag_add("search", start_pos, end_pos)
text_editor.tag_config("search", background="yellow")
text_editor.see(start_pos)
# 更新当前位置为找到位置的下一个字符
self.current_search_pos = end_pos
def find_prev():
search_text = find_var.get()
if search_text:
# 从当前位置向前搜索
start_pos = text_editor.search(search_text, self.current_search_pos, stopindex="1.0", backwards=True)
if not start_pos: # 如果找不到,从末尾开始搜索
self.current_search_pos = END
start_pos = text_editor.search(search_text, self.current_search_pos, stopindex="1.0", backwards=True)
if start_pos:
end_pos = f"{start_pos}+{len(search_text)}c"
# 清除之前的高亮
text_editor.tag_remove("search", "1.0", END)
# 添加新的高亮
text_editor.tag_add("search", start_pos, end_pos)
text_editor.tag_config("search", background="yellow")
text_editor.see(start_pos)
# 更新当前位置
self.current_search_pos = start_pos
# 添加搜索按钮
ttk.Button(search_frame, text="查找",
command=find_text,
bootstyle="info-outline").pack(side=LEFT, padx=2)
ttk.Button(search_frame, text="上一个",
command=find_prev,
bootstyle="info-outline").pack(side=LEFT, padx=2)
ttk.Button(search_frame, text="下一个",
command=find_next,
bootstyle="info-outline").pack(side=LEFT, padx=2)
# 创建文本编辑器
text_editor = ttk.Text(editor_tab, wrap=WORD, undo=True)
text_editor.pack(fill=BOTH, expand=True)
# 添加一些示例文本
text_editor.insert("1.0", "这是一个文本编辑器示例。\n\n"
"支持以下功能:\n"
"1. Ctrl+Z 撤销\n"
"2. Ctrl+Y 恢复\n"
"3. 文本查找和高亮\n"
"4. 点击查找定位文本\n"
"5. 上一个/下一个匹配项\n\n"
"请随意编辑此文本来测试这些功能。")
# 添加右键菜单
editor_menu = tk.Menu(text_editor, tearoff=0)
editor_menu.add_command(label="撤销", command=lambda: text_editor.event_generate("<<Undo>>"))
editor_menu.add_command(label="重做", command=lambda: text_editor.event_generate("<<Redo>>"))
editor_menu.add_separator()
editor_menu.add_command(label="剪切", command=lambda: text_editor.event_generate("<<Cut>>"))
editor_menu.add_command(label="复制", command=lambda: text_editor.event_generate("<<Copy>>"))
editor_menu.add_command(label="粘贴", command=lambda: text_editor.event_generate("<<Paste>>"))
def show_menu(event):
editor_menu.tk_popup(event.x_root, event.y_root)
text_editor.bind("<Button-3>", show_menu)
# 添加快捷键
text_editor.bind("<Control-z>", lambda e: text_editor.event_generate("<<Undo>>"))
text_editor.bind("<Control-y>", lambda e: text_editor.event_generate("<<Redo>>"))
# 第三个选项卡 - 控件展示
controls_tab = ttk.Frame(notebook, padding=10)
notebook.add(controls_tab, text="控件展示")
# 创建左右分栏
left_controls = ttk.Frame(controls_tab)
left_controls.pack(side=LEFT, fill=BOTH, expand=True, padx=(0,10))
right_controls = ttk.Frame(controls_tab)
right_controls.pack(side=LEFT, fill=BOTH, expand=True)
# 开关按钮展示
toggle_frame = ttk.LabelFrame(left_controls, text="开关按钮", padding=10)
toggle_frame.pack(fill=X, pady=(0,10))
ttk.Checkbutton(toggle_frame, text="默认开关",
bootstyle="round-toggle").pack(pady=5)
ttk.Checkbutton(toggle_frame, text="主要开关",
bootstyle="round-toggle-primary").pack(pady=5)
ttk.Checkbutton(toggle_frame, text="成功开关",
bootstyle="round-toggle-success").pack(pady=5)
# 日期选择器展示
date_frame = ttk.LabelFrame(right_controls, text="日期选择器", padding=10)
date_frame.pack(fill=X, pady=(0,10))
# 创建日期选择器
date_entry = ttk.DateEntry(date_frame,
bootstyle="primary",
firstweekday=0)
date_entry.pack(side=LEFT, pady=5)
# 添加清除按钮
def clear_date():
date_entry.entry.delete(0, END)
ttk.Button(date_frame, text="清除",
command=clear_date,
bootstyle="info-outline").pack(side=LEFT, padx=5, pady=5)
# 消息框按钮展示
msg_frame = ttk.LabelFrame(right_controls, text="消息框", padding=10)
msg_frame.pack(fill=X)
def show_info():
messagebox.showinfo("信息", "这是一条信息消息")
def show_warning():
messagebox.showwarning("警告", "这是一条警告消息")
def show_error():
messagebox.showerror("错误", "这是一条错误消息")
ttk.Button(msg_frame, text="显示信息",
command=show_info,
bootstyle="info-outline").pack(pady=5)
ttk.Button(msg_frame, text="显示警告",
command=show_warning,
bootstyle="warning-outline").pack(pady=5)
ttk.Button(msg_frame, text="显示错误",
command=show_error,
bootstyle="danger-outline").pack(pady=5)
# 状态栏
status_frame = ttk.Frame(right_frame)
status_frame.pack(fill=X)
ttk.Label(status_frame,
text=f"当前时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
bootstyle="secondary").pack(side=LEFT)
ttk.Label(status_frame,
text="就绪",
bootstyle="success").pack(side=RIGHT)
if __name__ == "__main__":
app = ComponentShowcase()
app.mainloop()