修改问题,子类模块界面(1.输入分析)里就是没有用户指定的标签及其它,而其它模块界面里,只有模块界面(3.跟随分析)里出现重复的四个按钮,其它的都是正确的。问题2:Exception in Tkinter callback
Traceback (most recent call last):
File "F:\python\Lib\tkinter\__init__.py", line 1967, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "C:\Users\Administrator\Desktop\数字模型生成器.py", line 983, in <lambda>
command=lambda m=module: self._on_module_button_click(m)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Administrator\Desktop\数字模型生成器.py", line 1097, in _on_module_button_click
self._create_input_analysis_content(content_frame)
File "C:\Users\Administrator\Desktop\数字模型生成器.py", line 1285, in _create_input_analysis_content
exclude_frame = LabelFrame(main_frame, text=" 排除号码 ", font=('微软雅黑', 12, 'bold'))
^^^^^^^^^^
NameError: name 'LabelFrame' is not defined
检查原代码class MainInterface:
def __init__(self, root: Tk, pool: 'NumberPool'):
self.root = root
self.pool = pool
self.left_panel = None
self.center_paned = None # 修正变量名
self.right_panel = None
self.core_vars = {}
self.pool_vars = {}
self.status_var = StringVar()
self.dynamic_text = None
self.current_module = None
self._setup_ui()
self._setup_event_handlers()
self.module_instances = {}
self.exclude_front_entries = []
self.exclude_back_entries = []
self.front_dan_entries = []
self.back_dan_entries = []
# 初始化结果文本控件
self.result_text = None
# 初始化排除号码变量
self.exclude_front_var = StringVar()
self.exclude_back_var = StringVar()
self.recommend_front_var = StringVar()
self.recommend_back_var = StringVar()
# 初始化模块内容框架
self.dynamic_content = None
self.module_content_frame = None
# 模块标签定义
self.labels = {
'input_analysis': [ # 修正为小写
"排除号码:", "前区:", "后区:", "推荐号码:", "前区:", "后区:",
],
'combination_analysis': [
"前数字频:", "前数字缺:", "后数字频:", "后数字缺:",
"前频繁推:", "后低频推:", "生组合数:", "未组合码:"
],
'follow_analysis': [
"前推荐多:", "前推荐少:", "后推荐多:", "后推荐少:"
],
'trend_analysis': [
"和值:", "质合比:", "奇偶比:", "断区推荐:", "连号推荐:",
"冷热推荐:", "后区热号:", "后区冷号:", "趋势号:"
],
'number_generation': [ # 修正为小写
"胆码:", "前区:", "后区:", "推荐5注号码:",
"1:", "", "2:", "", "3:", "", "4:", "", "5:", ""
],
}
# 初始化所有模块的条目引用
self.front_dan_entry = None
self.back_dan_entry = None
self.result_text = None
self.exclude_front_entry = None
self.exclude_back_entry = None
self.front_entry = None
self.back_entry = None
def _setup_event_handlers(self):
"""初始化事件处理器"""
event_center.subscribe(EventType.MODULE_COMPLETE, self._handle_module_complete)
event_center.subscribe(EventType.UI_UPDATE, self._handle_ui_update)
event_center.subscribe(EventType.EXCLUDE_NUMBERS, self._handle_exclude_numbers)
def _setup_ui(self):
self.root.title(f"大乐透智能分析平台 - {GlobalConfig.VERSION}")
self.root.geometry("1400x800")
# 添加主标题
title_frame = Frame(self.root)
title_frame.pack(fill='x', pady=5)
Label(title_frame, text="大乐透智能分析平台", font=('微软雅黑', 16, 'bold')).pack(expand=True)
# 主容器 - 三栏布局
main_container = PanedWindow(self.root, orient=HORIZONTAL, sashrelief=RAISED, sashwidth=5)
main_container.pack(fill='both', expand=True, padx=5, pady=(0, 5))
# 左侧面板
self.left_panel = Frame(main_container, width=200, bg="#eaeaea")
main_container.add(self.left_panel, minsize=150, stretch="never")
# 中间内容区
self.center_paned = PanedWindow(main_container, orient=VERTICAL, sashrelief=RAISED, sashwidth=5)
main_container.add(self.center_paned, minsize=500, stretch="always")
# 右侧面板
self.right_panel = Frame(main_container, width=700, bg="#f5f5f5")
main_container.add(self.right_panel, minsize=250, stretch="never")
# 初始化各区域
self._setup_left_panel()
self._setup_center_area()
self._setup_right_panel()
def _setup_left_panel(self):
"""初始化左侧模块按钮区"""
module_names = {
'input_analysis': '1. 输入分析',
'combination_analysis': '2. 组合分析',
'follow_analysis': '3. 跟随分析',
'trend_analysis': '4. 趋势分析',
'number_generation': '5. 数字生成'
}
for module in GlobalConfig.MODULES:
Button(
self.left_panel,
text=module_names[module],
width=18,
command=lambda m=module: self._on_module_button_click(m)
).pack(pady=3, padx=5, ipady=3)
def _setup_center_area(self):
"""设置中间区域布局,分为上下两部分"""
# 上半部分 - 核心区 (固定高度)
self.core_frame = Frame(self.center_paned, bd=1, relief='solid')
self.center_paned.add(self.core_frame, minsize=150, stretch="never")
# 核心区内容
Label(self.core_frame, text="核心区", font=('微软雅黑', 12, 'bold')).pack(anchor='w', padx=5, pady=2)
# 核心数据展示
self.core_vars = {
'front_area': StringVar(),
'back_area': StringVar(),
'front_hot': StringVar(),
'front_cold': StringVar(),
'back_hot': StringVar(),
'back_cold': StringVar()
}
for label, var_name in [
("前区:", 'front_area'),
("后区:", 'back_area'),
("前区热号:", 'front_hot'),
("前区冷号:", 'front_cold'),
("后区热号:", 'back_hot'),
("后区冷号:", 'back_cold')
]:
frame = Frame(self.core_frame)
frame.pack(fill='x', padx=5, pady=2)
Label(frame, text=label, width=10, anchor='w').pack(side='left')
entry_container = Frame(frame)
entry_container.pack(side='left', fill='x', expand=True)
entry = Entry(entry_container, textvariable=self.core_vars[var_name], font=('微软雅黑', 10),
state='readonly', readonlybackground='#f0f0f0', relief='sunken', bd=1)
entry.pack(fill='x', expand=True)
# 下半部分 - 动态区
self.dynamic_frame = Frame(self.center_paned, bd=1, relief='solid')
self.center_paned.add(self.dynamic_frame, minsize=200, stretch="always")
# 主容器使用Grid布局
self.dynamic_container = Frame(self.dynamic_frame)
self.dynamic_container.pack(fill='both', expand=True)
self.dynamic_container.grid_rowconfigure(0, weight=1)
self.dynamic_container.grid_columnconfigure(0, weight=1)
# 操作按钮放在右下角
self.btn_frame = Frame(self.dynamic_container)
self.btn_frame.grid(row=1, column=0, sticky='se', pady=5, padx=5)
Button(self.btn_frame, text="运行", width=8, command=self._run_current_module).pack(side='left', padx=2)
Button(self.btn_frame, text="清除", width=8, command=self._clear_dynamic_content).pack(side='left', padx=2)
Button(self.btn_frame, text="保存", width=8, command=self._save_dynamic_content).pack(side='left', padx=2)
Button(self.btn_frame, text="刷新", width=8, command=self._refresh_dynamic).pack(side='left', padx=2)
# 模块内容容器 - 确保先创建
self.module_content_frame = Frame(self.dynamic_container)
self.module_content_frame.grid(row=0, column=0, sticky='nsew')
# 初始化默认内容
self._init_default_dynamic_content()
def _init_default_dynamic_content(self):
"""初始化默认动态区内容"""
# 清除现有内容
for widget in self.module_content_frame.winfo_children():
widget.destroy()
# 创建新内容
self.dynamic_content = Frame(self.module_content_frame)
self.dynamic_content.pack(fill='both', expand=True)
Label(self.dynamic_content,
text="请从左侧选择分析模块",
font=('微软雅黑', 12)).pack(expand=True, pady=50)
def _on_module_button_click(self, module: str):
"""模块按钮点击事件处理"""
self.status_var.set(f"打开 {module} 模块...")
self.current_module = module
if not hasattr(self, 'module_content_frame') or self.module_content_frame is None:
# 紧急初始化内容框架
self.module_content_frame = Frame(self.dynamic_container)
self.module_content_frame.grid(row=0, column=0, sticky='nsew')
logging.error("紧急初始化 module_content_frame")
# 同时初始化默认内容
self._init_default_dynamic_content()
# 清除现有内容
try:
for widget in self.module_content_frame.winfo_children():
widget.destroy()
except AttributeError as e:
logging.critical(f"清除内容失败: {str(e)}")
# 尝试恢复UI
self.module_content_frame = Frame(self.dynamic_container)
self.module_content_frame.grid(row=0, column=0, sticky='nsew')
self._init_default_dynamic_content()
# 清除之前的动态内容
for widget in self.module_content_frame.winfo_children():
widget.destroy()
# 创建新的内容容器 - 使用pack布局填充整个空间
content_frame = Frame(self.module_content_frame)
content_frame.pack(fill='both', expand=True)
# 根据模块类型创建具体内容
if module == "input_analysis":
self._create_input_analysis_content(content_frame)
elif module == "combination_analysis":
self._create_combination_analysis_content(content_frame)
elif module == "follow_analysis":
self._create_follow_analysis_content(content_frame)
elif module == "trend_analysis":
self._create_trend_analysis_content(content_frame)
elif module == "number_generation":
self._create_number_generation_content(content_frame)
# 底部按钮区 - 使用pack放在底部
btn_frame = Frame(self.module_content_frame)
btn_frame.pack(side='bottom', fill='x', pady=5)
# 按钮容器靠右
btn_container = Frame(btn_frame)
btn_container.pack(side='right')
Button(btn_container, text="运行", width=8,
command=lambda: self._run_module(module)).pack(side='left', padx=2)
Button(btn_container, text="清除", width=8,
command=lambda: self._clear_module_data(module)).pack(side='left', padx=2)
Button(btn_container, text="保存", width=8,
command=lambda: self._save_module_data(module)).pack(side='left', padx=2)
Button(btn_container, text="刷新", width=8,
command=lambda: self._on_module_button_click(module)).pack(side='left', padx=2)
# 强制刷新界面
self.root.update_idletasks()
def _run_current_module(self):
"""运行当前模块"""
if self.current_module:
self._run_module(self.current_module)
def _clear_dynamic_content(self):
"""清除动态区内容"""
if self.current_module:
self._clear_module_data(self.current_module)
# 额外确保清除结果文本框(如果存在)
if hasattr(self, 'result_text') and self.result_text:
self.result_text.delete(1.0, 'end')
def _save_dynamic_content(self):
"""保存动态区内容"""
if self.current_module:
self._save_module_data(self.current_module)
else:
messagebox.showinfo("提示", "请先选择并运行一个模块")
def _refresh_dynamic(self):
"""刷新动态区内容"""
if self.current_module:
self._on_module_button_click(self.current_module)
else:
messagebox.showinfo("提示", "请先选择一个模块")
def _organize_data(self):
"""整理号码池数据"""
try:
# 发布整理事件
event = Event(
event_id=int(time.time()),
type=EventType.ORGANIZE_DATA,
source='main_ui',
target='pool'
)
event_center.publish(event)
self.status_var.set("号码池数据已整理")
except Exception as e:
messagebox.showerror("整理失败", str(e))
logging.error(f"整理数据失败: {str(e)}", exc_info=True)
def _freeze_data(self):
"""冻结号码池数据"""
try:
# 发布冻结事件
event = Event(
event_id=int(time.time()),
type=EventType.FREEZE_DATA,
source='main_ui',
target='pool'
)
event_center.publish(event)
self.status_var.set("号码池数据已冻结")
except Exception as e:
messagebox.showerror("冻结失败", str(e))
logging.error(f"冻结数据失败: {str(e)}", exc_info=True)
def _run_module(self, module: str):
"""运行指定模块"""
if module == "input_analysis":
# 获取排除号码
exclude_front = self.exclude_front_entry.get()
exclude_back = self.exclude_back_entry.get()
# 发布排除号码事件
exclude_event = Event(
event_id=int(time.time()),
type=EventType.EXCLUDE_NUMBERS,
source='main_ui',
target='pool',
data={
'exclude_front': exclude_front,
'exclude_back': exclude_back
}
)
event_center.publish(exclude_event)
# 在结果文本中记录
self.result_text.insert('end', f"已设置排除号码: 前区 {exclude_front}, 后区 {exclude_back}\n")
# 发布模块运行事件
run_event = Event(
event_id=int(time.time()),
type=EventType.MODULE_RUN,
source='main_ui',
target=module
)
event_center.publish(run_event)
def _create_ui_element(self, parent, label_text):
"""创建统一的UI元素(与核心区对齐)"""
frame = Frame(parent)
frame.pack(fill='x', pady=2)
# 标签固定宽度与核心区对齐
Label(frame, text=label_text, width=10, anchor='w').pack(side='left')
# 条目容器 - 宽度与核心区对齐
entry_container = Frame(frame)
entry_container.pack(side='left', fill='x', expand=True)
return entry_container
def _setup_right_panel(self):
"""设置右侧号码池布局"""
# 号码池标题
pool_title_frame = Frame(self.right_panel)
pool_title_frame.pack(fill='x', pady=5)
Label(pool_title_frame, text="号码池", font=('微软雅黑', 12, 'bold')).pack(anchor='w')
# 号码池内容区(添加边框和2px内边距)
pool_content = Frame(self.right_panel, bd=1, relief='solid', padx=2, pady=2)
pool_content.pack(fill='both', expand=True, padx=5, pady=5)
# 创建Canvas和Scrollbar
canvas = Canvas(pool_content, highlightthickness=0)
scrollbar = Scrollbar(pool_content, orient="vertical", command=canvas.yview)
scrollable_frame = Frame(canvas)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
# 号码池项目 - 优化布局和样式(带2px右边距)
for label, var_name, row_id in GlobalConfig.UI_CONFIG:
frame = Frame(scrollable_frame)
frame.grid(row=row_id, column=0, sticky='ew', padx=0, pady=1) # 移除水平padding
# 左侧标签(固定宽度8字符)
lbl = Label(frame, text=label, width=8, anchor='w')
lbl.pack(side='left', padx=(0, 5)) # 标签右侧留5px间距
# 右侧输入框容器(带2px右边距)
entry_container = Frame(frame)
entry_container.pack(side='left', fill='x', expand=True, padx=(0, 2))
var = StringVar()
self.pool_vars[var_name] = var
entry = Entry(entry_container, textvariable=var, font=('微软雅黑', 9),
state='readonly', readonlybackground='#f0f0f0', relief='sunken', bd=1)
entry.pack(fill='x', expand=True)
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
# 底部按钮区
btn_frame = Frame(self.right_panel)
btn_frame.pack(fill='x', pady=5)
Button(btn_frame, text="整理", width=10, command=self._organize_data).pack(side='left', padx=5)
Button(btn_frame, text="冻结", width=10, command=self._freeze_data).pack(side='left', padx=5)
Button(btn_frame, text="导出", width=10).pack(side='left', padx=5)
def _create_input_analysis_content(self, parent: Frame):
"""创建输入分析模块内容 - 修复版"""
# 主容器使用Grid布局
main_frame = Frame(parent)
main_frame.pack(fill='both', expand=True)
# === 排除号码区 ===
exclude_frame = LabelFrame(main_frame, text=" 排除号码 ", font=('微软雅黑', 12, 'bold'))
exclude_frame.pack(fill='x', padx=20, pady=10, ipady=5)
# 使用预定义的标签文本
labels = self.labels['input_analysis']
# 排除号码标签
Label(exclude_frame, text=labels[0], font=('微软雅黑', 10, 'bold')).pack(anchor='w', padx=10, pady=(5, 0))
# 前区排除
Label(exclude_frame, text=labels[1], font=('微软雅黑', 10)).pack(anchor='w', padx=10, pady=5)
front_entries_frame = Frame(exclude_frame)
front_entries_frame.pack(fill='x', padx=10, pady=5)
self.exclude_front_entries = []
for i in range(10): # 10个前区输入框
entry_frame = Frame(front_entries_frame)
entry_frame.pack(side='left', padx=2)
Label(entry_frame, text=f"{i + 1}:").pack(side='left')
entry = Entry(entry_frame, width=3, font=('微软雅黑', 10))
entry.pack(side='left')
# 绑定事件处理
entry.bind("<KeyRelease>", self._auto_format_entry)
entry.bind("<Left>", lambda e, d=-1: self._navigate_entry(e, d))
entry.bind("<Right>", lambda e, d=1: self._navigate_entry(e, d))
self.exclude_front_entries.append(entry)
# 后区排除
Label(exclude_frame, text=labels[2], font=('微软雅黑', 10)).pack(anchor='w', padx=10, pady=(10, 5))
back_entries_frame = Frame(exclude_frame)
back_entries_frame.pack(fill='x', padx=10, pady=5)
self.exclude_back_entries = []
for i in range(10): # 10个后区输入框
entry_frame = Frame(back_entries_frame)
entry_frame.pack(side='left', padx=2)
Label(entry_frame, text=f"{i + 1}:").pack(side='left')
entry = Entry(entry_frame, width=3, font=('微软雅黑', 10))
entry.pack(side='left')
# 绑定事件处理
entry.bind("<KeyRelease>", self._auto_format_entry)
entry.bind("<Left>", lambda e, d=-1: self._navigate_entry(e, d))
entry.bind("<Right>", lambda e, d=1: self._navigate_entry(e, d))
self.exclude_back_entries.append(entry)
# === 推荐号码区 ===
recommend_frame = LabelFrame(main_frame, text=" 推荐号码 ", font=('微软雅黑', 12, 'bold'))
recommend_frame.pack(fill='x', padx=20, pady=10, ipady=5)
# 推荐号码标签
Label(recommend_frame, text=labels[3], font=('微软雅黑', 10, 'bold')).pack(anchor='w', padx=10, pady=(5, 0))
# 前区推荐
front_rec_frame = Frame(recommend_frame)
front_rec_frame.pack(fill='x', padx=10, pady=5)
Label(front_rec_frame, text=labels[4], font=('微软雅黑', 10)).pack(side='left')
self.recommend_front_var = StringVar()
Entry(front_rec_frame, textvariable=self.recommend_front_var,
state='readonly', font=('微软雅黑', 10),
readonlybackground='#f0f5f0').pack(side='left', fill='x', expand=True, padx=5)
# 后区推荐
back_rec_frame = Frame(recommend_frame)
back_rec_frame.pack(fill='x', padx=10, pady=5)
Label(back_rec_frame, text=labels[5], font=('微软雅黑', 10)).pack(side='left')
self.recommend_back_var = StringVar()
Entry(back_rec_frame, textvariable=self.recommend_back_var,
state='readonly', font=('微软雅黑', 10),
readonlybackground='#f0f5f0').pack(side='left', fill='x', expand=True, padx=5)
# === 结果区 ===
result_frame = LabelFrame(main_frame, text=" 分析结果 ", font=('微软雅黑', 12, 'bold'))
result_frame.pack(fill='both', expand=True, padx=20, pady=10, ipady=5)
scrollbar = Scrollbar(result_frame)
scrollbar.pack(side='right', fill='y')
self.result_text = Text(result_frame, yscrollcommand=scrollbar.set,
wrap='word', font=('微软雅黑', 10))
self.result_text.pack(fill='both', expand=True)
scrollbar.config(command=self.result_text.yview)
# 添加初始提示
self.result_text.insert('end', "请设置排除号码后点击'运行'按钮开始分析\n")
# 强制刷新界面
self.root.update_idletasks()
def _handle_entry_input(self, event):
"""处理输入框相关事件的总入口"""
if event.keysym in ('Left', 'Right'):
# 处理方向键导航
self._navigate_entry(event, 1 if event.keysym == 'Right' else -1)
else:
# 处理输入自动格式化
self._auto_format_entry(event)
def _auto_format_entry(self, event):
"""
自动格式化输入框内容
功能:
1. 自动将1-9的数字补零显示为01-09
2. 输入满2位后自动跳到下一个输入框
"""
entry = event.widget
current = entry.get().strip()
if current.isdigit(): # 只处理数字输入
# 自动补零处理
formatted = self._format_number(current)
if formatted != current:
entry.delete(0, 'end')
entry.insert(0, formatted)
# 输入满2位后自动跳转
if len(current) == 2:
self._focus_adjacent_entry(event.widget, 1) # 正向跳转
def _focus_adjacent_entry(self, current_entry, direction):
"""
焦点跳转到相邻输入框
:param current_entry: 当前输入框控件
:param direction: 跳转方向 (1:下一个, -1:上一个)
"""
all_entries = self.exclude_front_entries + self.exclude_back_entries
try:
current_index = all_entries.index(current_entry)
target_index = current_index + direction
if 0 <= target_index < len(all_entries):
all_entries[target_index].focus()
except ValueError:
pass
def _navigate_entry(self, event, direction):
"""使用方向键在输入框间导航"""
self._focus_adjacent_entry(event.widget, direction)
def _format_number(self, num_str: str) -> str:
"""
格式化数字为两位数
:param num_str: 输入的数字字符串
:return: 格式化后的两位数字符串
"""
if not num_str.isdigit():
return num_str # 非数字不处理
num = int(num_str)
if 1 <= num <= 9: # 1-9的数字补零
return f"0{num}"
return str(num) if num > 0 else num_str # 保留0和负数原样
def _create_combination_analysis_content(self, parent: Frame):
"""创建组合分析模块的特定内容"""
content_frame = Frame(parent)
content_frame.pack(fill='both', expand=True, padx=10, pady=10)
# 使用预定义的labels
for label in self.labels['combination_analysis']:
frame = Frame(content_frame)
frame.pack(fill='x', pady=2)
Label(frame, text=label, width=12, anchor='w', font=('微软雅黑', 10, 'bold')).pack(side='left')
entry = Entry(frame, width=30, state='readonly', readonlybackground='#f0f0f0')
entry.pack(side='left', padx=5)
# 保存对控件的引用
var_name = label.replace(':', '').replace(' ', '')
setattr(self, f"{var_name}_entry", entry) # 直接保存到实例变量
if var_name == "前区热号":
self.front_hot_entry = entry
elif var_name == "前数字频":
self.front_freq_entry = entry
elif var_name == "前频繁推":
self.front_freq_rec_entry = entry
elif var_name == "后区热号":
self.back_hot_entry = entry
elif var_name == "后数字频":
self.back_freq_entry = entry
elif var_name == "后低频推":
self.back_infreq_rec_entry = entry
# 结果显示区
result_frame = Frame(content_frame)
result_frame.pack(fill='both', expand=True)
scrollbar = Scrollbar(result_frame)
scrollbar.pack(side='right', fill='y')
self.result_text = Text(result_frame, yscrollcommand=scrollbar.set, wrap='word')
self.result_text.pack(fill='both', expand=True)
scrollbar.config(command=self.result_text.yview)
def _create_follow_analysis_content(self, parent: Frame):
"""创建跟随分析模块的特定内容"""
content_frame = Frame(parent)
content_frame.pack(fill='both', expand=True, padx=10, pady=10)
for label in self.labels['follow_analysis']:
frame = Frame(content_frame)
frame.pack(fill='x', pady=2)
Label(frame, text=label, width=12, anchor='w', font=('微软雅黑', 10, 'bold')).pack(side='left')
entry = Entry(frame, width=30, state='readonly', readonlybackground='#f0f0f0')
entry.pack(side='left', padx=5)
var_name = label.replace(':', '').replace(' ', '')
setattr(self, f"{var_name}_entry", entry) # 直接保存到实例变量
if var_name == "前推荐多":
self.front_more_entry = entry
elif var_name == "前推荐少":
self.front_less_entry = entry
elif var_name == "后推荐多":
self.back_more_entry = entry
elif var_name == "后推荐少":
self.back_less_entry = entry
# 结果显示区
result_frame = Frame(content_frame)
result_frame.pack(fill='both', expand=True)
scrollbar = Scrollbar(result_frame)
scrollbar.pack(side='right', fill='y')
self.result_text = Text(result_frame, yscrollcommand=scrollbar.set, wrap='word')
self.result_text.pack(fill='both', expand=True)
scrollbar.config(command=self.result_text.yview)
def _create_trend_analysis_content(self, parent: Frame):
"""创建趋势分析模块的特定内容"""
content_frame = Frame(parent)
content_frame.pack(fill='both', expand=True, padx=10, pady=10)
for label in self.labels['trend_analysis']:
frame = Frame(content_frame)
frame.pack(fill='x', pady=2)
Label(frame, text=label, width=12, anchor='w', font=('微软雅黑', 10, 'bold')).pack(side='left')
entry = Entry(frame, width=30, state='readonly', readonlybackground='#f0f0f0')
entry.pack(side='left', padx=5)
var_name = label.replace(':', '').replace(' ', '')
setattr(self, f"{var_name}_entry", entry) # 直接保存到实例变量
if var_name == "和值":
self.sum_value_entry = entry
elif var_name == "质合比":
self.prime_ratio_entry = entry
elif var_name == "奇偶比":
self.odd_even_ratio_entry = entry
elif var_name == "断区推荐":
self.zone_rec_entry = entry
elif var_name == "连号推荐":
self.consec_rec_entry = entry
elif var_name == "冷热推荐":
self.hot_cold_rec_entry = entry
elif var_name == "后区热号":
self.hot_rec_entry = entry
elif var_name == "后区冷号":
self.cold_rec_entry = entry
elif var_name == "趋势号":
self.trend_rec_entry = entry
# 结果显示区
result_frame = Frame(content_frame)
result_frame.pack(fill='both', expand=True)
scrollbar = Scrollbar(result_frame)
scrollbar.pack(side='right', fill='y')
self.result_text = Text(result_frame, yscrollcommand=scrollbar.set, wrap='word')
self.result_text.pack(fill='both', expand=True)
scrollbar.config(command=self.result_text.yview)
def _create_number_generation_content(self, parent: Frame):
"""创建数字生成模块的动态内容"""
content_frame = Frame(parent)
content_frame.pack(fill='both', expand=True, padx=10, pady=10)
# 胆码输入区
dan_frame = Frame(content_frame)
dan_frame.pack(fill='x', pady=5)
# 前区胆码
front_dan_frame = Frame(dan_frame)
front_dan_frame.pack(fill='x')
Label(front_dan_frame, text="前区胆码:").pack(side='left')
self.front_dan_entries = []
for i in range(5):
entry = Entry(front_dan_frame, width=3)
entry.pack(side='left', padx=2)
self.front_dan_entries.append(entry)
self.front_dan_entry = self.front_dan_entries[0] # 保存第一个条目引用
# 后区胆码
back_dan_frame = Frame(dan_frame)
back_dan_frame.pack(fill='x')
Label(back_dan_frame, text="后区胆码:").pack(side='left')
self.back_dan_entries = []
for i in range(5):
entry = Entry(back_dan_frame, width=3)
entry.pack(side='left', padx=2)
self.back_dan_entries.append(entry)
self.back_dan_entry = self.back_dan_entries[0] # 保存第一个条目引用
# 生成的号码显示区
generated_frame = Frame(content_frame)
generated_frame.pack(fill='x', pady=5)
Label(generated_frame, text="生成号码:").pack(anchor='w')
self.generated_labels = []
for i in range(1, 6):
frame = Frame(generated_frame)
frame.pack(fill='x')
Label(frame, text=f"{i}. ").pack(side='left')
label = Label(frame, text="", width=30, anchor='w')
label.pack(side='left')
self.generated_labels.append(label)
# 结果显示区
result_frame = Frame(content_frame)
result_frame.pack(fill='both', expand=True)
scrollbar = Scrollbar(result_frame)
scrollbar.pack(side='right', fill='y')
self.result_text = Text(result_frame, yscrollcommand=scrollbar.set, wrap='word')
self.result_text.pack(fill='both', expand=True)
scrollbar.config(command=self.result_text.yview)
def _run_module(self, module: str):
"""运行指定模块"""
if module == "input_analysis":
# 获取并格式化排除号码
exclude_front_list = []
for entry in self.exclude_front_entries:
num = entry.get()
if num: # 只处理非空输入
formatted = self._format_number(num)
exclude_front_list.append(formatted)
exclude_back_list = []
for entry in self.exclude_back_entries:
num = entry.get()
if num: # 只处理非空输入
formatted = self._format_number(num)
exclude_back_list.append(formatted)
exclude_front = ' '.join(exclude_front_list)
exclude_back = ' '.join(exclude_back_list)
# 发布排除号码事件
exclude_event = Event(
event_id=int(time.time()),
type=EventType.EXCLUDE_NUMBERS,
source='main_ui',
target='pool',
data={
'exclude_front': exclude_front,
'exclude_back': exclude_back
}
)
event_center.publish(exclude_event)
# 在结果文本中记录
self.result_text.insert('end', f"已设置排除号码: 前区 {exclude_front}, 后区 {exclude_back}\n")
# 发布模块运行事件
run_event = Event(
event_id=int(time.time()),
type=EventType.MODULE_RUN,
source='main_ui',
target=module
)
event_center.publish(run_event)
def _generate_recommend_numbers(self, exclude_front: str, exclude_back: str):
"""生成推荐号码(示例逻辑)"""
# 实际应用中应调用分析模块生成推荐号码
# 这里简化为生成随机推荐号码
import random
# 前区号码范围1-35
all_front = [str(idx) for idx in range(1, 36)]
exclude_front_list = exclude_front.split() if exclude_front else []
available_front = [num for num in all_front if num not in exclude_front_list]
# 后区号码范围1-12
all_back = [str(idx) for idx in range(1, 13)]
exclude_back_list = exclude_back.split() if exclude_back else []
available_back = [num for num in all_back if num not in exclude_back_list]
# 随机选择5个前区号码
if len(available_front) >= 5:
recommend_front = random.sample(available_front, 5)
else:
recommend_front = random.sample(all_front, 5)
# 随机选择2个后区号码
if len(available_back) >= 2:
recommend_back = random.sample(available_back, 2)
else:
recommend_back = random.sample(all_back, 2)
# 更新推荐号码显示
self.recommend_front_var.set(' '.join(sorted(recommend_front, key=int)))
self.recommend_back_var.set(' '.join(sorted(recommend_back, key=int)))
# 在结果文本中记录
self.result_text.insert('end', f"生成推荐号码: 前区 {self.recommend_front_var.get()}, 后区 {self.recommend_back_var.get()}\n")
# 更新号码池
self._update_pool_with_recommendations(self.recommend_front_var.get(), self.recommend_back_var.get())
def _update_pool_with_recommendations(self, front: str, back: str):
"""用推荐号码更新号码池"""
# 发布事件更新号码池
update_event = Event(
event_id=int(time.time()),
type=EventType.POOL_UPDATE,
source='input_analysis',
target='pool',
data={
'front_numbers': front,
'back_numbers': back
}
)
event_center.publish(update_event)
# 在结果文本中记录
self.result_text.insert('end', "号码池已更新\n")
def _clear_module_data(self, module: str):
"""清除模块数据"""
if module == "input_analysis":
if hasattr(self, 'front_entry') and self.front_entry:
self.front_entry.delete(0, 'end')
if hasattr(self, 'back_entry') and self.back_entry:
self.back_entry.delete(0, 'end')
if hasattr(self, 'exclude_front_entry') and self.exclude_front_entry:
self.exclude_front_entry.delete(0, 'end')
if hasattr(self, 'exclude_back_entry') and self.exclude_back_entry:
self.exclude_back_entry.delete(0, 'end')
if hasattr(self, 'recommend_front_var'):
self.recommend_front_var.set('')
if hasattr(self, 'recommend_back_var'):
self.recommend_back_var.set('')
if hasattr(self, 'result_text') and self.result_text:
self.result_text.delete(1.0, 'end')
elif module == "combination_analysis":
if hasattr(self, 'front_hot_entry') and self.front_hot_entry:
self.front_hot_entry.delete(0, 'end')
if hasattr(self, 'front_freq_entry') and self.front_freq_entry:
self.front_freq_entry.delete(0, 'end')
if hasattr(self, 'front_freq_rec_entry') and self.front_freq_rec_entry:
self.front_freq_rec_entry.delete(0, 'end')
if hasattr(self, 'back_hot_entry') and self.back_hot_entry:
self.back_hot_entry.delete(0, 'end')
if hasattr(self, 'back_freq_entry') and self.back_freq_entry:
self.back_freq_entry.delete(0, 'end')
if hasattr(self, 'back_infreq_rec_entry') and self.back_infreq_rec_entry:
self.back_infreq_rec_entry.delete(0, 'end')
if hasattr(self, 'result_text') and self.result_text:
self.result_text.delete(1.0, 'end')
if hasattr(self, 'result_text') and self.result_text:
self.result_text.delete(1.0, 'end')
if hasattr(self, 'front_entry') and self.front_entry:
self.front_entry.delete(0, 'end')
if hasattr(self, 'back_entry') and self.back_entry:
self.back_entry.delete(0, 'end')
if hasattr(self, 'exclude_front_entry') and self.exclude_front_entry:
self.exclude_front_entry.delete(0, 'end')
if hasattr(self, 'exclude_back_entry') and self.exclude_back_entry:
self.exclude_back_entry.delete(0, 'end')
def _save_module_data(self, module: str):
"""保存模块数据"""
try:
data = {}
if module == "input_analysis":
data['front'] = self.front_entry.get()
data['back'] = self.back_entry.get()
data['exclude_front'] = self.exclude_front_entry.get()
data['exclude_back'] = self.exclude_back_entry.get()
data['recommend_front'] = self.recommend_front_var.get()
data['recommend_back'] = self.recommend_back_var.get()
data['result'] = self.result_text.get(1.0, 'end')
elif module == "combination_analysis":
data['front_hot'] = self.front_hot_entry.get()
data['front_freq'] = self.front_freq_entry.get()
data['front_freq_rec'] = self.front_freq_rec_entry.get()
data['back_hot'] = self.back_hot_entry.get()
data['back_freq'] = self.back_freq_entry.get()
data['back_infreq_rec'] = self.back_infreq_rec_entry.get()
data['result'] = self.result_text.get(1.0, 'end')
# 其他模块数据收集...
filename = f"{module}_data.json"
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
messagebox.showinfo("保存成功", f"数据已保存到{filename}")
except Exception as e:
messagebox.showerror("保存失败", str(e))
logging.error(f"保存数据失败: {str(e)}", exc_info=True)
def _handle_exclude_numbers(self, event: Event):
"""处理排除号码事件"""
if event.data:
exclude_front = event.data.get('exclude_front', '')
exclude_back = event.data.get('exclude_back', '')
# 更新排除号码显示
self.exclude_front_entry.delete(0, 'end')
self.exclude_front_entry.insert(0, exclude_front)
self.exclude_back_entry.delete(0, 'end')
self.exclude_back_entry.insert(0, exclude_back)
# 在结果文本中记录
self.result_text.insert('end', f"收到排除号码: 前区 {exclude_front}, 后区 {exclude_back}\n")
def _handle_module_complete(self, event: Event):
self.status_var.set(f"{event.source} 模块运行完成")
if event.source == "input_analysis" and hasattr(self, 'result_text') and self.result_text:
# 更新推荐号码显示
if 'recommend_front' in event.data:
self.recommend_front_var.set(event.data['recommend_front'])
if 'recommend_back' in event.data:
self.recommend_back_var.set(event.data['recommend_back'])
# 在结果文本中记录
self.result_text.insert('end', f"\n{event.source} 模块已完成分析\n")
self.result_text.insert('end',
f"推荐号码: 前区 {self.recommend_front_var.get()}, 后区 {self.recommend_back_var.get()}\n")
# 同步更新号码池
update_event = Event(
event_id=int(time.time()),
type=EventType.POOL_UPDATE,
source='input_analysis',
target='pool',
data={
'front_numbers': self.recommend_front_var.get(),
'back_numbers': self.recommend_back_var.get()
}
)
event_center.publish(update_event)
self.result_text.insert('end', "号码池已同步更新\n")
def _on_module_renovate(self, module: str):
"""刷新模块"""
if module == self.current_module:
self._on_module_button_click(module)
def _handle_ui_update(self, event: Event):
"""处理UI更新事件"""
if not event.data or 'update_type' not in event.data:
return
update_type = event.data['update_type']
data = event.data.get('data', {})
# 处理核心变量更新
if update_type == 'organized_data':
# 确保所有核心变量已初始化
if not hasattr(self, 'core_vars'):
self.core_vars = {
'front_area': StringVar(),
'back_area': StringVar(),
'front_hot': StringVar(),
'front_cold': StringVar(),
'back_hot': StringVar(),
'back_cold': StringVar()
}
# 更新界面变量
self.core_vars['front_area'].set(str(data.get('front_numbers', [])))
self.core_vars['back_area'].set(str(data.get('back_numbers', [])))
self.core_vars['front_hot'].set(str(data.get('front_hot', [])))
self.core_vars['front_cold'].set(str(data.get('front_cold', [])))
self.core_vars['back_hot'].set(str(data.get('back_hot', [])))
self.core_vars['back_cold'].set(str(data.get('back_cold', [])))