#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 策略编辑器 GUI 版本 使用 PyQt5 实现图形界面,功能与 strategy_editor.py 一致 """ import os import sys import re import glob from datetime import datetime # 导入 PyQt5 模块 from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QListWidget, QTextEdit, QInputDialog, QMessageBox, QGroupBox, QSplitter, QStatusBar ) from PyQt5.QtCore import Qt # 导入策略编辑器核心功能 from strategy_editor import StrategyEditor class StrategyEditorGUI(QMainWindow): """策略编辑器 GUI 类""" def __init__(self): super().__init__() # 初始化策略编辑器核心 self.editor = StrategyEditor() # 设置窗口标题和大小 self.setWindowTitle("策略编辑器") self.setGeometry(100, 100, 1200, 800) # 初始化界面组件 self.init_ui() # 加载策略列表 self.load_strategy_list() def init_ui(self): """初始化界面组件""" # 创建中心部件 central_widget = QWidget() self.setCentralWidget(central_widget) # 创建主布局 main_layout = QHBoxLayout(central_widget) # 创建分割器 splitter = QSplitter(Qt.Horizontal) main_layout.addWidget(splitter) # 创建左侧策略列表区域 self.strategy_list_widget = self.create_strategy_list() splitter.addWidget(self.strategy_list_widget) # 创建右侧编辑区域 self.editor_widget = self.create_editor() splitter.addWidget(self.editor_widget) # 设置分割器比例 splitter.setSizes([200, 1000]) # 创建状态栏 self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage("就绪") def create_strategy_list(self): """创建策略列表区域""" group_box = QGroupBox("可用策略") layout = QVBoxLayout(group_box) # 创建策略列表 self.strategy_list = QListWidget() self.strategy_list.itemClicked.connect(self.on_strategy_selected) layout.addWidget(self.strategy_list) # 创建操作按钮 button_layout = QVBoxLayout() self.new_btn = QPushButton("新建策略") self.new_btn.clicked.connect(self.on_new_strategy) button_layout.addWidget(self.new_btn) self.open_btn = QPushButton("打开策略") self.open_btn.clicked.connect(self.on_open_strategy) button_layout.addWidget(self.open_btn) self.delete_btn = QPushButton("删除策略") self.delete_btn.clicked.connect(self.on_delete_strategy) button_layout.addWidget(self.delete_btn) self.refresh_btn = QPushButton("刷新列表") self.refresh_btn.clicked.connect(self.load_strategy_list) button_layout.addWidget(self.refresh_btn) layout.addLayout(button_layout) return group_box def create_editor(self): """创建代码编辑区域""" group_box = QGroupBox("策略编辑") layout = QVBoxLayout(group_box) # 创建当前策略信息标签 self.current_strategy_label = QLabel("未选择策略") self.current_strategy_label.setStyleSheet("font-weight: bold;") layout.addWidget(self.current_strategy_label) # 创建代码编辑器 self.code_editor = QTextEdit() self.code_editor.setPlainText("# 请先选择或创建策略") layout.addWidget(self.code_editor) # 创建保存按钮 self.save_btn = QPushButton("保存策略") self.save_btn.clicked.connect(self.on_save_strategy) layout.addWidget(self.save_btn) return group_box def load_strategy_list(self): """加载策略列表""" self.strategy_list.clear() # 获取策略文件 strategy_files = glob.glob(os.path.join(self.editor.strategy_dir, '*.py')) for file_path in strategy_files: if os.path.basename(file_path) in ['__init__.py', 'base_strategy.py', 'market_filter.py']: continue file_name = os.path.basename(file_path) # 读取文件内容,获取类定义 try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() # 查找类定义 class_match = re.search(r'class\s+(\w+)\s*\(', content) if class_match: class_name = class_match.group(1) self.strategy_list.addItem(f"{class_name} ({file_name})") else: self.strategy_list.addItem(f"{file_name.replace('.py', '')} ({file_name})") except Exception as e: QMessageBox.warning(self, "错误", f"读取文件 {file_name} 失败: {str(e)}") def on_strategy_selected(self, item): """选择策略时的处理""" strategy_info = item.text() # 提取策略名称 strategy_name = strategy_info.split(' ')[0] # 读取策略 if self.editor.read_strategy(strategy_name): self.current_strategy_label.setText(f"当前策略: {self.editor.current_strategy_name}") self.code_editor.setPlainText(self.editor.current_strategy_content) self.status_bar.showMessage(f"已加载策略: {strategy_name}") else: QMessageBox.warning(self, "错误", f"无法加载策略: {strategy_name}") def on_new_strategy(self): """新建策略""" strategy_name, ok = QInputDialog.getText( self, "新建策略", "请输入策略名称(首字母大写):" ) if ok and strategy_name: if self.editor.create_new_strategy(strategy_name): # 更新界面 self.current_strategy_label.setText(f"当前策略: {self.editor.current_strategy_name}") self.code_editor.setPlainText(self.editor.current_strategy_content) self.load_strategy_list() # 刷新策略列表 self.status_bar.showMessage(f"已创建新策略: {strategy_name}") else: QMessageBox.warning(self, "错误", "策略创建失败,请检查策略名称是否合法或已存在") def on_open_strategy(self): """打开策略""" strategy_name, ok = QInputDialog.getText( self, "打开策略", "请输入策略名称:" ) if ok and strategy_name: if self.editor.read_strategy(strategy_name): self.current_strategy_label.setText(f"当前策略: {self.editor.current_strategy_name}") self.code_editor.setPlainText(self.editor.current_strategy_content) self.status_bar.showMessage(f"已加载策略: {strategy_name}") else: QMessageBox.warning(self, "错误", f"无法找到策略: {strategy_name}") def on_save_strategy(self): """保存策略""" if not self.editor.current_strategy_name: QMessageBox.warning(self, "错误", "请先选择或创建策略") return # 获取编辑器内容 content = self.code_editor.toPlainText() if not content: QMessageBox.warning(self, "错误", "策略内容不能为空") return # 更新当前策略内容 self.editor.current_strategy_content = content # 保存策略 if self.editor.save_strategy(): self.status_bar.showMessage(f"已保存策略: {self.editor.current_strategy_name}") QMessageBox.information(self, "成功", f"策略 {self.editor.current_strategy_name} 保存成功") else: QMessageBox.warning(self, "错误", "策略保存失败") def on_delete_strategy(self): """删除策略""" # 获取当前选中的策略 current_item = self.strategy_list.currentItem() if not current_item: QMessageBox.warning(self, "错误", "请先选择要删除的策略") return strategy_info = current_item.text() strategy_name = strategy_info.split(' ')[0] # 确认删除 reply = QMessageBox.question( self, "确认删除", f"确定要删除策略 {strategy_name} 吗?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No ) if reply == QMessageBox.Yes: if self.editor.delete_strategy(strategy_name): # 清空当前编辑内容 self.current_strategy_label.setText("未选择策略") self.code_editor.setPlainText("# 请先选择或创建策略") # 刷新策略列表 self.load_strategy_list() self.status_bar.showMessage(f"已删除策略: {strategy_name}") else: QMessageBox.warning(self, "错误", f"无法删除策略: {strategy_name}") def main(): """主函数""" # 创建应用程序 app = QApplication(sys.argv) # 创建主窗口 window = StrategyEditorGUI() # 显示窗口 window.show() # 运行应用程序 sys.exit(app.exec_()) if __name__ == "__main__": main()