未给Editor指定icon引发的异常

扩展elcipse.ui.editor时报了[color=red]org.eclipse.ui.PartInitException: Unable to open editor, unknown editor ID: XXX[/color]异常,以前也报过这个异常,那是因为eclipse没有自动将扩展加入启动配置中,需要手动添加一上,而这一次排除了这种可能,也排除了editorId不一致的可能,那么到底是什么原因呢?
反复查看配置文件(plugin.xml)都没有发现有任何问题,确定配置文件没有问题后开始折腾其他地方,结果一阵折腾之后还是没有发现问题,于是又把注意力回到了配置文件上,通过对比其他的配置文件发现一个差别这次配置文件中没有配置icon属性,而以往做扩展时都配置了的,会不会是这个问题呢?但是又没道理啊,这么牛x的eclipse不会这么一点点小小的容错能力都没有吧?
不管怎么样还是试一试吧(快要疯了),令人意想不到的结果出现了,设置了icon属性后不报错了,我的edior成功打开了... ...吐血,折腾了我这么长时间的问题竟然是一个小小的icon引起的。
看一下ediors.exsd中icon是怎么写的:[b]'a relative name of the icon that will be used for all resources that match the specified extensions.
An icon is not required if you specify a command rather than a class. In that case, the workbench will use the icon provided by the operating system.'[/b]也没有说icon是必须的啊????
再次疑惑中...

[b][size=medium][i][align=center][color=red][img]http://img.tongji.linezing.com/729225/tongji.gif[/img]希望踩的朋友也能留下宝贵批评意见,也能使我从中有所收获不断进步,不甚感激![/color][/align][/i][/size][/b]

