import tkinter as tk
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import math
import random
import time
import sys
class CornerMarkModule:
def __init__(self, parent, width, height, module_id, label_text):
self.parent = parent
self.width = width
self.height = height
self.module_id = module_id
self.label_text = label_text
self.line_ids = []
self.animation_id = None
self.active_flows = [] # 存储当前活动的数据流
# 创建画布
self.canvas = tk.Canvas(
parent,
width=width,
height=height,
bg="#121212",
highlightthickness=0,
bd=0,
relief="flat"
)
self.canvas.pack(fill=tk.BOTH, expand=True)
# 计算中心位置
self.square_size = 80
self.start_x = width // 2 - self.square_size // 2
self.start_y = height // 2 - self.square_size // 2 - 10
# 创建蓝色圆角矩形
self.square = self.create_round_rect(
self.start_x, self.start_y,
self.start_x + self.square_size,
self.start_y + self.square_size,
radius=15,
fill="#325b74",
outline="#5a9bc0",
width=2
)
# 添加标签文本
self.label_id = self.canvas.create_text(
width // 2, height // 2 - 10,
text=label_text,
fill="#e0e0e0",
font=("Microsoft YaHei", 11, "bold"),
width=self.square_size - 10,
justify="center"
)
# 添加模块编号标签
self.canvas.create_text(
width // 2, height - 30,
text=f"模块 {module_id}",
fill="#7a7a7a",
font=("Microsoft YaHei", 9)
)
# 添加装饰线条
self.decor_line = self.canvas.create_line(
width//2 - 40, height - 25,
width//2 + 40, height - 25,
fill="#3a6b8c",
width=1,
dash=(4, 2)
)
# 初始参数
self.base_gap = 12
self.base_length = 30
self.create_all_lines()
# 动画计数器
self.counter = 0
# 绑定悬停效果
self.canvas.bind("<Enter>", self.on_enter)
self.canvas.bind("<Leave>", self.on_leave)
def on_enter(self, event):
"""鼠标悬停效果"""
self.canvas.itemconfig(self.square, fill="#5a9bc0")
for line_id in self.line_ids:
self.canvas.itemconfig(line_id, fill="#5a9bc0")
self.canvas.itemconfig(self.decor极, fill="#5a9bc0")
def on_leave(self, event):
"""鼠标离开效果"""
self.canvas.itemconfig(self.square, fill="#325b74")
for line_id in self.line_ids:
self.canvas.itemconfig(line_id, fill="#3a6b8c")
self.canvas.itemconfig(self.decor_line, fill="#3a6b8c")
def create_round_rect(self, x1, y1, x2, y2, radius=25, **kwargs):
"""创建圆角矩形"""
points = [
x1 + radius, y1, # 左上角
x2 - radius, y1, x2, y1, x2, y1 + radius, # 右上角
x2, y2 - radius, x2, y2, x2 - radius, y2, # 右下角
x1 + radius, y2, x1, y2, x1, y2 - radius, # 左下角
x1, y1 + radius, x1, y1, x1 + radius, y1
]
return self.canvas.create_polygon(points, **kwargs, smooth=True)
def create_all_lines(self):
line_color = "#3a6b8c"
# 左上角标记
self.line_ids.append(self.canvas.create_line(
self.start_x - self.base_gap, self.start_y - self.base_gap,
self.start_x - self.base_gap + self.base_length, self.start_y - self.base_gap,
width=2, fill=line_color
))
self.line_ids.append(self.canvas.create_line(
self.start_x - self.base_gap, self.start_y - self.base_gap,
self.start_x - self.base_gap, self.start_y - self.base_gap + self.base_length,
width=2, fill=line_color
))
# 右上角标记
self.line_ids.append(self.canvas.create_line(
self.start_x + self.square_size + self.base_gap, self.start_y - self.base_gap,
self.start_x + self.square_size + self.base_gap - self.base_length, self.start_y - self.base_gap,
width=2, fill=line_color
))
self.line_ids.append(self.canvas.create_line(
self.start_x + self.square_size + self.base_gap, self.start_y - self.base_gap,
self.start_x + self.square_size + self.base_gap, self.start_y - self.base_gap + self.base_length,
width=2, fill=line_color
))
# 左下角标记
self.line_ids.append(self.canvas.create_line(
self.start_x - self.base_gap, self.start_y + self.square_size + self.base_gap,
self.start_x - self.base_gap + self.base_length, self.start_y + self.square_size + self.base_gap,
width=2, fill=line_color
))
self.line_ids.append(self.canvas.create_line(
self.start_x - self.base_gap, self.start_y + self.square_size + self.base_gap,
self.start_x - self.base_gap, self.start_y + self.square_size + self.base_gap - self.base_length,
width=2, fill=line_color
))
# 右下角标记
self.line_ids.append(self.canvas.create_line(
self.start_x + self.square_size + self.base_gap, self.start_y + self.square_size + self.base_gap,
self.start_x + self.square_size + self.base_gap - self.base_length, self.start_y + self.square_size + self.base_gap,
width=2, fill=line_color
))
self.line_ids.append(self.canvas.create_line(
self.start_x + self.square_size + self.base_gap, self.start_y + self.square_size + self.base_gap,
self.start_x + self.square_size + self.base_gap, self.start_y + self.square_size + self.base_gap - self.base_length,
width=2, fill=line_color
))
def update_animation(self):
"""更新角标动画"""
phase = self.counter * 0.08
self.counter += 1
phase_offset = self.module_id * 0.5
distance_factor = 0.5 * math.sin(phase + phase_offset) + 0.5
current_gap = 5 + distance_factor * 20
current_length = 25 + distance_factor * 15
self.update_lines(current_gap, current_length)
self.animation_id = self.parent.after(50, self.update_animation)
def pause_animation(self):
"""暂停动画"""
if self.animation_id:
self.parent.after_cancel(self.animation_id)
self.animation_id = None
def resume_animation(self):
"""恢复动画"""
if not self.animation_id:
self.update_animation()
def reset_counter(self):
"""重置计数器"""
self.counter = 0
def update_lines(self, gap, length):
"""更新角标线条位置"""
# 左上角
self.canvas.coords(self.line_ids[0], self.start_x - gap, self.start_y - gap, self.start_x - gap + length, self.start_y - gap)
self.canvas.coords(self.line_ids[1], self.start_x - gap, self.start_y - gap, self.start_x - gap, self.start_y - gap + length)
# 右上角
self.canvas.coords(self.line_ids[2], self.start_x + self.square_size + gap, self.start_y - gap, self.start_x + self.square_size + gap - length, self.start_y - gap)
self.canvas.coords(self.line_ids[3], self.start_x + self.square_size + gap, self.start_y - gap, self.start_x + self.square_size + gap, self.start_y - gap + length)
# 左下角
self.canvas.coords(self.line_ids[4], self.start_x - gap, self.start_y + self.square_size + gap, self.start_x - gap + length, self.start_y + self.square_size + gap)
self.canvas.coords(self.line_ids[5], self.start_x - gap, self.start_y + self.square_size + gap, self.start_x - gap, self.start_y + self.square_size + gap - length)
# 右下角
self.canvas.coords(self.line_ids[6], self.start_x + self.square_size + gap, self.start_y + self.square_size + gap, self.start_x + self.square_size + gap - length, self.start_y + self.square_size + gap)
self.canvas.coords(self.line_ids[7], self.start_x + self.square_size + gap, self.start_y + self.square_size + gap, self.start_x + self.square_size + gap, self.start_y + self.square_size + gap - length)
def get_center(self):
"""获取模块中心位置"""
return (self.width // 2, self.height // 2 - 10)
class DataFlowManager:
"""管理模块间数据流动画的类"""
def __init__(self, modules, canvas):
self.modules = modules
self.canvas = canvas
self.flows = []
self.active_flows = []
self.connections = self.define_connections()
def define_connections(self):
"""定义模块之间的连接关系"""
return [
# (from_module_id, to_module_id, color)
(1, 2, "#ff6b6b"), # 干扰 -> 威胁分析
(2, 4, "#4ecdc4"), # 威胁分析 -> 知识库
(2, 5, "#ffd166"), # 威胁分析 -> 推理引擎
(5, 6, "#1a936f"), # 推理引擎 -> 决策输出
(6, 4, "#9b5de5"), # 决策输出 -> 知识库
(3, 1, "#5a9bc0") # 抗干扰中 -> 干扰
]
def get_module_by_id(self, module_id):
"""根据ID获取模块实例"""
for module in self.modules:
if module.module_id == module_id:
return module
return None
def start_flow(self, from_module_id, to_module_id, color):
"""启动数据流动画"""
from_module = self.get_module_by_id(from_module_id)
to_module = self.get_module_by_id(to_module_id)
if not from_module or not to_module:
return
from_x, from_y = from_module.get_center()
to_x, to_y = to_module.get_center()
# 调整位置到模块容器的绝对位置
from_x += from_module.winfo_x()
from_y += from_module.winfo_y()
to_x += to_module.winfo_x()
to_y += to_module.winfo_y()
# 创建流动点
flow_id = self.canvas.create_oval(0, 0, 0, 0, fill=color, outline="")
flow = {
'id': flow_id,
'from': (from_x, from_y),
'to': (to_x, to_y),
'progress': 0.0,
'speed': random.uniform(0.02, 0.05),
'color': color
}
self.active_flows.append(flow)
def update_flows(self):
"""更新所有数据流动画"""
flows_to_remove = []
for flow in self.active_flows:
flow['progress'] += flow['speed']
if flow['progress'] >= 1.0:
flows_to_remove.append(flow)
continue
# 使用贝塞尔曲线使路径更自然
x, y = self.calculate_bezier_point(
flow['from'][0], flow['from'][1],
flow['to'][0], flow['to'][1],
flow['progress']
)
# 更新流动点位置
r = 6
self.canvas.coords(flow['id'], x-r, y-r, x+r, y+r)
# 移除已完成动画
for flow in flows_to_remove:
self.canvas.delete(flow['id'])
self.active_flows.remove(flow)
# 随机生成新数据流
if random.random() < 0.2 and len(self.active_flows) < 15:
conn = random.choice(self.connections)
self.start_flow(conn[0], conn[1], conn[2])
# 继续动画
self.canvas.after(50, self.update_flows)
def calculate_bezier_point(self, x0, y0, x1, y1, t):
"""计算贝塞尔曲线上的点"""
# 控制点偏移量
ctrl_offset = 0.3 * math.sqrt((x1-x0)**2 + (y1-y0)**2)
# 计算控制点
angle = math.atan2(y1 - y0, x1 - x0)
ctrl_x1 = x0 + ctrl_offset * math.cos(angle + math.pi/4)
ctrl_y1 = y0 + ctrl_offset * math.sin(angle + math.pi/4)
ctrl_x2 = x1 - ctrl_offset * math.cos(angle - math.pi/4)
ctrl_y2 = y1 - ctrl_offset * math.sin(angle - math.pi/4)
# 三次贝塞尔曲线公式
u = 1 - t
tt = t * t
uu = u * u
uuu = uu * u
ttt = tt * t
x = uuu * x0 + 3 * uu * t * ctrl_x1 + 3 * u * tt * ctrl_x2 + ttt * x1
y = uuu * y0 + 3 * uu * t * ctrl_y1 + 3 * u * tt * ctrl_y2 + ttt * y1
return x, y
class SystemStatusBar(ttk.Frame):
"""系统状态栏组件"""
def __init__(self, parent):
super().__init__(parent, padding=(10, 5))
self.pack(fill=tk.X, pady=(15, 5))
# 系统状态
self.status_label = ttk.Label(
self,
text="系统状态: 运行中",
font=("Microsoft YaHei", 10),
bootstyle="success"
)
self.status_label.pack(side=tk.LEFT, padx=10)
# 数据流状态
self.flow_label = ttk.Label(
self,
text="数据流: 正常",
font=("Microsoft YaHei", 10),
bootstyle="info"
)
self.flow_label.pack(side=tk.LEFT, padx=10)
# 威胁级别
self.threat_label = ttk.Label(
self,
text="威胁级别: 低",
font=("Microsoft YaHei", 10),
bootstyle="warning"
)
self.threat_label.pack(side=tk.LEFT, padx=10)
# 更新时间
self.time_label = ttk.Label(
self,
text="",
font=("Microsoft YaHei", 10),
bootstyle="secondary"
)
self.time_label.pack(side=tk.RIGHT, padx=10)
self.update_time()
def update_time(self):
"""更新时间显示"""
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
self.time_label.config(text=f"更新时间: {current_time}")
self.after(1000, self.update_time)
def create_dynamic_flow_visualization():
"""创建动态数据流可视化系统"""
# 创建主窗口
root = ttk.Window(title="动态数据流可视化系统", themename="superhero")
root.configure(bg="#121212")
# 设置窗口大小并居中
window_width = 1400
window_height = 800
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
center_x = int(screen_width/2 - window_width/2)
center_y = int(screen_height/2 - window_height/2)
root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}")
# 创建主容器框架
main_container = ttk.Frame(root, padding=(30, 20, 30, 10))
main_container.pack(fill=tk.BOTH, expand=True)
# 创建标题栏
header_frame = ttk.Frame(main_container)
header_frame.pack(fill=tk.X, pady=(0, 20))
title_label = ttk.Label(
header_frame,
text="动态数据流可视化系统",
font=("Microsoft YaHei", 18, "bold"),
bootstyle="inverse-primary"
)
title_label.pack(side=tk.LEFT)
subtitle = ttk.Label(
header_frame,
text="实时监控与响应系统",
font=("Microsoft YaHei", 12),
bootstyle="secondary"
)
subtitle.pack(side=tk.LEFT, padx=(15, 0), pady=(5, 0))
# 添加控制按钮
control_frame = ttk.Frame(header_frame)
control_frame.pack(side=tk.RIGHT)
# 创建网格容器
grid_container = ttk.Frame(main_container)
grid_container.pack(fill=tk.BOTH, expand=True)
# 配置网格布局
grid_container.grid_rowconfigure(0, weight=1)
grid_container.grid_rowconfigure(1, weight=1)
grid_container.grid_rowconfigure(2, weight=1)
grid_container.grid_columnconfigure(0, weight=1)
grid_container.grid_columnconfigure(1, weight=1)
grid_container.grid_columnconfigure(2, weight=1)
grid_container.grid_columnconfigure(3, weight=1)
# 定义模块标签文本
labels = ["干扰", "威胁分析", "抗干扰中", "知识库", "推理引擎", "决策输出"]
# 创建模块容器
modules = []
# 抗干扰中 - 第1行第2列
cell0 = ttk.Frame(grid_container)
cell0.grid(row=0, column=1, padx=15, pady=15, sticky="nsew")
module0 = CornerMarkModule(cell0, 220, 280, 3, labels[2])
modules.append(module0)
# 知识库 - 第3行第2列
cell1 = ttk.Frame(grid_container)
cell1.grid(row=2, column=1, padx=15, pady=15, sticky="nsew")
module1 = CornerMarkModule(cell1, 220, 280, 4, labels[3])
modules.append(module1)
# 干扰 - 第2行第1列
cell2 = ttk.Frame(grid_container)
cell2.grid(row=1, column=0, padx=15, pady=15, sticky="nsew")
module2 = CornerMarkModule(cell2, 220, 280, 1, labels[0])
modules.append(module2)
# 威胁分析 - 第2行第2列
cell3 = ttk.Frame(grid_container)
cell3.grid(row=1, column=1, padx=15, pady=15, sticky="nsew")
module3 = CornerMarkModule(cell3, 220, 280, 2, labels[1])
modules.append(module3)
# 推理引擎 - 第2行第3列
cell4 = ttk.Frame(grid_container)
cell4.grid(row=1, column=2, padx=15, pady=15, sticky="nsew")
module4 = CornerMarkModule(cell4, 220, 280, 5, labels[4])
modules.append(module4)
# 决策输出 - 第2行第4列
cell5 = ttk.Frame(grid_container)
cell5.grid(row=1, column=3, padx=15, pady=15, sticky="nsew")
module5 = CornerMarkModule(cell5, 220, 280, 6, labels[5])
modules.append(module5)
# 创建数据流画布
flow_canvas = tk.Canvas(
grid_container,
bg="#121212",
highlightthickness=0,
bd=0
)
flow_canvas.place(relx=0, rely=0, relwidth=1, relheight=1)
flow_canvas.lower() # 置于底层
# 创建数据流管理器
flow_manager = DataFlowManager(modules, flow_canvas)
# 启动所有模块的动画
for module in modules:
module.update_animation()
# 启动数据流动画
flow_manager.update_flows()
# 添加系统状态栏
status_bar = SystemStatusBar(main_container)
# 添加控制按钮
exit_button = ttk.Button(
control_frame,
text="安全退出",
command=root.destroy,
bootstyle="danger-outline",
width=12
)
exit_button.pack(side=tk.RIGHT, padx=5)
pause_button = ttk.Button(
control_frame,
text="暂停动画",
command=lambda: toggle_animation(modules, pause_button, flow_manager),
bootstyle="warning-outline",
width=12
)
pause_button.pack(side=tk.RIGHT, padx=5)
# 添加性能优化按钮
optimize_button = ttk.Button(
control_frame,
text="性能优化",
command=lambda: optimize_performance(modules, flow_manager),
bootstyle="info-outline",
width=12
)
optimize_button.pack(side=tk.RIGHT, padx=5)
# 绑定窗口关闭事件
root.protocol("WM_DELETE_WINDOW", lambda: safe_exit(root, modules, flow_manager))
root.mainloop()
def safe_exit(root, modules, flow_manager):
"""安全退出程序"""
for module in modules:
module.pause_animation()
root.destroy()
sys.exit()
def toggle_animation(modules, button, flow_manager):
"""切换动画状态"""
if button.cget("text") == "暂停动画":
for module in modules:
module.pause_animation()
button.configure(text="继续动画")
else:
for module in modules:
module.resume_animation()
button.configure(text="暂停动画")
def optimize_performance(modules, flow_manager):
"""优化系统性能"""
# 简化动画效果
for module in modules:
module.pause_animation()
module.resume_animation()
# 减少数据流动画数量
# 实际应用中可添加更多优化逻辑
if __name__ == "__main__":
create_dynamic_flow_visualization()
解析一下这段代码