QAction ___ Recent Files Menu

本文介绍如何在Qt应用程序中实现Recent Files菜单功能,包括设置最大文件数量、初始化操作、更新菜单显示及打开最近文件等功能。

 

1.

   定义recent files 最大数量,即多少个recent files action;    

         如:#define MaxRecentFiles 15

   定义存放recent files action的QAction;

         如: QAction recentFileActs[ MaxRecentFiles ];

 

2.

  初始化recent files action;

   pseudo code:

      for (int i = 0; i < MaxRecentFiles; ++i)

    {
        recentFileActs[i] = new QAction(this);
        recentFileActs[i]->setVisible(false);
        connect(recentFileActs[i], SIGNAL(triggered()),
                this, SLOT(openRecentFile()));
    }

 

3.create menu

   fileMenu = menuBar()->addMenu(tr("&File"));
   QMenu *recentFiles = new QMenu(tr("Recent Files"));
    for (int i = 0; i < MaxRecentFiles; ++i)
        recentFiles ->addAction(recentFileActs[i]);

    fileMenu->addMenu(recentFiles);

4.updateRecentFileActions()

void MainWindow::updateRecentFileActions()
{
    QSettings settings;
    QStringList files = settings.value("recentFileList").toStringList();

    int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);

    for (int i = 0; i < numRecentFiles; ++i) {
        //QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(fullFileName).fileName());

           QString text = files[i];  //文件的全路径名称
        recentFileActs[i]->setText(text);    // important
        recentFileActs[i]->setData(files[i]);  // important
        recentFileActs[i]->setVisible(true);  // important

    }
    for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
        recentFileActs[j]->setVisible(false);

    separatorAct->setVisible(numRecentFiles > 0);
}

 

5. openRecentFile() slots:

void MainWindow::openRecentFile()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
        loadFile(action->data().toString() );
}

 

6.

void MainWindow::loadFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, tr("Recent Files"),
                             tr("Cannot read file %1:/n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
        return;
    }

    QTextStream in(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    textEdit->setPlainText(in.readAll());
    QApplication::restoreOverrideCursor();

    setCurrentFile(fileName);
    statusBar()->showMessage(tr("File loaded"), 2000);
}

 

7.

void MainWindow::setCurrentFile(const QString &fileName)
{
    curFile = fileName;
    setWindowFilePath(curFile);

    QSettings settings;
    QStringList files = settings.value("recentFileList").toStringList();
    files.removeAll(fileName);
    files.prepend(fileName);
    while (files.size() > MaxRecentFiles)
        files.removeLast();

    settings.setValue("recentFileList", files);

    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
        MainWindow *mainWin = qobject_cast<MainWindow *>(widget);
        if (mainWin)
            mainWin->updateRecentFileActions();
    }
}

 

 

