fix: 修复GUI界面图表显示和事件处理问题

This commit is contained in:
dmy
2026-01-04 12:05:06 +08:00
parent 6f2f851a6e
commit 06680a6e33

30
gui.py
View File

@@ -113,15 +113,23 @@ def index():
if refs['plot_container']: if refs['plot_container']:
refs['plot_container'].clear() refs['plot_container'].clear()
with refs['plot_container']: with refs['plot_container']:
# 使用 ui.pyplot 上下文自动管理 figure 生命周期
with ui.pyplot(figsize=(10, 8)) as plot: with ui.pyplot(figsize=(10, 8)) as plot:
title = f"{result['name']}\nCost: ¥{result['cost']/10000:.2f}万 | Loss: {result['loss']:.2f} kW" title = f"{result['name']}\nCost: ¥{result['cost']/10000:.2f}万 | Loss: {result['loss']:.2f} kW"
# 获取当前 ui.pyplot 创建的 axes # 显式获取当前 ui.pyplot 创建的 axes,并传递给绘图函数
# 确保绘图发生在正确的 figure 上
ax = plt.gca() ax = plt.gca()
visualize_design(result['turbines'], state['substation'], result['eval']['details'], title, ax=ax) visualize_design(result['turbines'], state['substation'], result['eval']['details'], title, ax=ax)
def handle_row_click(e): def handle_row_click(e):
if not e.args or 'data' not in e.args: return # ui.table row-click args: [evt, row, index]
row_name = e.args['data']['name'] row = None
if e.args and isinstance(e.args, list) and len(e.args) > 1:
row = e.args[1]
if not row or 'name' not in row: return
row_name = row['name']
selected_res = next((r for r in state['results'] if r['name'] == row_name), None) selected_res = next((r for r in state['results'] if r['name'] == row_name), None)
if selected_res: if selected_res:
update_plot(selected_res) update_plot(selected_res)
@@ -161,18 +169,24 @@ def index():
# 2. 定义在线程中运行的任务 # 2. 定义在线程中运行的任务
def task(): def task():
# 捕获 stdout 到我们的 QueueLogger # 捕获 stdout 到我们的 QueueLogger
# 禁止 main.py 中的后台绘图,避免线程安全问题
with contextlib.redirect_stdout(QueueLogger()): with contextlib.redirect_stdout(QueueLogger()):
return compare_design_methods( return compare_design_methods(
excel_path=state['excel_path'], excel_path=state['excel_path'],
n_clusters_override=n_clusters, n_clusters_override=n_clusters,
interactive=False, interactive=False,
plot_results=False # 禁止后台绘图,避免线程安全问题 plot_results=False
) )
# 在后台线程运行计算任务
results = await run.io_bound(task) results = await run.io_bound(task)
state['results'] = results state['results'] = results
if not state['excel_path'] and results: if not state['excel_path'] and results:
if state['substation'] is None: if state['substation'] is None:
_, state['substation'] = generate_wind_farm_data(n_turbines=30, layout='grid', spacing=800) _, state['substation'] = generate_wind_farm_data(n_turbines=30, layout='grid', spacing=800)
# 更新结果表格
if refs['results_table']: if refs['results_table']:
table_data = [] table_data = []
for res in results: for res in results:
@@ -180,7 +194,7 @@ def index():
refs['results_table'].rows = table_data refs['results_table'].rows = table_data
refs['results_table'].update() refs['results_table'].update()
# 计算完成后,自动寻找并显示最佳方案的拓扑图 (不再显示4合1大图) # 计算完成后,自动寻找并显示最佳方案的拓扑图
if results: if results:
best_res = min(results, key=lambda x: x['cost']) best_res = min(results, key=lambda x: x['cost'])
update_plot(best_res) update_plot(best_res)
@@ -190,6 +204,8 @@ def index():
if refs['status_label']: refs['status_label'].text = "计算完成!" if refs['status_label']: refs['status_label'].text = "计算完成!"
except Exception as ex: except Exception as ex:
ui.notify(f'运行出错: {ex}', type='negative') ui.notify(f'运行出错: {ex}', type='negative')
import traceback
traceback.print_exc()
finally: finally:
log_timer.cancel() log_timer.cancel()
process_log_queue() process_log_queue()
@@ -227,7 +243,7 @@ def index():
] ]
# 移除 selection='single',改为纯行点击交互 # 移除 selection='single',改为纯行点击交互
refs['results_table'] = ui.table(columns=columns, rows=[]).classes('w-full') refs['results_table'] = ui.table(columns=columns, rows=[]).classes('w-full')
refs['results_table'].on('rowClick', handle_row_click) refs['results_table'].on('row-click', handle_row_click)
with ui.card().classes('w-full p-4 shadow-md'): with ui.card().classes('w-full p-4 shadow-md'):
ui.label('拓扑可视化').classes('text-xl font-semibold mb-2') ui.label('拓扑可视化').classes('text-xl font-semibold mb-2')
refs['plot_container'] = ui.column().classes('w-full items-center') refs['plot_container'] = ui.column().classes('w-full items-center')
@@ -235,4 +251,4 @@ def index():
ui.label('导出与下载').classes('text-xl font-semibold mb-2') ui.label('导出与下载').classes('text-xl font-semibold mb-2')
refs['export_row'] = ui.row().classes('gap-4') refs['export_row'] = ui.row().classes('gap-4')
ui.run(title='海上风电场集电线路优化', port=8080) ui.run(title='海上风电场集电线路优化', port=8080)