[table]|[url="http://s.click.taobao.com/t_1?i=qX1eVuxw6cVJpA%3D%3D&p=mm_14390488_0_0&n=11"][img]http://image.taobao.com/bao/uploaded/http://img05.taobaocdn.com/bao/uploaded/i5/T1q4BpXl8gXXaNzWM3_045807.jpg_sum.jpg[/img]震撼手感 镭射防伪 Levi's钱包 李维斯钱包 软牛皮长款钱包[/url][/table][table]|[url="http://s.click.taobao.com/t_1?i=qX98H4zYjXIhAQ%3D%3D&p=mm_14390488_0_0&n=11"][img]http://image.taobao.com/bao/uploaded/http://img08.taobaocdn.com/bao/uploaded/i8/T1SylrXi4bXXaax._a_092611.jpg_sum.jpg[/img]09新款¥Levi's李维斯牛皮钱包/卡包/男士钱包 情侣款 新年礼物[/url][/table][table]|[url="http://s.click.taobao.com/t_1?i=qz75YSmrgO376A%3D%3D&p=mm_14390488_0_0&n=12"][img]http://image.taobao.com/bao/uploaded/http://img06.taobaocdn.com/bao/uploaded/i6/T1S3tkXi37zJPz3QzX_085801.jpg_sum.jpg[/img][/url][url="http://s.click.taobao.com/t_1?i=qz75YSmrgO376A%3D%3D&p=mm_14390488_0_0&n=12"]双冠信誉-诺基亚5800手机-触摸屏手机-大陆行货-全国联保[/url][b]2299.0元[/b][url="http://s.click.taobao.com/t_1?i=qz75YSmrgO376A%3D%3D&p=mm_14390488_0_0&n=12"][img]http://img.alimama.cn/images/tbk/cps/fgetccode_btn.gif[/img][/url][/table]
以下是main_window.py的完整代码: # 主窗口 - PyQt6 版本 import os import sys import datetime import logging import faulthandler # 启用详细日志和调试模式 import tracemalloc # 内存监控 import ctypes # 启用故障处理程序 faulthandler.enable() # 添加虚拟环境检查 if not hasattr(sys, 'real_prefix') and not hasattr(sys, 'base_prefix'): logging.warning("警告: 在虚拟环境中运行,建议使用虚拟环境") # 配置详细日志 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler("app_debug.log"), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) logger.info("应用程序启动") logger.info(f"Python 路径: {sys.executable}") logger.info(f"参数: {sys.argv}") # 添加更多诊断信息 logger.info(f"系统路径: {sys.path}") logger.info(f"工作目录: {os.getcwd()}") # 启用详细错误报告 faulthandler.enable() os.environ['QT_DEBUG_PLUGINS'] = '1' # 启用 Qt 插件调试 os.environ['QTWEBENGINE_CHROMIUM_FLAGS'] = '--disable-gpu --no-sandbox' # 禁用 GPU 加速 # 设置 Windows 错误报告 if sys.platform == 'win32': ctypes.windll.kernel32.SetErrorMode(0x0001 | 0x0002) # SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX # 设置堆栈保护 os.environ['QT_FATAL_CRITICALS'] = '1' os.environ['QT_FATAL_WARNINGS'] = '1' # 确保先导入PyQt6核心模块 try: from PyQt6.QtCore import QObject, pyqtSignal, PYQT_VERSION_STR, Qt, QRectF, QTimer from PyQt6.QtGui import QIcon, QPixmap, QColor, QFont, QAction from PyQt6.QtWidgets import ( QApplication, QMainWindow, QFileDialog, QSplitter, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QComboBox, QLabel, QStatusBar, QToolBar, QDockWidget, QTabWidget, QMessageBox, QInputDialog, QDialog, QMenu ) logger.info(f"PyQt6 版本: {PYQT_VERSION_STR}") except ImportError as e: logger.error(f"导入 PyQt6 失败: {str(e)}") # 添加更详细的错误信息 import traceback logger.error(traceback.format_exc()) # 无法继续运行,退出程序 sys.exit(1) # 然后导入其他模块 from src.auto_print_system.ui.template_editor import TemplateCanvas, TextRegionItem, QRRegionItem, LogoRegionItem from src.auto_print_system.ui.data_mapper import DataMapperWidget from src.auto_print_system.ui.preview_dialog import PreviewDialog from src.auto_print_system.ui.history_dialog import HistoryDialog from src.auto_print_system.core.project_manager import ProjectManager from src.auto_print_system.core.file_compositor import FileCompositor from src.auto_print_system.core.font_manager import FontManager logger = logging.getLogger(__name__) # 定义属性面板类 class BasePropertiesPanel(QWidget): propertyChanged = pyqtSignal(str, object) # 定义信号 def __init__(self, parent=None): super().__init__(parent) self.region = None self.setup_ui() def setup_ui(self): """子类实现具体UI布局""" pass def set_region(self, region): """设置当前区域""" self.region = region self.update_ui_from_region() def update_ui_from_region(self): """根据区域更新UI""" pass def update_region_from_ui(self): """根据UI更新区域""" pass class TextPropertiesPanel(BasePropertiesPanel): def setup_ui(self): layout = QVBoxLayout(self) layout.addWidget(QLabel("文本属性面板 - 实际实现需要添加更多控件")) # 这里添加实际的文本属性控件 self.setLayout(layout) def update_ui_from_region(self): if self.region and isinstance(self.region, TextRegionItem): # 根据区域更新UI控件 pass def update_region_from_ui(self): if self.region: # 根据UI更新区域属性 pass class QRPropertiesPanel(BasePropertiesPanel): def setup_ui(self): layout = QVBoxLayout(self) layout.addWidget(QLabel("二维码属性面板 - 实际实现需要添加更多控件")) # 这里添加实际的二维码属性控件 self.setLayout(layout) def update_ui_from_region(self): if self.region and isinstance(self.region, QRRegionItem): # 根据区域更新UI控件 pass class LogoPropertiesPanel(BasePropertiesPanel): def setup_ui(self): layout = QVBoxLayout(self) layout.addWidget(QLabel("Logo属性面板 - 实际实现需要添加更多控件")) # 这里添加实际的Logo属性控件 self.setLayout(layout) def update_ui_from_region(self): if self.region and isinstance(self.region, LogoRegionItem): # 根据区域更新UI控件 pass class MainWindow(QMainWindow): def __init__(self, data_path=None): super().__init__() #简化初始化 self.central_widget = None self.logo_path = None self.project_manager = None self.btn_generate = None self.field_mapping_widget = None self.btn_add_text = None self.btn_add_qr = None self.current_project = None self.spot_color_path = None self.compositor = None self.font_manager = None self.left_layout = None self.btn_upload = None self.btn_import_data = None self.template_canvas = None self.status_bar = None self.btn_rerun = None self.btn_history = None self.data_mapper = None self.btn_save_config = None self.right_layout = None self.logo_props_panel = None self.text_props_panel = None self.props_tabs = None self.qr_props_panel = None self.history_combo = None self.logger = logging.getLogger(__name__) self.logger.info("主窗口初始化开始") self.data_path = data_path try: # 尝试简化初始化 self.logger.info("尝试基本初始化...") self.setWindowTitle("自动打印系统") self.resize(800, 600) # 延迟加载复杂组件 self.logger.info("延迟加载复杂组件") QTimer.singleShot(100, self.delayed_init) except Exception as e: self.logger.exception("主窗口初始化期间发生错误") raise def delayed_init(self): try: self.logger.info("开始延迟初始化") self.init_components() self.logger.info("组件初始化完成") # 其他初始化... except Exception as e: self.logger.exception("延迟初始化期间发生错误") # 显示错误消息 QMessageBox.critical( self, "初始化错误", f"初始化过程中发生错误:\n{str(e)}", QMessageBox.StandardButton.Ok ) self.close() self.data_path = self.data_path or os.path.join(os.path.dirname(__file__), "../../../data") self.setWindowTitle("自动拼版系统") self.setGeometry(100, 100, 1200, 800) # 声明所有实例变量 self.project_manager = None self.font_manager = None self.compositor = None self.status_bar = None self.current_project = None self.logo_path = None self.spot_color_path = None # 布局和控件变量 self.left_layout = None self.btn_upload = None self.btn_add_text = None self.btn_add_qr = None self.template_canvas = None self.props_tabs = None self.text_props_panel = None self.qr_props_panel = None self.logo_props_panel = None self.right_layout = None self.btn_import_data = None self.btn_save_config = None self.data_mapper = None self.field_mapping_widget = None self.history_combo = None self.btn_history = None self.btn_generate = None self.btn_rerun = None # 初始化核心组件 self.init_components() # 创建项目管理器 self.project_manager = ProjectManager(self.data_path) # 创建字体管理器 self.font_manager = FontManager(self.data_path) # 创建合成引擎 self.compositor = FileCompositor(self.data_path, self.font_manager) # 设置状态栏 self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage("就绪") # 当前项目 self.current_project = None self.logo_path = None self.spot_color_path = None # 加载样式 self.apply_styles() def init_components(self): """初始化主界面组件""" self.logger.info("开始初始化组件") # 逐步初始化各个组件,添加日志 self.logger.info("创建中央部件...") self.central_widget = QWidget() self.setCentralWidget(self.central_widget) self.logger.info("创建布局...") self.layout = QVBoxLayout(self.central_widget) # 逐步添加其他组件,每一步都添加日志 # 例如先注释掉停靠窗口的创建 # self.logger.info("创建左侧停靠窗口...") # self.create_left_dock() # 只添加一个简单的标签用于测试 test_label = QLabel("应用程序启动成功,基本UI已加载") self.layout.addWidget(test_label) self.logger.info("基本组件初始化完成") # def create_left_dock(self): # # 暂时注释掉停靠窗口创建 # pass # 创建菜单栏 self.create_menus() # 创建工具栏 self.create_toolbar() # 创建主中心区域 central_widget = QWidget() self.setCentralWidget(central_widget) main_layout = QVBoxLayout(central_widget) # 左侧模板编辑区(占40%) left_dock = QDockWidget("模板编辑区", self) left_dock.setFeatures(QDockWidget.DockWidgetFeature.DockWidgetMovable | QDockWidget.DockWidgetFeature.DockWidgetFloatable) left_widget = QWidget() self.left_layout = QVBoxLayout(left_widget) # 模板操作按钮 btn_layout = QHBoxLayout() self.btn_upload = QPushButton("上传模板") self.btn_upload.clicked.connect(self.upload_template) self.btn_add_text = QPushButton("添加文本框") self.btn_add_text.clicked.connect(self.add_text_region) self.btn_add_qr = QPushButton("添加二维码区") self.btn_add_qr.clicked.connect(self.add_qr_region) btn_layout.addWidget(self.btn_upload) btn_layout.addWidget(self.btn_add_text) btn_layout.addWidget(self.btn_add_qr) self.left_layout.addLayout(btn_layout) # 模板编辑画布 self.template_canvas = TemplateCanvas(data_path=self.data_path) self.template_canvas.setAlignment(Qt.AlignmentFlag.AlignCenter) self.template_canvas.setStyleSheet("background-color: #f0f0f0; border: 1px solid #ccc;") self.left_layout.addWidget(self.template_canvas) # 属性面板(标签页) self.props_tabs = QTabWidget() self.text_props_panel = TextPropertiesPanel() self.qr_props_panel = QRPropertiesPanel() self.logo_props_panel = LogoPropertiesPanel() self.props_tabs.addTab(self.text_props_panel, "文本属性") self.props_tabs.addTab(self.qr_props_panel, "二维码属性") self.props_tabs.addTab(self.logo_props_panel, "Logo属性") # 连接信号 if hasattr(self.text_props_panel, 'propertyChanged'): self.text_props_panel.propertyChanged.connect(self.handle_property_change) if hasattr(self.qr_props_panel, 'propertyChanged'): self.qr_props_panel.propertyChanged.connect(self.handle_property_change) if hasattr(self.logo_props_panel, 'propertyChanged'): self.logo_props_panel.propertyChanged.connect(self.handle_property_change) self.left_layout.addWidget(self.props_tabs) left_dock.setWidget(left_widget) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, left_dock) # 右侧数据区域(占60%) right_dock = QDockWidget("数据映射区", self) right_widget = QWidget() self.right_layout = QVBoxLayout(right_widget) # 数据操作按钮 data_btn_layout = QHBoxLayout() self.btn_import_data = QPushButton("导入数据") self.btn_import_data.clicked.connect(self.import_data) self.btn_save_config = QPushButton("保存配置") self.btn_save_config.clicked.connect(self.save_config) data_btn_layout.addWidget(self.btn_import_data) data_btn_layout.addWidget(self.btn_save_config) self.right_layout.addLayout(data_btn_layout) # 数据映射表格 self.data_mapper = DataMapperWidget(self) self.right_layout.addWidget(self.data_mapper, 1) # 字段映射区域 self.right_layout.addWidget(QLabel("字段映射配置:")) self.field_mapping_widget = QLabel("拖拽字段到模板区域进行映射") self.field_mapping_widget.setStyleSheet("min-height: 100px; background-color: #fff; border: 1px dashed #999;") self.right_layout.addWidget(self.field_mapping_widget) right_dock.setWidget(right_widget) self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, right_dock) # 底部操作区 bottom_widget = QWidget() bottom_layout = QHBoxLayout(bottom_widget) # 翻单历史选择 bottom_layout.addWidget(QLabel("翻单历史:")) self.history_combo = QComboBox() self.history_combo.setMinimumWidth(200) self.history_combo.currentIndexChanged.connect(self.on_history_selected) self.refresh_history_combo() # 历史管理按钮 self.btn_history = QPushButton("管理") self.btn_history.setToolTip("管理历史记录") self.btn_history.clicked.connect(self.manage_history) bottom_layout.addWidget(self.history_combo) bottom_layout.addWidget(self.btn_history) bottom_layout.addSpacing(20) # 合成按钮 self.btn_generate = QPushButton("开始合成") self.btn_generate.setStyleSheet( "background-color: #4CAF50; color: white; font-weight: bold; padding: 8px 16px;") self.btn_generate.clicked.connect(self.generate_output) bottom_layout.addWidget(self.btn_generate) # 翻单按钮 self.btn_rerun = QPushButton("执行翻单") self.btn_rerun.setStyleSheet("background-color: #2196F3; color: white; font-weight: bold; padding: 8px 16px;") self.btn_rerun.clicked.connect(self.rerun_project) self.btn_rerun.setEnabled(False) bottom_layout.addWidget(self.btn_rerun) main_layout.addWidget(bottom_widget) def create_menus(self): """创建菜单栏""" menubar = self.menuBar() # 文件菜单 file_menu = menubar.addMenu('文件') # 使用 QAction 创建菜单项 new_action = QAction('新建项目', self) open_action = QAction('打开项目', self) save_action = QAction('保存项目', self) exit_action = QAction('退出', self) exit_action.triggered.connect(self.close) save_project_action = QAction('保存项目', self) save_project_action.triggered.connect(self.save_project) file_menu.addAction(save_project_action) open_project_action = QAction('打开项目', self) open_project_action.triggered.connect(self.open_project) file_menu.addAction(open_project_action) file_menu.addAction(new_action) file_menu.addAction(open_action) file_menu.addAction(save_action) file_menu.addSeparator() file_menu.addAction(exit_action) # 编辑菜单 edit_menu = menubar.addMenu('编辑') edit_menu.addAction('撤销') edit_menu.addAction('重做') edit_menu.addSeparator() font_action = QAction('字体管理', self) font_action.triggered.connect(self.open_font_manager) edit_menu.addAction(font_action) edit_menu.addAction('专色设置') # 视图菜单 view_menu = menubar.addMenu('视图') view_menu.addAction('放大') view_menu.addAction('缩小') view_menu.addAction('实际大小') # 帮助菜单 help_menu = menubar.addMenu('帮助') help_menu.addAction('用户手册') about_action = QAction('关于', self) about_action.triggered.connect(self.show_about) help_menu.addAction(about_action) def create_toolbar(self): """创建工具栏""" toolbar = QToolBar("主工具栏") self.addToolBar(toolbar) # 添加工具按钮 toolbar.addAction("打开模板", self.upload_template) toolbar.addAction("导入数据", self.import_data) toolbar.addSeparator() toolbar.addAction("添加文本", self.add_text_region) toolbar.addAction("添加二维码", self.add_qr_region) toolbar.addSeparator() toolbar.addAction("开始合成", self.generate_output) def apply_styles(self): """应用基本样式""" self.setStyleSheet(""" QMainWindow { background-color: #f5f5f5; } QPushButton { padding: 5px 10px; border: 1px solid #ccc; border-radius: 4px; } QPushButton:hover { background-color: #e9e9e9; } QDockWidget { background-color: #f0f0f0; border: 1px solid #ddd; titlebar-close-icon: url(resources/icons/close.png); titlebar-normal-icon: url(resources/icons/restore.png); } QDockWidget::title { background: #e0e0e0; padding: 4px; text-align: center; font-weight: bold; } QTabWidget::pane { border: 1px solid #ddd; top: 1px; background: white; } QTabBar::tab { background: #e0e0e0; border: 1px solid #ccc; padding: 6px 12px; border-top-left-radius: 4px; border-top-right-radius: 4px; } QTabBar::tab:selected { background: white; border-bottom-color: white; } """) # ===== 功能槽函数 ===== def upload_template(self): """上传模板图片""" file_path, _ = QFileDialog.getOpenFileName( self, "选择模板图片", self.data_path, "图像文件 (*.png *.jpg *.jpeg *.bmp);;PDF文件 (*.pdf)" ) if file_path: # 加载模板到画布 if self.template_canvas.load_template(file_path): self.status_bar.showMessage(f"已加载模板: {os.path.basename(file_path)}") # 更新区域信息 self.update_regions() def import_data(self): """导入数据文件""" file_path, _ = QFileDialog.getOpenFileName( self, "选择数据文件", self.data_path, "CSV文件 (*.csv);;Excel文件 (*.xlsx *.xls)" ) if file_path: self.status_bar.showMessage(f"已导入数据: {file_path}") # 解析并显示数据 self.data_mapper.import_data(file_path) def add_text_region(self): """添加文本区域""" self.template_canvas.set_mode(TemplateCanvas.MODE_TEXT) self.status_bar.showMessage("请在模板上框选文本区域") def add_qr_region(self): """添加二维码区域""" self.template_canvas.set_mode(TemplateCanvas.MODE_QR) self.status_bar.showMessage("请在模板上框选二维码区域") def save_config(self): """保存当前配置到项目文件""" if not self.template_canvas or not self.template_canvas.template_path: self.status_bar.showMessage("请先加载模板") return # 获取所有区域数据 regions_data = self.template_canvas.get_regions() # 获取映射关系 mapping = self.data_mapper.get_mapping() # 创建项目数据 project_data = { 'template_path': self.template_canvas.template_path, 'regions': regions_data, 'mapping': mapping } # 保存到文件 project_name = os.path.basename(self.template_canvas.template_path).split('.')[0] self.status_bar.showMessage(f"配置已保存: {project_name}") # 实际保存到文件 config_path = self.project_manager.save_project(project_data, project_name) if config_path: QMessageBox.information(self, "保存成功", f"项目已保存:\n{config_path}") self.refresh_history_combo() def generate_output(self): """开始合成""" self.status_bar.showMessage("合成中...") # 检查必要组件 if not self.template_canvas or not self.template_canvas.template_path: self.status_bar.showMessage("请先加载模板") QMessageBox.warning(self, "错误", "请先加载模板") return if not self.data_mapper.data_frame: self.status_bar.showMessage("请先导入数据") QMessageBox.warning(self, "错误", "请先导入数据") return # 获取区域和映射 regions = self.template_canvas.get_regions() mapping = self.data_mapper.get_mapping() # 生成输出文件名 timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") output_dir = os.path.join(self.data_path, "outputs") os.makedirs(output_dir, exist_ok=True) output_path = os.path.join(output_dir, f"output_{timestamp}.pdf") # 执行合成 success, logs = self.compositor.composite( template_path=self.template_canvas.template_path, regions=regions, mapping=mapping, data_source=self.data_mapper.data_frame, output_path=output_path, logo_path=self.logo_path if hasattr(self, 'logo_path') else "", spot_color_path=self.spot_color_path if hasattr(self, 'spot_color_path') else "" ) # 显示结果 if success: self.status_bar.showMessage(f"合成完成! 输出文件: {output_path}") # 显示预览对话框 preview_dialog = PreviewDialog(output_path, self) preview_dialog.exec() else: # 显示错误日志 error_msg = "\n".join(logs[-5:]) if logs else "知错误" QMessageBox.critical(self, "合成错误", f"合成过程中发生错误:\n{error_msg}") def preview_current(self): """预览当前配置""" if not self.template_canvas or not self.template_canvas.template_path: QMessageBox.warning(self, "预览", "请先加载模板") return if not self.data_mapper.data_frame or len(self.data_mapper.data_frame) == 0: QMessageBox.warning(self, "预览", "请先导入数据") return # 获取第一行数据 data_row = self.data_mapper.data_frame.iloc[0].to_dict() # 获取区域和映射 regions = self.template_canvas.get_regions() mapping = self.data_mapper.get_mapping() # 创建临时预览文件 preview_path = os.path.join(self.compositor.temp_dir, "preview.png") # 执行合成 if hasattr(self.compositor, 'composite_single'): success, logs = self.compositor.composite_single( template_path=self.template_canvas.template_path, regions=regions, mapping=mapping, data_row=data_row, output_path=preview_path, logo_path=self.logo_path if hasattr(self, 'logo_path') else "", spot_color_path=self.spot_color_path if hasattr(self, 'spot_color_path') else "" ) else: QMessageBox.warning(self, "预览错误", "composite_single方法实现") return if success: # 显示预览对话框 preview_dialog = PreviewDialog(preview_path, self) preview_dialog.exec() else: error_msg = "\n".join(logs) if logs else "知错误" QMessageBox.critical(self, "预览错误", f"预览生成失败:\n{error_msg}") def open_font_manager(self): """打开字体管理器""" self.status_bar.showMessage("打开字体管理器") QMessageBox.information(self, "字体管理", "字体管理功能将在后续版本中实现") def update_regions(self): """更新模板区域信息""" if not self.template_canvas: return # 获取所有区域 regions = [region.get_name() for region in self.template_canvas.regions] # 更新数据映射模块 self.data_mapper.update_regions(regions) def update_property_panel(self, region): """更新属性面板显示""" if isinstance(region, TextRegionItem): self.props_tabs.setCurrentIndex(0) self.text_props_panel.set_region(region) elif isinstance(region, QRRegionItem): self.props_tabs.setCurrentIndex(1) self.qr_props_panel.set_region(region) elif isinstance(region, LogoRegionItem): self.props_tabs.setCurrentIndex(2) self.logo_props_panel.set_region(region) def handle_property_change(self, key, value): """处理属性变化""" self.template_canvas.set_region_property(key, value) def refresh_history_combo(self): """刷新历史记录下拉框""" self.history_combo.clear() self.history_combo.addItem("选择历史项目...", None) history = self.project_manager.get_history() for item in history: self.history_combo.addItem(item['name'], item['path']) def on_history_selected(self, index): """历史项目选择事件""" if index <= 0: self.current_project = None self.btn_rerun.setEnabled(False) return project_path = self.history_combo.itemData(index) if project_path: self.current_project = self.project_manager.load_project(project_path) self.btn_rerun.setEnabled(True) def manage_history(self): """打开历史记录管理对话框""" dialog = HistoryDialog(self.project_manager, self) if dialog.exec() == QDialog.DialogCode.Accepted: self.refresh_history_combo() def save_project(self): """保存当前项目配置""" if not self.template_canvas or not self.template_canvas.template_path: QMessageBox.warning(self, "保存项目", "请先加载模板") return if not self.data_mapper.data_frame: QMessageBox.warning(self, "保存项目", "请先导入数据") return # 获取项目数据 project_data = { 'template_path': self.template_canvas.template_path, 'regions': self.template_canvas.get_regions(), 'mapping': self.data_mapper.get_mapping(), 'data_source': os.path.basename(self.data_mapper.data_path) if hasattr(self.data_mapper, 'data_path') else "", 'logo_path': self.logo_path if hasattr(self, 'logo_path') else "", 'spot_color_path': self.spot_color_path if hasattr(self, 'spot_color_path') else "", 'timestamp': datetime.datetime.now().isoformat(), 'description': "" } # 输入项目名称 name, ok = QInputDialog.getText( self, "保存项目", "输入项目名称:", text=f"项目_{datetime.datetime.now().strftime('%Y%m%d')}" ) if ok and name: # 保存项目 config_path = self.project_manager.save_project(project_data, name) if config_path: QMessageBox.information(self, "保存成功", f"项目已保存:\n{config_path}") self.refresh_history_combo() def open_project(self): """打开项目""" # 使用历史记录对话框选择项目 dialog = HistoryDialog(self.project_manager, self) if dialog.exec() == QDialog.DialogCode.Accepted: selected_project = dialog.get_selected_project() if selected_project: self.load_project(selected_project['path']) def load_project(self, project_dir): """加载项目到界面""" project_data = self.project_manager.load_project(project_dir) if not project_data: QMessageBox.warning(self, "加载项目", "项目加载失败") return # 加载模板 if self.template_canvas.load_template(project_data['template_path']): self.status_bar.showMessage(f"已加载模板: {os.path.basename(project_data['template_path'])}") # 清除现有区域 self.template_canvas.clear_regions() # 添加区域 for region_data in project_data['regions']: self._create_region_from_data(region_data) # 更新区域显示 self.update_regions() # 加载Logo和专色路径 if 'logo_path' in project_data and os.path.exists(project_data['logo_path']): self.logo_path = project_data['logo_path'] if 'spot_color_path' in project_data and os.path.exists(project_data['spot_color_path']): self.spot_color_path = project_data['spot_color_path'] # 加载映射关系 self.data_mapper.mapping = project_data['mapping'] self.data_mapper.update_mapping_list() # 提示加载数据源 data_source = project_data.get('data_source', '') if data_source: data_path = self._get_data_source_path(project_data) if data_path: self.data_mapper.import_data(data_path) # 设置当前项目 self.current_project = project_data self.btn_rerun.setEnabled(True) # 更新历史记录下拉框 self.refresh_history_combo() # 选中当前项目 for i in range(self.history_combo.count()): if self.history_combo.itemData(i) == project_dir: self.history_combo.setCurrentIndex(i) break def _create_region_from_data(self, region_data): """根据区域数据创建区域项""" rect = QRectF( region_data['rect']['x'], region_data['rect']['y'], region_data['rect']['width'], region_data['rect']['height'] ) region = None if region_data['type'] == 'text': region = TextRegionItem(rect) region.set_name(region_data.get('name', '文本区域')) if 'font' in region_data: font = QFont() font.fromString(region_data['font']) region.set_font(font) if 'align' in region_data: region.set_align(region_data['align']) if 'color' in region_data: region.set_color(QColor(region_data['color'])) elif region_data['type'] == 'qr': region = QRRegionItem(rect) region.set_name(region_data.get('name', '二维码区域')) if 'code_type' in region_data: region.code_type = region_data['code_type'] elif region_data['type'] == 'logo': # 创建空区域,实际Logo在合成时加载 region = LogoRegionItem(rect, QPixmap()) region.set_name(region_data.get('name', 'Logo区域')) if 'opacity' in region_data: region.set_opacity(region_data['opacity']) # 添加到场景 if region: self.template_canvas.scene.addItem(region) self.template_canvas.regions.append(region) def rerun_project(self): """执行翻单操作""" if not self.current_project: QMessageBox.warning(self, "翻单", "请先选择项目") return # 确认数据源 data_source_path = self._get_data_source_path(self.current_project) if not data_source_path: return # 生成输出文件名 timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") output_dir = os.path.join(self.data_path, "outputs") os.makedirs(output_dir, exist_ok=True) output_path = os.path.join(output_dir, f"翻单_{self.current_project.get('name', 'project')}_{timestamp}.pdf") # 执行合成 success, logs = self.compositor.composite( template_path=self.current_project['template_path'], regions=self.current_project['regions'], mapping=self.current_project['mapping'], data_source=data_source_path, output_path=output_path, logo_path=self.current_project.get('logo_path', ''), spot_color_path=self.current_project.get('spot_color_path', '') ) # 显示结果 if success: self.status_bar.showMessage(f"翻单完成! 输出文件: {output_path}") # 显示预览对话框 preview_dialog = PreviewDialog(output_path, self) preview_dialog.exec() else: # 显示错误日志 error_msg = "\n".join(logs[-5:]) if logs else "知错误" QMessageBox.critical(self, "翻单错误", f"翻单过程中发生错误:\n{error_msg}") def _get_data_source_path(self, project): """获取数据源文件路径""" # 1. 检查项目是否指定了数据源 data_source_name = project.get('data_source', '') if data_source_name: # 尝试在项目目录中查找 project_dir = os.path.dirname(project['template_path']) project_data_path = os.path.join(project_dir, data_source_name) if os.path.exists(project_data_path): return project_data_path # 尝试在数据目录中查找 data_dir = os.path.join(self.data_path, "data") data_path = os.path.join(data_dir, data_source_name) if os.path.exists(data_path): return data_path # 2. 提示用户选择数据文件 file_path, _ = QFileDialog.getOpenFileName( self, "选择数据文件", self.data_path, "CSV文件 (*.csv);;Excel文件 (*.xlsx *.xls)" ) return file_path if file_path else None def show_about(self): """显示关于对话框""" about_text = ( "<h2>自动拼版系统</h2>" "<p>版本: 1.0.0</p>" "<p>基于 PyQt6 构建</p>" "<p>© 2023 自动拼版系统团队</p>" ) QMessageBox.about(self, "关于", about_text) # 测试运行 if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec()) # 检查内存模块 def log_memory(): try: snapshot = tracemalloc.take_snapshot() top_stats = snapshot.statistics('lineno') logger.info("内存使用统计:") for stat in top_stats[:10]: logger.info(stat) except Exception as e: logger.error(f"内存监控失败: {str(e)}") import atexit atexit.register(log_memory) 请帮我分析该代码块,并修改调整不合理的地方,以及排查出刚才分析的AttributeError: ‘NoneType’ object has no attribute ‘setEnabled’问题,并输出完整的修改后的main_window.py的代码
最新发布
07-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值