/**************************************************************************** ** ** This file is part of the LibreCAD project, a 2D CAD program ** ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl) ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved. ** ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file gpl-2.0.txt included in the ** packaging of this file. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** This copyright notice MUST APPEAR in all copies of the script! ** **********************************************************************/ #ifndef QC_APPLICATIONWINDOW_H #define QC_APPLICATIONWINDOW_H #undef QT_NO_WORKSPACE #include <qworkspace.h> #include "qc_mdiwindow.h" #include "qg_mainwindowinterface.h" #ifdef RS_SCRIPTING #include "qs_scripter.h" #include <qsproject.h> #endif class QG_LibraryWidget; class QG_CadToolBar; class QC_DialogFactory; class QG_LayerWidget; class QG_BlockWidget; class QG_CommandWidget; class QG_CoordinateWidget; class QG_MouseWidget; class QG_SelectionWidget; class QG_RecentFiles; class QG_PenToolBar; class QHelpEngine; class QC_PluginInterface; /** * Main application window. Hold together document, view and controls. * * @author Andrew Mustun */ class QC_ApplicationWindow: public QMainWindow, public QG_MainWindowInterface { Q_OBJECT public: QC_ApplicationWindow(); ~QC_ApplicationWindow(); void initActions(); void initMenuBar(); void initToolBar(); void initStatusBar(); void initSettings(); void restoreDocks(); void storeSettings(); void updateRecentFilesMenu(); void initMDI(); void initView(); bool queryExit(bool force); /** Catch hotkey for giving focus to command line. */ virtual void keyPressEvent(QKeyEvent* e); virtual void keyReleaseEvent(QKeyEvent* e); public slots: virtual void show(); void finishSplashScreen(); void slotFocus(); void slotBack(); void slotKillAllActions(); //void slotNext(); void slotEnter(); void slotFocusCommandLine(); void slotError(const QString& msg); void slotWindowActivated(QWidget* w); void slotWindowsMenuAboutToShow(); void slotWindowsMenuActivated(int); void slotTileHorizontal(); void slotTileVertical(); void slotPenChanged(RS_Pen p); /** generates a new document for a graphic. */ QC_MDIWindow* slotFileNew(RS_Document* doc=NULL); /** opens a document */ void slotFileOpen(); /** * opens a recent file document * @param id File Menu id of the file */ void slotFileOpenRecent(int id); /** * opens the given file. */ void slotFileOpen(const QString& fileName, RS2::FormatType type); /** saves a document */ void slotFileSave(); /** saves a document under a different filename*/ void slotFileSaveAs(); /** auto-save document */ void slotFileAutoSave(); /** exports the document as bitmap */ void slotFileExport(); bool slotFileExport(const QString& name, const QString& format, QSize size, bool black, bool bw=false); /** closes the current file */ void slotFileClose(); /** closing the current file */ void slotFileClosing(); /** prints the current file */ void slotFilePrint(); /** shows print preview of the current file */ void slotFilePrintPreview(bool on); /** exits the application */ void slotFileQuit(); /** toggle the grid */ void slotViewGrid(bool toggle); /** toggle the draft mode */ void slotViewDraft(bool toggle); /** toggle the statusbar */ void slotViewStatusBar(bool toggle); // void slotBlocksEdit(); void slotOptionsGeneral(); void slotScriptOpenIDE(); void slotScriptRun(); void slotRunStartScript(); void slotRunScript(); void slotRunScript(const QString& name); void slotInsertBlock(); void slotInsertBlock(const QString& name); /** shows an about dlg*/ void slotHelpAbout(); void slotHelpManual(); /** dumps entities to file */ void slotTestDumpEntities(RS_EntityContainer* d=NULL); /** dumps undo info to stdout */ void slotTestDumpUndo(); /** updates all inserts */ void slotTestUpdateInserts(); /** draws some random lines */ void slotTestDrawFreehand(); /** inserts a test block */ void slotTestInsertBlock(); /** inserts a test ellipse */ void slotTestInsertEllipse(); /** inserts a test text */ void slotTestInsertText(); /** inserts a test image */ void slotTestInsertImage(); /** unicode table */ void slotTestUnicode(); /** math experimental */ void slotTestMath01(); /** resizes window to 640x480 for screen shots */ void slotTestResize640(); /** resizes window to 640x480 for screen shots */ void slotTestResize800(); /** resizes window to 640x480 for screen shots */ void slotTestResize1024(); signals: void gridChanged(bool on); void draftChanged(bool on); void printPreviewChanged(bool on); void windowsChanged(bool windowsLeft); public: /** * @return Pointer to application window. */ static QC_ApplicationWindow* getAppWindow() { return appWindow; } /** * @return Pointer to workspace. */ QWorkspace* getWorkspace() { return workspace; } /** * @return Pointer to the currently active MDI Window or NULL if no * MDI Window is active. */ QC_MDIWindow* getMDIWindow() { if (workspace!=NULL) { return (QC_MDIWindow*)workspace->activeWindow(); } else { return NULL; } } /** * Implementation from RS_MainWindowInterface (and QS_ScripterHostInterface). * * @return Pointer to the graphic view of the currently active document * window or NULL if no window is available. */ virtual RS_GraphicView* getGraphicView() { QC_MDIWindow* m = getMDIWindow(); if (m!=NULL) { return m->getGraphicView(); } return NULL; } /** * Implementation from RS_MainWindowInterface (and QS_ScripterHostInterface). * * @return Pointer to the graphic document of the currently active document * window or NULL if no window is available. */ virtual RS_Document* getDocument() { QC_MDIWindow* m = getMDIWindow(); if (m!=NULL) { return m->getDocument(); } return NULL; } /** * Creates a new document. Implementation from RS_MainWindowInterface. */ virtual void createNewDocument( const QString& fileName = QString::null, RS_Document* doc=NULL) { slotFileNew(doc); if (fileName!=QString::null && getDocument()!=NULL) { getDocument()->setFilename(fileName); } } /** * Implementation from QG_MainWindowInterface. * * @return Pointer to this. */ virtual QMainWindow* getMainWindow() { return this; } /** * @return Pointer to action handler. Implementation from QG_MainWindowInterface. */ virtual QG_ActionHandler* getActionHandler() { return actionHandler; } //virtual QToolBar* createToolBar(const QString& name); //virtual void addToolBarButton(QToolBar* tb); /** * @return Pointer to the qsa object. */ #ifdef RS_SCRIPTING QSProject* getQSAProject() { if (scripter!=NULL) { return scripter->getQSAProject(); } else { return NULL; } } #endif void redrawAll(); void updateGrids(); /** * Implementation from QG_MainWindowInterface. */ virtual void setFocus2() { setFocus(); } /** Block list widget */ QG_BlockWidget* getBlockWidget(void) { return blockWidget; } protected: void closeEvent(QCloseEvent*); virtual void mouseReleaseEvent(QMouseEvent* e); private: /** Pointer to the application window (this). */ static QC_ApplicationWindow* appWindow; QTimer *autosaveTimer; /** Workspace for MDI */ QWorkspace* workspace; /** Dialog factory */ QC_DialogFactory* dialogFactory; /** Layer list widget */ QG_LayerWidget* layerWidget; /** Block list widget */ QG_BlockWidget* blockWidget; /** Library browser widget */ QG_LibraryWidget* libraryWidget; /** Layer list dock widget */ QDockWidget* layerDockWindow; /** Block list dock widget */ QDockWidget* blockDockWindow; /** Library list dock widget */ QDockWidget* libraryDockWindow; /** Command line */ QG_CommandWidget* commandWidget; QDockWidget* commandDockWindow; /** Coordinate widget */ QG_CoordinateWidget* coordinateWidget; /** Mouse widget */ QG_MouseWidget* mouseWidget; /** Selection Status */ QG_SelectionWidget* selectionWidget; /** Option widget for individual tool options */ QToolBar* optionWidget; /** Recent files list */ QG_RecentFiles* recentFiles; /** Action handler. */ QG_ActionHandler* actionHandler; #ifdef RS_SCRIPTING /** Scripting interface. */ QS_Scripter* scripter; #endif QMenu* fileMenu; QMenu* windowsMenu; QMenu* scriptMenu; QMenu* helpMenu; QMenu* testMenu; /** the main toolbars */ QToolBar* fileToolBar; QToolBar* editToolBar; QToolBar* zoomToolBar; // Toolbar for selecting the current pen QG_PenToolBar* penToolBar; // Toolbar for CAD tools QG_CadToolBar* cadToolBar; QHelpEngine* helpEngine; QDockWidget *helpWindow; QAction* scriptOpenIDE; QAction* scriptRun; QAction* helpAboutApp; QAction* helpManual; QAction *testDumpEntities; QAction *testDumpUndo; QAction *testUpdateInserts; QAction *testDrawFreehand; QAction *testInsertBlock; QAction *testInsertText; QAction *testInsertImage; QAction *testUnicode; QAction *testInsertEllipse; QAction *testMath01; QAction *testResize640; QAction *testResize800; QAction *testResize1024; //Plugin support private: void loadPlugins(); QMenu *findMenu(const QString &searchMenu, const QObjectList thisMenuList, const QString& currentEntry); QList<QC_PluginInterface*> loadedPlugins; public slots: void execPlug(); }; #endif 给出完整的代码注释
07-04
以上是main_window.py的完整代码: #主窗口 - PyQt6 版本 import os import sys import logging import faulthandler # 捕获崩溃信息 import ctypes # Windows API 调用支持 from typing import Optional from PyQt6.QtCore import Qt, pyqtSignal, PYQT_VERSION_STR from PyQt6.QtGui import QAction from PyQt6.QtWidgets import QDockWidget, QWidget, QVBoxLayout, QLabel, QMainWindow, QStatusBar, QPushButton, \ QHBoxLayout, QTabWidget, QComboBox, QToolBar, QApplication, QMessageBox, QFileDialog from ui.template_editor import TemplateCanvas # 启用故障处理程序,帮助调试崩溃问题 faulthandler.enable() # 设置日志系统,记录运行时信息 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()}") logger.info(f"PyQt6 版本: {'未导入' if 'PYQT_VERSION_STR' not in globals() else PYQT_VERSION_STR}") # 检查是否运行在虚拟环境中 if not hasattr(sys, 'real_prefix') and not hasattr(sys, 'base_prefix'): logging.warning("警告: 未在虚拟环境中运行,建议使用虚拟环境") # 设置调试标志和环境变量 os.environ['QT_DEBUG_PLUGINS'] = '1' os.environ['QTWEBENGINE_CHROMIUM_FLAGS'] = '--disable-gpu --no-sandbox' # Windows 错误报告设置 if sys.platform == 'win32': ctypes.windll.kernel32.SetErrorMode.argtypes = [ctypes.c_uint] ctypes.windll.kernel32.SetErrorMode(ctypes.c_uint(0x0001 | 0x0002)) # 设置堆栈保护 os.environ['QT_FATAL_CRITICALS'] = '1' os.environ['QT_FATAL_WARNINGS'] = '1' 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): 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): """文本属性面板 UI 实现""" def setup_ui(self): layout = QVBoxLayout(self) layout.addWidget(QLabel("文本属性面板")) self.setLayout(layout) def update_ui_from_region(self): if self.region: pass class QRPropertiesPanel(BasePropertiesPanel): """二维码属性面板 UI 实现""" def setup_ui(self): layout = QVBoxLayout(self) layout.addWidget(QLabel("二维码属性面板")) self.setLayout(layout) class LogoPropertiesPanel(BasePropertiesPanel): """Logo属性面板 UI 实现""" def setup_ui(self): layout = QVBoxLayout(self) layout.addWidget(QLabel("Logo属性面板")) self.setLayout(layout) class MainWindow(QMainWindow): def __init__(self, data_path: Optional[str] = None): super().__init__() self.logger = logging.getLogger(__name__) self.logger.info("主窗口初始化开始") self.setWindowTitle("自动打印系统") self.resize(800, 600) self.data_path = data_path or os.path.join(os.path.dirname(__file__), "../../../data") # 初始化所有实例属性为 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.project_manager = None self.font_manager = None self.compositor = None # 初始化控件 self.init_components() try: # 创建项目管理器 from src.auto_print_system.core.project_manager import ProjectManager self.project_manager = ProjectManager(self.data_path) # 创建字体管理器 from src.auto_print_system.core.font_manager import FontManager self.font_manager = FontManager(self.data_path) # 创建合成引擎 from src.auto_print_system.core.file_compositor import FileCompositor self.compositor = FileCompositor(self.data_path, self.font_manager) except ImportError as e: self.logger.error(f"初始化核心组件失败: {str(e)}", exc_info=True) QMessageBox.critical(self, "错误", f"初始化核心组件失败:\n{str(e)}") # 设置状态栏 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) -> None: """初始化所有界面组件""" self.logger.info("开始初始化组件") central_widget = QWidget() self.setCentralWidget(central_widget) main_layout = QVBoxLayout(central_widget) # 左侧模板编辑区 left_dock = QDockWidget("模板编辑区", self) left_widget = QWidget() self.left_layout = QVBoxLayout(left_widget) btn_layout = QHBoxLayout() self.btn_upload = QPushButton("上传模板") self.btn_add_text = QPushButton("添加文本框") self.btn_add_qr = QPushButton("添加二维码区") self.btn_upload.clicked.connect(self.upload_template) self.btn_add_text.clicked.connect(self.add_text_region) 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) try: from src.auto_print_system.ui.template_editor import TemplateCanvas 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) except ImportError as e: self.logger.error(f"初始化模板画布失败: {str(e)}", exc_info=True) self.template_canvas = None # 属性面板 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属性") self.left_layout.addWidget(self.props_tabs) left_dock.setWidget(left_widget) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, left_dock) # 右侧数据映射区 right_dock = QDockWidget("数据映射区", self) right_widget = QWidget() self.right_layout = QVBoxLayout(right_widget) data_btn_layout = QHBoxLayout() self.btn_import_data = QPushButton("导入数据") self.btn_save_config = QPushButton("保存配置") self.btn_import_data.clicked.connect(self.import_data) 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) try: from src.auto_print_system.ui.data_mapper import DataMapperWidget self.data_mapper = DataMapperWidget(self) self.right_layout.addWidget(self.data_mapper, 1) except ImportError as e: self.logger.error(f"初始化数据映射器失败: {str(e)}", exc_info=True) 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) self.history_combo = QComboBox() self.btn_history = QPushButton("管理") self.btn_generate = QPushButton("开始合成") 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(QLabel("翻单历史:")) bottom_layout.addWidget(self.history_combo) bottom_layout.addWidget(self.btn_history) bottom_layout.addSpacing(20) bottom_layout.addWidget(self.btn_generate) bottom_layout.addWidget(self.btn_rerun) main_layout.addWidget(bottom_widget) # 其他功能初始化... self.create_menus() self.create_toolbar() # ===== 功能槽函数 ===== def rerun_project(self) -> None: """执行翻单操作""" if self.btn_rerun is not None: self.btn_rerun.setEnabled(False) # 防止多次点击 else: logging.error("btn_rerun 控件未正确初始化") return # ... 其他业务逻辑 ... def create_menus(self) -> None: """创建菜单栏""" menubar = self.menuBar() file_menu = menubar.addMenu('文件') new_action = QAction('新建项目', self) open_action = QAction('打开项目', self) save_action = QAction('保存项目', self) exit_action = QAction('退出', self) exit_action.triggered.connect(self.close) 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('重做') def create_toolbar(self) -> None: """创建工具栏""" 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) -> None: """应用基本样式表""" self.setStyleSheet(""" QMainWindow { background-color: #f5f5f5; } QPushButton { padding: 5px 10px; border: 1px solid #ccc; border-radius: 4px; } QPushButton:hover { background-color: #e9e9e9; } """) def upload_template(self) -> None: """上传模板文件""" self.logger.debug("上传模板操作被触发") file_dialog = QFileDialog(self) file_dialog.setNameFilter("模板文件 (*.pdf *.png *.jpg *.jpeg)") file_dialog.setWindowTitle("选择模板文件") if file_dialog.exec(): template_path = file_dialog.selectedFiles()[0] self.logger.info(f"选择了模板文件: {template_path}") try: if self.template_canvas: success = self.template_canvas.load_template(template_path) if success: self.status_bar.showMessage(f"模板加载成功: {os.path.basename(template_path)}") else: self.status_bar.showMessage("模板加载失败,请检查文件格式") self.logger.error(f"模板加载失败: {template_path}") else: self.logger.error("模板画布未初始化") self.status_bar.showMessage("模板画布未初始化,无法加载模板") except Exception as e: self.logger.error(f"模板加载失败: {str(e)}", exc_info=True) self.status_bar.showMessage("模板加载失败,请检查文件格式或权限") def add_text_region(self) -> None: """添加文本区域""" self.logger.debug("添加文本区域操作被触发") if self.template_canvas: try: self.template_canvas.set_mode(TemplateCanvas.MODE_TEXT) self.status_bar.showMessage("添加文本区域模式激活") except Exception as e: self.logger.error(f"设置文本区域模式失败: {str(e)}", exc_info=True) self.status_bar.showMessage("设置文本区域模式失败,请重试") else: self.logger.error("模板画布未初始化") self.status_bar.showMessage("模板画布未初始化,无法添加文本区域") def add_text_region(self) -> None: """添加文本区域""" self.logger.debug("添加文本区域操作被触发") if self.template_canvas: try: self.template_canvas.set_mode(TemplateCanvas.MODE_TEXT) self.status_bar.showMessage("添加文本区域模式激活") except Exception as e: self.logger.error(f"设置文本区域模式失败: {str(e)}", exc_info=True) self.status_bar.showMessage("设置文本区域模式失败,请重试") else: self.logger.error("模板画布未初始化") self.status_bar.showMessage("模板画布未初始化,无法添加文本区域") def import_data(self) -> None: """导入数据文件""" self.logger.debug("导入数据操作被触发") file_dialog = QFileDialog(self) file_dialog.setNameFilter("数据文件 (*.csv *.xlsx *.xls)") file_dialog.setWindowTitle("选择数据文件") if file_dialog.exec(): data_path = file_dialog.selectedFiles()[0] self.logger.info(f"选择了数据文件: {data_path}") try: if self.data_mapper: self.data_mapper.import_data() self.status_bar.showMessage(f"数据文件已导入: {os.path.basename(data_path)}") else: self.logger.error("数据映射器未初始化") self.status_bar.showMessage("数据映射器未初始化,无法导入数据文件") except Exception as e: self.logger.error(f"导入数据失败: {str(e)}", exc_info=True) self.status_bar.showMessage("导入数据失败,请检查文件格式或权限") def save_config(self) -> None: """保存配置文件""" self.logger.debug("保存配置操作被触发") try: if self.data_mapper: mapping_config = self.data_mapper.get_mapping() if mapping_config: # 假设配置文件保存到 JSON 文件 config_path = os.path.join(self.data_path, "config.json") with open(config_path, "w", encoding="utf-8") as config_file: import json json.dump(mapping_config, config_file, ensure_ascii=False, indent=4) self.logger.info(f"配置文件已保存至: {config_path}") self.status_bar.showMessage("配置文件保存成功") else: self.logger.warning("无映射配置可保存") self.status_bar.showMessage("无映射配置可保存") else: self.logger.error("数据映射器未初始化") self.status_bar.showMessage("数据映射器未初始化,无法保存配置") except Exception as e: self.logger.error(f"保存配置失败: {str(e)}", exc_info=True) self.status_bar.showMessage("保存配置失败,请检查文件权限") def generate_output(self) -> None: """生成输出文件""" self.logger.debug("开始合成操作被触发") if not self.current_project: self.logger.error("未选择项目,无法生成输出文件") self.status_bar.showMessage("未选择项目,无法生成输出文件") return try: # 检查是否有有效的模板和数据映射 if not self.template_canvas or not self.template_canvas.template_item: self.logger.error("无有效模板,无法生成输出文件") self.status_bar.showMessage("无有效模板,无法生成输出文件") return if not self.data_mapper or not self.data_mapper.data_frame: self.logger.error("无有效数据,无法生成输出文件") self.status_bar.showMessage("无有效数据,无法生成输出文件") return # 开始合成操作 self.status_bar.showMessage("正在生成输出文件...") self.logger.info("开始合成输出文件") output_path = os.path.join(self.data_path, "output.pdf") self.compositor.compose(output_path) self.status_bar.showMessage("输出文件生成成功") self.logger.info(f"输出文件已生成至: {output_path}") except Exception as e: self.logger.error(f"生成输出文件失败: {str(e)}", exc_info=True) self.status_bar.showMessage("生成输出文件失败,请检查设置") def rerun_project(self) -> None: """执行翻单操作""" self.logger.debug("执行翻单操作被触发") if self.btn_rerun is not None: self.btn_rerun.setEnabled(False) # 防止多次点击 else: self.logger.error("btn_rerun 控件未正确初始化") return if not self.current_project: self.logger.error("未选择项目,无法执行翻单") self.status_bar.showMessage("未选择项目,无法执行翻单") return try: # 检查是否有有效的模板和数据映射 if not self.template_canvas or not self.template_canvas.template_item: self.logger.error("无有效模板,无法执行翻单") self.status_bar.showMessage("无有效模板,无法执行翻单") return if not self.data_mapper or not self.data_mapper.data_frame: self.logger.error("无有效数据,无法执行翻单") self.status_bar.showMessage("无有效数据,无法执行翻单") return # 执行翻单操作 self.status_bar.showMessage("正在执行翻单...") self.logger.info("开始执行翻单") output_path = os.path.join(self.data_path, "rerun_output.pdf") self.compositor.compose(output_path) self.status_bar.showMessage("翻单执行成功") self.logger.info(f"翻单输出文件已生成至: {output_path}") # 恢复按钮状态 self.btn_rerun.setEnabled(True) except Exception as e: self.logger.error(f"翻单执行失败: {str(e)}", exc_info=True) self.status_bar.showMessage("翻单执行失败,请检查设置") # 恢复按钮状态 self.btn_rerun.setEnabled(True) # 测试运行 if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec()) 运行之后出现以下错误,请帮我进行修改Traceback (most recent call last): File "D:\PycharmProjects\Panelsystem\src\auto_print_system\ui\main_window.py", line 534, in <module> window = MainWindow() ^^^^^^^^^^^^ File "D:\PycharmProjects\Panelsystem\src\auto_print_system\ui\main_window.py", line 145, in __init__ self.init_components() File "D:\PycharmProjects\Panelsystem\src\auto_print_system\ui\main_window.py", line 195, in init_components self.btn_add_qr.clicked.connect(self.add_qr_region) ^^^^^^^^^^^^^^^^^^ AttributeError: 'MainWindow' object has no attribute 'add_qr_region'. Did you mean: 'add_text_region'?
07-15
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值