Files
sfgrid/core/main_ui.py
T
2025-11-12 11:51:40 +08:00

214 lines
7.7 KiB
Python

import tkinter as tk
from tkinter import ttk
from core.logger import LogLevel, PrintLog
from core.sfgrid.sfgrid_ui import TradeTargetUI
class MainWindow:
def __init__(self):
self.root = tk.Tk()
self.root.title("神之一手 - 交易系统")
self.root.geometry("1400x700")
# 当前选中的策略Tab索引
self.current_strategy_index = 0
# 存储各个Frame的引用
self.strategy_frames = {}
# 日志面板可见性标志
self.log_visible = False
# 创建界面
self.create_ui()
def create_ui(self):
"""创建UI界面"""
# 主容器
main_container = ttk.Frame(self.root)
main_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 中间主体区域(左右布局)
content_area = ttk.Frame(main_container)
content_area.pack(fill=tk.BOTH, expand=True)
# 左侧Tab按钮栏(垂直排列)
tab_bar_frame = ttk.Frame(content_area)
tab_bar_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))
# 创建Tab按钮(垂直排列,文字垂直显示)
self.tab_buttons = []
strategy_names = ["蒙派\n策略", "涨停\n分析"]
for idx, name in enumerate(strategy_names):
btn = ttk.Button(
tab_bar_frame,
text=name,
command=lambda i=idx: self.switch_strategy_tab(i),
width=4
)
btn.pack(side=tk.TOP, pady=2, fill=tk.X)
self.tab_buttons.append(btn)
# 在Tab按钮下方添加退出按钮和日志按钮(底部对齐)
# 使用一个填充Frame将按钮推到底部
spacer = ttk.Frame(tab_bar_frame)
spacer.pack(side=tk.TOP, fill=tk.X, ipady=10)
# 清空日志按钮(底部第三个)
clear_log_btn = ttk.Button(
tab_bar_frame,
text="🗑", # 垃圾桶图标
command=self.clear_logs,
width=3
)
clear_log_btn.pack(side=tk.TOP, pady=2, fill=tk.X)
# 日志显示按钮(退出按钮上方)
self.log_toggle_btn = ttk.Button(
tab_bar_frame,
text="📋", # 日志图标
command=self.toggle_log_panel,
width=3
)
self.log_toggle_btn.pack(side=tk.TOP, pady=2, fill=tk.X)
# 退出按钮(最底部)
exit_btn = ttk.Button(
tab_bar_frame,
text="", # 电源图标
command=self.on_exit,
width=3
)
exit_btn.pack(side=tk.TOP, pady=2, fill=tk.X)
# 添加垂直分隔线
separator = ttk.Separator(content_area, orient='vertical')
separator.pack(side=tk.LEFT, fill=tk.Y, padx=1)
# 右侧内容区域容器(用于放置不同策略的Frame)
self.content_container = ttk.Frame(content_area)
self.content_container.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# 创建各个策略的Frame
self.create_strategy_frames(strategy_names)
# 创建全局日志面板(默认隐藏)
self.create_global_log_panel(main_container)
# 默认显示第一个策略
self.switch_strategy_tab(0)
def create_global_log_panel(self, parent):
"""创建全局日志面板"""
# 日志区域(默认隐藏)
self.log_frame = ttk.LabelFrame(parent, text="操作日志", padding=10)
# 默认不显示,通过工具栏按钮控制
# 创建日志表格
columns = ("timestamp", "level", "message")
self.log_table = ttk.Treeview(self.log_frame, columns=columns, show='headings', height=8)
log_column_configs = {
"timestamp": ("时间", 100),
"level": ("级别", 50),
"message": ("消息", 1150) # 调整宽度适应全局布局
}
for col in columns:
title, width = log_column_configs[col]
self.log_table.heading(col, text=title)
self.log_table.column(col, width=width, anchor=tk.W)
# 添加初始日志
from datetime import datetime
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.log_table.insert('', tk.END, values=(timestamp, "INFO", "系统启动成功"))
# 滚动条
scrollbar = ttk.Scrollbar(self.log_frame, orient=tk.VERTICAL, command=self.log_table.yview)
self.log_table.configure(yscrollcommand=scrollbar.set)
self.log_table.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
def add_log(self, level:LogLevel, message):
"""添加日志记录 - 全局方法"""
from datetime import datetime
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.log_table.insert('', 0, values=(timestamp, level.value, message))
def clear_logs(self):
"""清空日志记录"""
# 删除所有日志项
for item in self.log_table.get_children():
self.log_table.delete(item)
self.add_log(LogLevel.DEBUG, "日志已清空")
def create_strategy_frames(self, strategy_names):
"""创建各个策略的Frame"""
for idx, name in enumerate(strategy_names):
if idx == 0:
# 第一个Tab使用TradeTargetUI,传入main_window引用
frame = TradeTargetUI(self.content_container)
self.strategy_frames[idx] = frame
else:
# 其他策略使用占位Frame
frame = ttk.Frame(self.content_container)
self.strategy_frames[idx] = frame
# 添加占位内容
placeholder = ttk.Label(
frame,
text=f"{name} - 策略界面将在此实现",
font=('Arial', 14),
foreground='gray'
)
placeholder.pack(expand=True)
def switch_strategy_tab(self, index):
"""切换策略Tab"""
# 隐藏当前Frame
if self.current_strategy_index in self.strategy_frames:
self.strategy_frames[self.current_strategy_index].pack_forget()
# 更新当前索引
self.current_strategy_index = index
# 显示选中的Frame
if index in self.strategy_frames:
self.strategy_frames[index].pack(fill=tk.BOTH, expand=True)
# 更新Tab按钮样式(可选,用于视觉反馈)
self.update_tab_button_styles()
def update_tab_button_styles(self):
"""更新Tab按钮的样式以显示选中状态"""
# 注意:ttk.Button的样式需要通过ttk.Style来设置
# 这里简化处理,仅作为接口预留
pass
def toggle_log_panel(self):
"""切换日志面板的显示/隐藏"""
if self.log_visible:
# 隐藏日志面板
self.log_frame.pack_forget()
self.log_visible = False
self.log_toggle_btn.config(text="📋") # 日志图标
else:
# 显示日志面板
self.log_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=(5, 0))
self.log_visible = True
self.log_toggle_btn.config(text="🔽") # 使用不同图标表示隐藏
def on_exit(self):
"""退出程序"""
from tkinter import messagebox
result = messagebox.askyesno("确认退出", "确定要退出系统吗?")
if result:
self.root.destroy()
def run(self):
"""运行程序"""
self.root.mainloop()