写出完整代码::未使用的 import 语句 'import logging',意外实参,意外实参,意外实参意外实参意外实参意外实参,形参 'data' 未填,,2025-08-21 19:45:04,242 - __main__ - ERROR - 系统启动失败: InputAnalysisModule.register_callback() missing 1 required positional argument: 'callback_func'
Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\project\main.py", line 158, in main
main_ui = MainWindow(root, pool) # 确保MainWindow接受正确的参数
^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Administrator\Desktop\project\ui\main_window.py", line 114, in __init__
self._create_main_interface()
File "C:\Users\Administrator\Desktop\project\ui\main_window.py", line 127, in _create_main_interface
self.main_interface = MainInterface(self.root, self.pool)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Administrator\Desktop\project\ui\main_interface.py", line 58, in __init__
self._init_modules()
File "C:\Users\Administrator\Desktop\project\ui\main_interface.py", line 145, in _init_modules
self._register_module_callback(self.module1)
File "C:\Users\Administrator\Desktop\project\ui\main_interface.py", line 202, in _register_module_callback
module.register_callback(self._handle_analysis_result)
TypeError: InputAnalysisModule.register_callback() missing 1 required positional argument: 'callback_func'
进程已结束,退出代码为 1
代码#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 标准库导入
import json
import logging
import os
import sys
import tkinter as tk
import time
import uuid
from pathlib import Path
from tkinter import ttk, messagebox, scrolledtext
import logging
# 项目路径设置
def add_project_to_path():
"""确保项目根目录在Python路径中"""
project_root = Path(__file__).parent.parent.absolute()
if str(project_root) not in sys.path:
sys.path.insert(0, str(project_root))
add_project_to_path()
# 核心模块导入
try:
from core.global_config import GlobalConfig
from core.event_system import Event, EventType
from core.event_center import event_center
from tkinter import Frame, Label, Button
print("成功导入核心模块")
except ImportError as import_err:
print(f"核心导入失败: {import_err}")
sys.exit(1)
# 本地模块导入
try:
from input_analysis import InputAnalysisModule
except ImportError as local_err:
print(f"输入分析模块导入失败: {local_err}")
sys.exit(1)
class InputAnalysisUI:
def __init__(self, parent_frame):
self.logger = logging.getLogger(f"{__name__}.InputAnalysisUI")
self.parent = parent_frame
self.token = str(uuid.uuid4())
self._is_analyzing = False
self._last_analysis_time = None
try:
# 修复:使用正确的模块初始化
self.module = InputAnalysisModule()
# 修复:正确注册回调函数
self.module.register_callback("analysis_result", self._handle_analysis_result)
except Exception as init_err:
messagebox.showerror("初始化错误", f"模块初始化失败: {init_err}")
raise
# 修复:移除内部类定义
self.labels = [
"排除号码", "前区", "后区", "推荐号码",
"前区", "后区"
]
self.dynamic_data = {
"排除号码": {"前区": [], "后区": []},
"推荐号码": {"前区": [], "后区": []}
}
self._setup_ui()
self._register_event_handlers()
self._load_saved_data()
@staticmethod
def _validate_number(text: str, min_val: int, max_val: int) -> bool:
"""验证输入的数字是否在指定范围内"""
if not text:
return True
return text.isdigit() and min_val <= int(text) <= max_val
def _validate_inputs(self):
"""验证所有输入有效性"""
valid = True
for entry in self.exclude_front_entries:
if entry.get() and not self._validate_number(entry.get(), 1, 35):
entry.config(foreground='red')
valid = False
else:
entry.config(foreground='black')
# 对后区做同样验证
for entry in self.exclude_back_entries:
if entry.get() and not self._validate_number(entry.get(), 1, 12):
entry.config(foreground='red')
valid = False
else:
entry.config(foreground='black')
return valid
@staticmethod
def _format_number(num_str: str) -> str:
"""格式化数字为两位数"""
if not num_str.isdigit():
return num_str
num = int(num_str)
return f"{num:02d}" if 1 <= num <= 9 else str(num)
def _setup_ui(self):
"""修复:使用正确的父组件类型"""
self.frame = ttk.LabelFrame(
self.parent, # 使用传递的parent_frame作为父组件
text="输入分析模块",
font=('微软雅黑', 12, 'bold')
)
self.frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 模块ID标识
module_id_label = ttk.Label(
self.frame,
text=f"模块ID: {GlobalConfig.MODULE_IDS['MODULE1_ID']}",
font=('微软雅黑', 8),
foreground='gray'
)
module_id_label.pack(anchor=tk.NE, padx=10, pady=5)
# 排除号码区
exclude_frame = ttk.LabelFrame(self.frame, text=" 排除号码 ", font=('微软雅黑', 10))
exclude_frame.pack(fill=tk.X, padx=20, pady=10, ipady=5)
# 创建输入框的通用方法
def create_number_entries(parent, label_text, count, min_val, max_val):
ttk.Label(parent, text=label_text, font=('微软雅黑', 10)).pack(
anchor=tk.W, padx=10, pady=5)
frame = ttk.Frame(parent)
frame.pack(fill=tk.X, padx=10, pady=5)
entries = []
for i in range(count):
entry_frame = ttk.Frame(frame)
entry_frame.pack(side=tk.LEFT, padx=2)
ttk.Label(entry_frame, text=f"{i + 1}:").pack(side=tk.LEFT)
entry = ttk.Entry(entry_frame, width=3, font=('微软雅黑', 10))
entry.pack(side=tk.LEFT)
entry.config(
validate="key",
validatecommand=(
entry.register(
lambda text, mn=min_val, mx=max_val:
self._validate_number(text, mn, mx)
),
'%P'
)
)
entry.bind("<KeyRelease>", self._auto_format_entry)
entry.bind("<Left>", lambda evt, d=-1: self._navigate_entry(evt, d))
entry.bind("<Right>", lambda evt, d=1: self._navigate_entry(evt, d))
entries.append(entry)
return entries
# 排除号码标题
ttk.Label(exclude_frame, text=self.labels[0], font=('微软雅黑', 10, 'bold')).pack(
anchor=tk.W, padx=10, pady=(5, 0))
# 创建前区和后区输入框
self.exclude_front_entries = create_number_entries(
exclude_frame, self.labels[1], 10, 1, 35)
self.exclude_back_entries = create_number_entries(
exclude_frame, self.labels[2], 10, 1, 12)
# 推荐号码区
recommend_frame = ttk.LabelFrame(self.frame, text=" 推荐号码 ", font=('微软雅黑', 10))
recommend_frame.pack(fill=tk.X, padx=20, pady=10, ipady=5)
# 推荐号码标题
ttk.Label(recommend_frame, text=self.labels[3], font=('微软雅黑', 10, 'bold')).pack(
anchor=tk.W, padx=10, pady=(5, 0))
# 前区推荐
front_rec_frame = ttk.Frame(recommend_frame)
front_rec_frame.pack(fill=tk.X, padx=10, pady=5)
ttk.Label(front_rec_frame, text=self.labels[4], font=('微软雅黑', 10)).pack(side=tk.LEFT)
self.recommend_front_var = tk.StringVar()
ttk.Entry(
front_rec_frame,
textvariable=self.recommend_front_var,
state='readonly',
font=('微软雅黑', 10),
readonlybackground='#f0f5f0'
).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
# 后区推荐
back_rec_frame = ttk.Frame(recommend_frame)
back_rec_frame.pack(fill=tk.X, padx=10, pady=5)
ttk.Label(back_rec_frame, text=self.labels[5], font=('微软雅黑', 10)).pack(side=tk.LEFT)
self.recommend_back_var = tk.StringVar()
ttk.Entry(
back_rec_frame,
textvariable=self.recommend_back_var,
state='readonly',
font=('微软雅黑', 10),
readonlybackground='#f0f5f0'
).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
# 结果区
result_frame = ttk.LabelFrame(self.frame, text=" 分析结果 ", font=('微软雅黑', 10))
result_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10, ipady=5)
# 结果文本框
self.result_text = scrolledtext.ScrolledText(
result_frame,
wrap=tk.WORD,
font=('微软雅黑', 10),
height=6
)
self.result_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
self.result_text.insert(tk.END, "请设置排除号码后点击'运行'按钮开始分析\n")
self.result_text.config(state=tk.DISABLED)
# 按钮区域
btn_frame = ttk.Frame(self.frame)
btn_frame.pack(fill=tk.X, pady=10)
self.analyze_btn = ttk.Button(
btn_frame,
text="运行分析",
command=self._on_analyze_clicked
)
self.analyze_btn.pack(side=tk.LEFT, padx=5)
self.save_btn = ttk.Button(
btn_frame,
text="保存配置",
command=self._save_config
)
self.save_btn.pack(side=tk.LEFT, padx=5)
def _safe_update_ui(self, callback, *args):
"""线程安全的UI更新"""
if not self.frame.winfo_exists():
return
self.frame.after(0, lambda: callback(*args))
def _register_event_handlers(self):
"""注册事件处理器"""
# 修复:添加事件类型检查
if hasattr(EventType, 'ANALYSIS_RESULT'):
event_center.subscribe(
event_type=EventType.ANALYSIS_RESULT,
token=self.token,
callback=lambda event: self._handle_analysis_result(event)
)
else:
self.logger.warning("EventType缺少ANALYSIS_RESULT定义")
def _handle_module_run(self, event):
"""处理模块运行事件"""
if not hasattr(event, 'data'):
self.logger.error("收到无效的运行事件: 缺少data属性")
return
if event.target != getattr(self.module, 'MODULE_ID', 'input_analysis'):
return
self._on_analyze_clicked() # 复用现有分析逻辑
def _load_saved_data(self):
"""加载保存的数据"""
save_path = GlobalConfig.MODULE1_SAVE_PATH
if not os.path.exists(save_path):
return
try:
with open(save_path, 'r', encoding='utf-8') as f:
saved_data = json.load(f)
# 恢复前区排除号码
if 'exclude_front' in saved_data:
for i, num in enumerate(saved_data['exclude_front']):
if i < len(self.exclude_front_entries) and num:
try:
formatted_num = f"{int(num):02d}"
self.exclude_front_entries[i].delete(0, tk.END)
self.exclude_front_entries[i].insert(0, formatted_num)
except ValueError:
continue
# 恢复后区排除号码
if 'exclude_back' in saved_data:
for i, num in enumerate(saved_data['exclude_back']):
if i < len(self.exclude_back_entries) and num:
try:
formatted_num = f"{int(num):02d}"
self.exclude_back_entries[i].delete(0, tk.END)
self.exclude_back_entries[i].insert(0, formatted_num)
except ValueError:
continue
except Exception as load_err:
self.logger.error(f"加载保存数据失败: {load_err}")
self._update_result_text(f"加载保存数据失败: {load_err}")
def _save_config(self):
"""保存当前配置"""
save_data = {
"exclude_front": [],
"exclude_back": []
}
# 收集前区排除号码
for entry in self.exclude_front_entries:
if entry.get().strip():
try:
save_data["exclude_front"].append(int(entry.get()))
except ValueError:
pass
# 收集后区排除号码
for entry in self.exclude_back_entries:
if entry.get().strip():
try:
save_data["exclude_back"].append(int(entry.get()))
except ValueError:
pass
# 保存到文件
try:
with open(GlobalConfig.MODULE1_SAVE_PATH, 'w', encoding='utf-8') as f:
json.dump(save_data, f, ensure_ascii=False, indent=2)
self._update_result_text("配置保存成功")
except Exception as save_err:
self.logger.error(f"保存配置失败: {save_err}")
self._update_result_text(f"保存配置失败: {save_err}")
def _on_analyze_clicked(self):
"""处理分析按钮点击事件"""
if not hasattr(Event, '__annotations__') or 'event_id' not in Event.__annotations__:
self.logger.warning("Event类缺少event_id属性定义")
exclude_front = []
exclude_back = []
try:
# 收集前区排除号码
for entry in self.exclude_front_entries:
if entry.get().strip():
try:
exclude_front.append(int(entry.get()))
except ValueError:
pass
# 收集后区排除号码
for entry in self.exclude_back_entries:
if entry.get().strip():
try:
exclude_back.append(int(entry.get()))
except ValueError:
pass
# 准备分析数据
analysis_data = {
'exclude_front': exclude_front,
'exclude_back': exclude_back
}
# 确定事件类型
run_event_type = getattr(EventType, 'MODULE_RUN',
getattr(EventType, 'MODULE_READY', 'module_run'))
# 发送分析命令事件
command_event = Event(
event_id=str(uuid.uuid4()),
type=run_event_type,
source=self.token,
target=getattr(self.module, 'MODULE_ID', 'input_analysis'),
data=analysis_data
)
event_center.publish(command_event)
self.analyze_btn.config(state='disabled')
self._update_result_text("分析中...", clear=True)
except Exception as analyze_error:
messagebox.showerror("输入错误", f"无效的输入格式: {analyze_error}")
self.analyze_btn.config(state='normal')
def run_analysis(self):
"""修复:使用正确的分析对象"""
if self.module:
result = self.module.analyze()
print(result) # 或者将结果显示在UI上
else:
print("分析模块未初始化")
def _handle_analysis_result(self, event: Event):
"""处理分析结果事件"""
if not hasattr(event, 'data'):
self.logger.error("收到无效的分析结果事件: 缺少data属性")
return
self.frame.after(0, lambda: self._display_results(event.data))
def _handle_error(self, event: Event):
"""处理错误事件"""
error_msg = event.data.get('error', '未知错误') if hasattr(event, 'data') else '未知错误'
self.frame.after(0, lambda: self._show_error(error_msg))
self.frame.after(0, lambda: self.analyze_btn.config(state='normal'))
def _display_results(self, data):
"""显示分析结果"""
if not isinstance(data, dict):
self.logger.error(f"无效的结果数据类型: {type(data)}")
return
try:
# 更新推荐号码
if 'recommended_fronts' in data:
self.recommend_front_var.set(' '.join(map(str, data['recommended_fronts'])))
if 'recommended_backs' in data:
self.recommend_back_var.set(' '.join(map(str, data['recommended_backs'])))
# 更新结果文本框
result_text = f"分析完成: {time.strftime('%H:%M:%S')}\n"
if 'recommended_fronts' in data:
result_text += f"前区推荐: {', '.join(map(str, data['recommended_fronts']))}\n"
if 'recommended_backs' in data:
result_text += f"后区推荐: {', '.join(map(str, data['recommended_backs']))}\n"
self._update_result_text(result_text)
self.analyze_btn.config(state='normal')
except Exception as display_err:
self._show_error(f"结果显示错误: {display_err}")
def _update_result_text(self, text, clear=False):
"""更新结果文本框内容"""
self.result_text.config(state=tk.NORMAL)
if clear:
self.result_text.delete(1.0, tk.END)
self.result_text.insert(tk.END, text + "\n")
self.result_text.see(tk.END)
self.result_text.config(state=tk.DISABLED)
def _show_error(self, error_msg):
"""显示错误信息"""
messagebox.showerror("分析错误", error_msg)
self._update_result_text(f"分析失败: {error_msg}")
self.recommend_front_var.set("分析失败")
self.recommend_back_var.set("分析失败")
def _auto_format_entry(self, event):
"""自动格式化输入框内容"""
entry = event.widget
current = entry.get().strip()
if current.isdigit():
formatted = self._format_number(current)
if formatted != current:
entry.delete(0, tk.END)
entry.insert(0, formatted)
if len(current) == 2:
self._focus_adjacent_entry(entry, 1)
def _focus_adjacent_entry(self, current_entry, direction):
"""焦点跳转到相邻输入框"""
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)
if __name__ == "__main__":
root = tk.Tk()
root.title("输入分析模块测试")
root.geometry("600x600")
main_frame = ttk.Frame(root)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
try:
InputAnalysisUI(main_frame)
except Exception as e:
messagebox.showerror("致命错误", f"应用程序初始化失败: {e}")
sys.exit(1)
root.mainloop()
最新发布