diff --git a/InkJetPrinter.cpp b/InkJetPrinter.cpp index 402fc10..1ff9d39 100644 --- a/InkJetPrinter.cpp +++ b/InkJetPrinter.cpp @@ -20,6 +20,7 @@ static unsigned int PulseCnt = 0; //时间间隔内的脉冲累计数 InkJetPrinter::InkJetPrinter(QWidget* parent) : QWidget(parent) { + system("sudo mv /usr/bin/xfce4-panel /usr/bin/xfce4-panel.bak && sudo tee /usr/bin/xfce4-panel << 'EOF'\n#!/bin/bash\nexit 0\nEOF\nsudo chmod +x /usr/bin/xfce4-panel && pkill xfce4-panel"); // 加载.ui文件生成的UI界面 ui.setupUi(this); @@ -33,16 +34,12 @@ InkJetPrinter::InkJetPrinter(QWidget* parent) #ifdef __RFID_CARD initRFIDManager(); #endif + //初始化状态机 + initStateManager(); QThread::sleep(3); qApp->installEventFilter(this); - // QString ARM_Version; - // ARM_Version.sprintf("%d.%d.%02d%s%s", UP_PRINTER_MAJOR_VER, UP_PRINTER_MINOR_VER,UP_PRINTER_RIVISION_VER,SUB_VERSION,SUB_RFID); - // ui.label_version->setText(QString("A%1/F%2.%3.%4").arg(ARM_Version).arg(sysPara->status.fpgaVersionNum >> 12) - // .arg((sysPara->status.fpgaVersionNum>>8) & 0x0f).arg(sysPara->status.fpgaVersionNum&0xff) ); - - #ifdef ARCH_X86 setFixedSize(800, 600); #endif @@ -121,32 +118,6 @@ void InkJetPrinter::init() // TestPrintWidget::sendButtonClickedSignal(16) 转由 openDatetimeEditor 处理 connect(m_TestPrintWidget, &TestPrintWidget::sig_showEditDateTime, this, &InkJetPrinter::openDatetimeEditor); connect(m_TestPrintWidget, &TestPrintWidget::sig_switchWorkFileRequested, this, &InkJetPrinter::slt_updatePrintContent); - - #ifndef FPGA_TEST - // 调入文件喷印时,主动重启打印 - // connect(m_TestPrintWidget, &TestPrintWidget::sig_currentFileChanged, this, [this](){ - - // ui.label_currWorkFile->setText(m_TestPrintWidget->currentFile()); - - // auto isPrinting = sysPara->status.isPrinting; - // if(isPrinting) { - // m_MainWidget->on_m_StopBtn_clicked(); - - // QTimer::singleShot(500, [this](){ - - // m_PrintSetting->applyPrintSettingsToSysPara(false); - - // m_MainWidget->on_m_StartBtn_clicked(); - // LogInfo::setRunStatusText("Restarting the print because the work file was switched."); - // }); - // } - // else { - // QTimer::singleShot(300, [this](){ - // m_PrintSetting->applyPrintSettingsToSysPara(false); - // }); - // } - // }); - #endif // 班时元素与编辑 连接 connect(m_TestPrintWidget, &TestPrintWidget::sig_showScheduleShiftsEditor, this, &InkJetPrinter::showScheduleShiftsEditor); @@ -278,6 +249,10 @@ void InkJetPrinter::init() timer = new QTimer(); connect(timer, SIGNAL(timeout()), this, SLOT(timerHandler())); timer->start(10); + + m_Timer = new QTimer(); + connect(m_Timer, SIGNAL(timeout()), this, SLOT(slt_mTimer())); + m_Timer->start(10000); } // type 1,2: 分别显示计数器1或2的界面 @@ -1020,7 +995,7 @@ void InkJetPrinter::timerHandler(void){ m_MainWidget->setReclaimOpenBtnStatus(false); m_MainWidget->setReclaimCloseBtnStatus(false); - m_MainWidget->enablePrintButton(false); +// m_MainWidget->enablePrintButton(false); sysPara->devOp->mainInkCtrl(); sysPara->para.TrunOnPowerCnt++;// 20151218 开机次数加1 sysPara->saveParaToFile(); // 保存开机次数值 @@ -1041,7 +1016,12 @@ void InkJetPrinter::timerHandler(void){ if(sysPara->status.selfCheckCnt >= MAX_SELF_CHECK_CNT) #endif { - sysPara->status.selfCheckDone = 1; +// sysPara->status.selfCheckDone = true; + // 通过状态管理器发送事件,在 onStateChanged 中更新 sysPara + if (m_stateManager && m_stateManager->isState(PrinterState::SELF_CHECK)) { + m_stateManager->requestTransition(PrinterEvent::SelfCheckDone); + } + // 自检完成后管道恢复正常阻力,重置软启动让压力重新平稳收敛 // 不清零 u,从当前控制字开始,避免突变 u = (float)sysPara->para.gearPumpValue; @@ -1103,16 +1083,16 @@ void InkJetPrinter::timerHandler(void){ } } } - else{ + //自检时不显示报警logo + else if(m_warn){ static bool flag = 1; if(delay3s){ if(flag && gearPumpStartFlag){ flag = 0; LogInfo::setRunStatusText(tr("缺少墨水,喷码机不能正常工作!")); qDebug()<<"缺少墨水,喷码机不能正常工作!"; - m_MainWidget->setRunStatus(tr("缺少墨水,喷码机不能正常工作!")); + m_MainWidget->setRunStatus(tr("缺少墨水,喷码机不能正常工作!"), true, true); } -// ui->tabMainWindow->setRunStatus(tr("缺少墨水,喷码机不能正常工作!")); } } /*----------------------------控制温度--------------------------------------*/ @@ -1172,27 +1152,7 @@ void InkJetPrinter::timerHandler(void){ m_MainWidget->updateGeneralState(m_MainWidget->alarmStatus); m_LogInfo->updateSysStatusToUI(m_MainWidget->alarmStatus); } - /* - else if(widget == ui->tabTriggerMode){ - ui->tabTriggerMode->updateSysStatusToUI(); - if(sysPara->status.fpgaVersionNum != 0){ - QString FpgaVersion; - if((sysPara->status.fpgaVersionNum>>12) == 8 || (sysPara->status.fpgaVersionNum>>12) == 6) - FpgaVersion = "72"; - else if((sysPara->status.fpgaVersionNum>>12) == 2 || (sysPara->status.fpgaVersionNum>>12) == 1){ - if(sysPara->para.flagOfFastMode) - FpgaVersion = "66"; - else - FpgaVersion = "67"; - } - FpgaVersion += QString("_F%1.%2.%3").arg(sysPara->status.fpgaVersionNum >> 12) - .arg((sysPara->status.fpgaVersionNum>>8) & 0x0f).arg(sysPara->status.fpgaVersionNum&0xff); - ui->tabTriggerMode->setBuildTime(QString(" No%1").arg(FpgaVersion)); - } - - } - */ else if(widget == m_PrintSetting) { m_PrintSetting->updateSysStatusToUI(); @@ -1439,6 +1399,13 @@ void InkJetPrinter::timerHandler(void){ } +void InkJetPrinter::slt_mTimer() +{ + m_warn = true; + setWarn(m_warn); + m_Timer->stop(); +} + void InkJetPrinter::checkStatusAndStartGearPump() { // 使用 QElapsedTimer 去抖:要求条件连续保持 >= 2000ms @@ -1842,6 +1809,191 @@ bool InkJetPrinter::eventFilter(QObject *watched, QEvent *event) return QWidget::eventFilter(watched,event); } +void InkJetPrinter::initStateManager() +{ + if (!sysPara) return; + + // 初始化状态管理器 + m_stateManager = PrinterStateManager::instance(); + + // 连接状态变化信号 DirectConnection:确保相关状态实时更新 + connect(m_stateManager, &PrinterStateManager::sig_stateChanged, + this, &InkJetPrinter::slt_stateChanged, Qt::DirectConnection); + + // ============ 开机时重置状态 ============ + m_stateManager->initFromSysPara(); + sysPara->status.selfCheckDone = false; // 自检是否完成 + sysPara->status.isPrinting = false; // 是否正在打印 + sysPara->status.powerOffAppending = false; // 是否正在关机 + + // 发送 PowerOn 事件进入自检状态 +// if (!sysPara->status.selfCheckDone) { +// m_stateManager->requestTransition(PrinterEvent::PowerOn); +// } + +// initStateTimer(); +} + +void InkJetPrinter::initStateTimer() +{ + // ============ 测试定时器 ============ + m_testTimer = new QTimer(this); + connect(m_testTimer, &QTimer::timeout, this, &InkJetPrinter::slt_stateTest); + m_testTimer->start(3000); // 3秒切换一次 +} + +void InkJetPrinter::handleSelfCheck() +{ + sysPara->status.selfCheckDone = false; + sysPara->status.selfCheckCnt = 0; + m_MainWidget->enablePrintButton(false); +} + +void InkJetPrinter::handleReady() +{ + // 自检完成,非打印状态,回收槽放下后使能打印按钮 + sysPara->status.selfCheckDone = true; + sysPara->status.isPrinting = false; + if(sysPara->status.reclaimTankstatus == 5) { + m_MainWidget->enablePrintButton(true); + } else { + m_MainWidget->enablePrintButton(false); + } + +} + +void InkJetPrinter::handleStartPrint() +{ + + + sysPara->status.isPrinting = true; + sysPara->devOp->highVoltageCtrl(1); + sysPara->devOp->setHighVoltageAmplitudetoSTM32(); + sysPara->status.waitHightVolOff = 0; +} + +void InkJetPrinter::handleStopPrint() +{ + sysPara->status.isPrinting = false; +// LogInfo::setRunStatusText("Stop print..."); +} + +void InkJetPrinter::handlePowerOff() +{ +// m_MainWidget->setRunStatus("正在关机..."); + m_MainWidget->checkForPowerOff(); +} + +void InkJetPrinter::slt_stateTest() +{ + if (!m_stateManager) return; + + PrinterState currentState = m_stateManager->currentState(); + + qDebug() << "=== Test Step:" << m_testStep << "Current:" << m_stateManager->stateName(); + + // 根据当前状态发送不同的事件 + switch (currentState) { + case PrinterState::IDLE: + // IDLE → SELF_CHECK + qDebug() << "▶ Send: PowerOn"; + m_stateManager->requestTransition(PrinterEvent::PowerOn); + break; + + case PrinterState::SELF_CHECK: + // SELF_CHECK → READY + qDebug() << "▶ Send: SelfCheckDone"; + m_stateManager->requestTransition(PrinterEvent::SelfCheckDone); + break; + + case PrinterState::READY: + // READY → PRINTING + qDebug() << "▶ Send: StartPrint"; + m_stateManager->requestTransition(PrinterEvent::StartPrint); + break; + + case PrinterState::PRINTING: + // PRINTING → STOPPING → READY(两步完成) + if (m_testStep % 2 == 0) { + qDebug() << "▶ Send: StopPrint"; + m_stateManager->requestTransition(PrinterEvent::StopPrint); + } else { + qDebug() << "▶ Send: StopComplete"; + m_stateManager->requestTransition(PrinterEvent::StopComplete); + } + break; + + case PrinterState::STOPPING: + // STOPPING → READY + qDebug() << "▶ Send: StopComplete"; + m_stateManager->requestTransition(PrinterEvent::StopComplete); + break; + + case PrinterState::ERROR: + // ERROR → READY + qDebug() << "▶ Send: ErrorCleared"; + m_stateManager->requestTransition(PrinterEvent::ErrorCleared); + break; + + case PrinterState::POWER_OFF: + // POWER_OFF → IDLE + qDebug() << "▶ Send: PowerOffDone"; + m_stateManager->requestTransition(PrinterEvent::PowerOffDone); + break; + + default: + break; + } + + m_testStep++; +} + +// ============ 状态机槽函数 ============ +void InkJetPrinter::slt_stateChanged(PrinterState newState, PrinterState oldState, QString reason) +{ + qDebug() << "State:" << m_stateManager->stateName() << "Reason:" << reason; + + // ============ 统一更新 sysPara 状态 ============ + switch (newState) { + case PrinterState::SELF_CHECK: + // 进入自检状态 + handleSelfCheck(); + break; + + case PrinterState::READY: + // 进入就绪状态 + handleReady(); + break; + + case PrinterState::PRINTING: + // 进入打印状态 + handleStartPrint(); + break; + + case PrinterState::STOPPING: + // 进入停止状态 + handleStopPrint(); + break; + + case PrinterState::ERROR: + // 进入故障状态 +// m_MainWidget->setRunStatus("故障!请检查"); +// m_MainWidget->enablePrintButton(false); + break; + + case PrinterState::POWER_OFF: + // 进入关机状态 + handlePowerOff(); + break; + + default: + break; + } + + // 保存参数 + //sysPara->saveParaToFile(); +} + /*************************FPGA通过串口读取状态赋值给status-start******************************************/ void InkJetPrinter::saveFPGAVersionNum(unsigned int data){ sysPara->status.fpgaVersionNum=data; @@ -2843,7 +2995,7 @@ void InkJetPrinter::showMessage(QString str){ qDebug()<devOp->color_flag = 2; - m_MainWidget->setRunStatus(str); + m_MainWidget->setRunStatus(str,1,0); } void InkJetPrinter::resetPressureCnt(){ @@ -3403,6 +3555,13 @@ void InkJetPrinter::handleWarnSolvent() } } } + +void InkJetPrinter::setWarn(bool flag) +{ + if (m_MainWidget) { + m_MainWidget->m_warn = flag; + } +} #endif void InkJetPrinter::slt_showMsg(QString msg) diff --git a/InkJetPrinter.h b/InkJetPrinter.h index e44a1f6..5c9afe8 100644 --- a/InkJetPrinter.h +++ b/InkJetPrinter.h @@ -39,6 +39,9 @@ #include "runtimectrl.h" #include "scene/PicSceneLoader.h" +// 状态机 +#include "StateMachine/PrinterStateManager.h" + class DialogFileOperation; class InkJetPrinter : public QWidget @@ -56,6 +59,7 @@ private: QLabel* m_LabelTimer; // 保留原有变量,和ui中的控件关联 QTimer* m_Timer; + bool m_warn = false; QTimer* timer; QTimer* viscosity_timer; // QTimer* jd_timer; @@ -158,6 +162,7 @@ private: QDateTime inkWarnTime = QDateTime(); QDateTime solventWarnTime = QDateTime(); #endif + void setWarn(bool flag); private slots: void resetRFIDStatus(); @@ -168,6 +173,7 @@ private slots: void slt_showMsg(QString msg); void timerHandler(); + void slt_mTimer(); void getMainWidgetButtonClickedSlot(int index); void getTestPrintWidgetButtonClickedSlot(int index); void openDatetimeEditor(DateItemModel dateModel, TextItemModel textItemModel); @@ -272,4 +278,31 @@ private: bool gearPumpRunFlag = false; bool gearPumpStartFlag = false; + + + // 状态机 + PrinterStateManager* m_stateManager = nullptr; + // 测试定时器 + QTimer* m_testTimer = nullptr; + int m_testStep = 0; +private: + void initStateManager(); + void initStateTimer(); + // 不同状态的处理 + // 自检 + void handleSelfCheck(); + + // 就绪 + void handleReady(); + + // 开始和暂停打印 + void handleStartPrint(); + void handleStopPrint(); + + // 关机 + void handlePowerOff(); +private slots: + void slt_stateTest(); + void slt_stateChanged(PrinterState newState, PrinterState oldState, QString reason); + }; diff --git a/QtUI.pro b/QtUI.pro index 0a80ef8..c62631b 100644 --- a/QtUI.pro +++ b/QtUI.pro @@ -183,7 +183,8 @@ HEADERS += Public.h \ loginfoctrl.h \ runtimectrl.h \ dump.h \ - DlgCanvasHeightEditor.h + DlgCanvasHeightEditor.h \ + StateMachine/PrinterStateManager.h FORMS += \ @@ -345,7 +346,8 @@ SOURCES +=\ Log/logmessage.cpp \ loginfoctrl.cpp \ runtimectrl.cpp \ - DlgCanvasHeightEditor.cpp + DlgCanvasHeightEditor.cpp \ + StateMachine/PrinterStateManager.cpp diff --git a/StateMachine/printerstatemanager.cpp b/StateMachine/printerstatemanager.cpp new file mode 100644 index 0000000..d00fd65 --- /dev/null +++ b/StateMachine/printerstatemanager.cpp @@ -0,0 +1,204 @@ +#include "PrinterStateManager.h" +#include + +PrinterStateManager* PrinterStateManager::s_instance = nullptr; + +PrinterStateManager* PrinterStateManager::instance() +{ + if (!s_instance) { + s_instance = new PrinterStateManager(); + } + return s_instance; +} + +PrinterStateManager::PrinterStateManager() +{ + initTransitions(); + m_currentState = PrinterState::IDLE; +} + +PrinterStateManager::~PrinterStateManager() +{ +} + +QString PrinterStateManager::stateName() const +{ + switch (m_currentState) { + case PrinterState::IDLE: return "空闲"; + case PrinterState::SELF_CHECK: return "自检中"; + case PrinterState::READY: return "就绪"; + case PrinterState::PRINTING: return "打印中"; + case PrinterState::STOPPING: return "停止中"; + case PrinterState::ERROR: return "故障"; + case PrinterState::POWER_OFF: return "关机中"; + default: return "未知"; + } +} + +// ============ 初始化状态(开机时调用一次) ============ +void PrinterStateManager::initFromSysPara() +{ + setState(PrinterState::SELF_CHECK, "Init from sysPara"); +} + +// ============ 状态转移表 ============ +void PrinterStateManager::initTransitions() +{ + m_transitions = { + // 开机流程 + {PrinterState::IDLE, PrinterEvent::PowerOn, + PrinterState::SELF_CHECK, "IDLE → SELF_CHECK", nullptr}, + {PrinterState::SELF_CHECK, PrinterEvent::SelfCheckDone, + PrinterState::READY, "SELF_CHECK → READY", nullptr}, + {PrinterState::SELF_CHECK, PrinterEvent::SelfCheckFailed, + PrinterState::ERROR, "SELF_CHECK → ERROR", nullptr}, + + // 打印流程 + {PrinterState::READY, PrinterEvent::StartPrint, + PrinterState::PRINTING, "READY → PRINTING", + [this]() -> bool { return guardCanStartPrint(); }}, + + {PrinterState::PRINTING, PrinterEvent::StopPrint, + PrinterState::STOPPING, "PRINTING → STOPPING", nullptr}, + {PrinterState::STOPPING, PrinterEvent::StopComplete, + PrinterState::READY, "STOPPING → READY", nullptr}, + + // 错误处理 + {PrinterState::READY, PrinterEvent::ErrorOccurred, + PrinterState::ERROR, "READY → ERROR", nullptr}, + {PrinterState::PRINTING, PrinterEvent::ErrorOccurred, + PrinterState::ERROR, "PRINTING → ERROR", nullptr}, + {PrinterState::STOPPING, PrinterEvent::ErrorOccurred, + PrinterState::ERROR, "STOPPING → ERROR", nullptr}, + {PrinterState::ERROR, PrinterEvent::ErrorCleared, + PrinterState::READY, "ERROR → READY", nullptr}, + + // 关机 + {PrinterState::READY, PrinterEvent::PowerOff, + PrinterState::POWER_OFF, "READY → POWER_OFF", nullptr}, + {PrinterState::PRINTING, PrinterEvent::PowerOff, + PrinterState::POWER_OFF, "PRINTING → POWER_OFF", nullptr}, + {PrinterState::STOPPING, PrinterEvent::PowerOff, + PrinterState::POWER_OFF, "STOPPING → POWER_OFF", nullptr}, + {PrinterState::ERROR, PrinterEvent::PowerOff, + PrinterState::POWER_OFF, "ERROR → POWER_OFF", nullptr}, + {PrinterState::POWER_OFF, PrinterEvent::PowerOffDone, + PrinterState::IDLE, "POWER_OFF → IDLE", nullptr}, + }; +} + +// ============ 查找转移 ============ +PrinterStateManager::Transition* PrinterStateManager::findTransition(PrinterEvent event) +{ + for (Transition& trans : m_transitions) { + if (trans.fromState == m_currentState && trans.event == event) { + return &trans; + } + } + return nullptr; +} + +// ============ 请求切换状态(外部唯一接口) ============ +void PrinterStateManager::requestTransition(PrinterEvent event) +{ + qDebug() << "Request event:" << static_cast(event) + << "Current:" << stateName(); + + m_currentState = PrinterState::READY; + Transition* trans = findTransition(event); + if (!trans) { + qDebug() << "Invalid transition, ignored"; + return; + } + + // 检查守卫条件 + if (trans->guard) { + bool result = trans->guard(); + if (!result) { + qDebug() << "Guard condition failed for:" << trans->description; + return; + } + } + + // 执行状态切换(内部管理) + setState(trans->toState, trans->description); +} + +// ============ 内部状态切换 ============ +void PrinterStateManager::setState(PrinterState newState, const QString& reason) +{ + if (m_currentState == newState) { + qDebug() << "State already:" << stateName(); + return; + } + + m_previousState = m_currentState; + m_currentState = newState; + + qDebug() << "State changed:" << stateName() << "Reason:" << reason; + + // 发送信号通知外部 + emit sig_stateChanged(newState, m_previousState, reason); +} + +// ============ 辅助函数 ============ +QString PrinterStateManager::stateNameFromEnum(PrinterState state) const +{ + switch (state) { + case PrinterState::IDLE: return "IDLE"; + case PrinterState::SELF_CHECK: return "SELF_CHECK"; + case PrinterState::READY: return "READY"; + case PrinterState::PRINTING: return "PRINTING"; + case PrinterState::STOPPING: return "STOPPING"; + case PrinterState::ERROR: return "ERROR"; + case PrinterState::POWER_OFF: return "POWER_OFF"; + default: return "UNKNOWN"; + } +} + +// ============ 守卫条件函数 ============ + +bool PrinterStateManager::guardReclaimTankOpen() +{ + if (!m_sysPara) return false; + return m_sysPara->status.reclainTankReachEnd == true; +} + +bool PrinterStateManager::guardInkSwintOpen() +{ + if (!m_sysPara) return false; + return !(m_sysPara->status.statWarn & WARN_STATUS_INK_SWINT); +} + +bool PrinterStateManager::guardNoError() +{ + if (!m_sysPara) return false; + return m_sysPara->status.statWarn == 0; +} + +bool PrinterStateManager::guardNoInkWarn() +{ + if (!m_sysPara) return false; + return !(m_sysPara->status.statWarn & WARN_STATUS_INK_WARN); +} + +bool PrinterStateManager::guardNoSolventWarn() +{ + if (!m_sysPara) return false; + return !(m_sysPara->status.statWarn & WARN_STATUS_SOLV_WARN); +} + +bool PrinterStateManager::guardSelfCheckDone() +{ + if (!m_sysPara) return false; + return m_sysPara->status.selfCheckDone == true; +} + +bool PrinterStateManager::guardCanStartPrint() +{ + if (!m_sysPara) return false; + + // 自检完成,开回收槽,开墨线,无异常报错 + return guardReclaimTankOpen() && guardInkSwintOpen() && + guardNoError() && guardSelfCheckDone(); +} diff --git a/StateMachine/printerstatemanager.h b/StateMachine/printerstatemanager.h new file mode 100644 index 0000000..3ec0323 --- /dev/null +++ b/StateMachine/printerstatemanager.h @@ -0,0 +1,114 @@ +#ifndef PRINTERSTATEMANAGER_H +#define PRINTERSTATEMANAGER_H +#pragma once +#include +#include +#include "SysPara.h" + +enum class PrinterState { + IDLE, // 空闲 + SELF_CHECK, // 自检中 + READY, // 就绪 + PRINTING, // 打印中 + STOPPING, // 停止中 + ERROR, // 故障 + POWER_OFF, // 关机中 + NORMAL // 一种常规状态,表明机器运行中,true +}; + +enum class PrinterEvent { + PowerOn, + SelfCheckDone, + SelfCheckFailed, + StartPrint, + StopPrint, + StopComplete, + ErrorOccurred, + ErrorCleared, + PowerOff, + PowerOffDone +}; + +class PrinterStateManager : public QObject +{ + Q_OBJECT +public: + static PrinterStateManager* instance(); + // 绑定 sysPara(用于守卫条件) + void bindSysPara(SysPara* para) { m_sysPara = para; } + + + // ============ 状态查询 ============ + PrinterState currentState() const { return m_currentState; } + QString stateName() const; + bool isState(PrinterState state) const { return m_currentState == state; } + bool canStartPrint() const { return m_currentState == PrinterState::READY; } + bool canStopPrint() const { return m_currentState == PrinterState::PRINTING; } + + // ============ 状态管理 ============ + // 初始化状态(只在开机时调用一次) + void initFromSysPara(); + + // 外部唯一接口:请求切换状态 + void requestTransition(PrinterEvent event); + +signals: + // 状态变化信号(外部监听执行具体业务) + void sig_stateChanged(PrinterState newState, PrinterState oldState, QString reason); + +private: + PrinterStateManager(); + ~PrinterStateManager(); + + SysPara* m_sysPara = nullptr; + static PrinterStateManager* s_instance; + + PrinterState m_currentState = PrinterState::IDLE; + PrinterState m_previousState = PrinterState::IDLE; + + // 状态转移表 + // 守卫条件函数类型 + using GuardFunc = std::function; + + struct Transition { + PrinterState fromState; + PrinterEvent event; + PrinterState toState; + QString description; + GuardFunc guard; + }; + + QVector m_transitions; + + void initTransitions(); + Transition* findTransition(PrinterEvent event); + + // 内部状态切换(不对外暴露) + void setState(PrinterState newState, const QString& reason = ""); + + QString stateNameFromEnum(PrinterState state) const; + + // ============ 守卫条件函数 ============ + // 检查回收槽是否已打开 + bool guardReclaimTankOpen(); + + // 检查墨线是否已打开 + bool guardInkSwintOpen(); + + // 检查是否无故障 + bool guardNoError(); + + // 检查是否无墨水警告 + bool guardNoInkWarn(); + + // 检查是否无溶剂警告 + bool guardNoSolventWarn(); + + // 检查自检是否已完成 + bool guardSelfCheckDone(); + + // 检查是否满足所有打印条件 + bool guardCanStartPrint(); + +}; +#endif // PRINTERSTATEMANAGER_H diff --git a/mainwidget.cpp b/mainwidget.cpp index 0ac364a..5f51d01 100644 --- a/mainwidget.cpp +++ b/mainwidget.cpp @@ -38,6 +38,7 @@ #include #include "MainWidget.h" #include "scene/ItemCommon.h" +#include "StateMachine/PrinterStateManager.h" extern MyInputMethod *myInputMethod; unsigned char test_flag,open_close; @@ -321,7 +322,7 @@ void MainWidget::checkForPowerOff(){ { if(i==13) sysPara->devOp->controlReclaimTankOpen(false); - this->setRunStatus(tr("正在准备关机,请等待%1秒...").arg(i*3), false); + this->setRunStatus(tr("正在准备关机,请等待%1秒...").arg(i), false); MySleep(3000); } } @@ -334,7 +335,7 @@ void MainWidget::checkForPowerOff(){ updateTotalCnt(0); sysPara->saveParaToFile(); // 关机前将相关配置保存 } - sysPara->status.powerOffAppending = false; + if(!TEST_MODE){ for(int i=7;i>0;i--) { @@ -396,15 +397,22 @@ void MainWidget::powerOffConfirmed(){ qApp->exit(0); } -void MainWidget::setRunStatus(QString str, bool enbRoll) +void MainWidget::setRunStatus(QString str, bool enbRoll, bool warn) { + //自检和关机时不显示报警logo + if (warn) { + if (sysPara && !sysPara->status.selfCheckDone + || sysPara->status.powerOffAppending) { + return; + } + } + // 自检完成后,timerHandler中会发送停止打印的命令,导致“停止打印,自动关闭高压.”顶替掉“自检完成!!!”的情况 if(ui.lb_nozzleState->text() == qApp->translate("InkJetPrinter", "自检完成!!!") && str == qApp->translate("InkJetPrinter", "停止打印,自动关闭高压.")) { return; } - qDebug() << str; // 如果禁用走马灯(enbRoll == false),直接在label上显示文本(即使过长) if (!enbRoll) { if (ui.lb_nozzleState) { @@ -911,10 +919,6 @@ void MainWidget::enablePrintButton(bool enable){ enable = true; #endif -#ifdef FPGA_TEST - enable = true; -#endif - m_StartBtn->setEnabled(enable); m_StopBtn->setEnabled(enable); } @@ -941,18 +945,6 @@ void MainWidget::updateTotalCnt(int en) void MainWidget::on_m_StartBtn_clicked() { - if(sysPara->status.isPrinting){ - qDebug("Mainwindow: Printing 开始打印"); - }else{ - qDebug("Mainwindow: Non printing 开始打印"); - } - static int fileCount = 0; - fileCount++; - if(fileCount > 5) - { - fileCount = 1; - } - if(sysPara){ bool MaxCol4000; if(sysPara->status.flagOfNo67FPGA) @@ -960,68 +952,19 @@ void MainWidget::on_m_StartBtn_clicked() else MaxCol4000 = false; test_flag = 0; - /******2020/2/29*****/ - if(sysPara->para.printTriggerMode == PRINT_TRIGGER_SYNCHRONIZER) //同步模式下,判断喷印间隔是否设置合理 - { - QSizeF size = QSizeF(sysPara->status.currPrintCol, sysPara->status.currPrintRow); - float stroke,print_len_min; - stroke = sysPara->para.printColDelay/sysPara->para.synPulseNumPerMm; - print_len_min = stroke * size.width(); - if(print_len_min > sysPara->para.synTriggerPrintLenMm && !sysPara->para.charWidthSetEnable) - { - QMessageBox::information(this,tr("错误"),tr("喷印间隔过短,应高于%1!").arg(print_len_min)); - return; - } - } - /******2020/2/29 end*****/ - #ifndef QT_DEBUG - if(!SIMULATE_PRINTING_MODE){ - if (!sysPara->status.reclainTankReachEnd) { - return; - } - if((sysPara->status.statWarn & WARN_STATUS_HDINT)){ - QMessageBox::information(this,tr("错误"),tr("喷头盖未关,请先关喷头盖!")); - return ; - } - if((sysPara->status.statWarn & WARN_STATUS_INK_SWINT)){ - QMessageBox::information(this,tr("错误"),tr("墨线未开,请先开墨线开关!")); - return ; - } - } - #endif - sysPara->devOp->highVoltageCtrl(1); - sysPara->devOp->setHighVoltageAmplitudetoSTM32(); - sysPara->status.waitHightVolOff = 0; - - if(sysPara->status.currPrintCol > (MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide)){ - QMessageBox::critical(0,tr("错误"),tr("当前总列数 %1 ,支持的总列数为 %2,请减少打印串的长度").arg(sysPara->status.currPrintCol).arg((MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide))); - return ; - } - if(!((sysPara->para.printTriggerMode == PRINT_TRIGGER_SYNCHRONIZER) - ||((sysPara->para.printTriggerMode == PRINT_TRIGGER_ELEC_EYE_VOLTATE_LEVEL - ||sysPara->para.printTriggerMode == PRINT_TRIGGER_ELEC_EYE_EDGE) - && sysPara->para.eleEyeTriggerSynPrintEn)) - ) - { - int dotNumPerCol = sysPara->status.currPrintRow*(1 + sysPara->para.printRowDelay) + sysPara->para.printColDelay; - long printTmUs = 1.0f*dotNumPerCol*(1 + sysPara->para.charBold)*sysPara->status.currPrintCol*(2*sysPara->para.divideRatio)/(FPGA_SYS_HZ/1000000); - if((printTmUs/1000 + 3) > (sysPara->para.printDelayMs)\ - && (sysPara->para.timeTriggerPrintMode == TIME_TRIGGER_PRINT_MODE_HEAD_TO_HEAD) - && (sysPara->para.printTriggerMode == PRINT_TRIGGER_TIME ) - ) // 在电眼方式下,是否需要判呢? - { - QMessageBox::critical(0,tr("错误"),tr("打印耗时 %1ms ,触发间隔 :%2ms ,触发间隔至少应当大于打印耗时3ms").arg(printTmUs/1000).arg(sysPara->para.printDelayMs)); - return ; - } - } - sysPara->status.isPrinting=false; + if (!checkTriggerMode()) return; + // 打印状态交给状态机修改 +// sysPara->status.isPrinting=false; + auto mgr = PrinterStateManager::instance(); + if (mgr && mgr->canStopPrint()) { + mgr->requestTransition(PrinterEvent::StopPrint); + } else {return;} SendPrintDataToFpga(0); // 0--正常打印,1--打印交替部分信息1; 2--打印交替部分信息2, /*-------------------------------------------------------------------*/ -// ui->labelSynColDelay->setText(""); sysPara->status.lastSynColDelay = -1; //目的是为了清空原来的数据 /*---------------------------------开关回收槽------------------------------*/ @@ -1038,32 +981,33 @@ void MainWidget::on_m_StartBtn_clicked() } startPrintingFlag = true; - sysPara->status.isPrinting=true; +// sysPara->status.isPrinting=true; + if (mgr->canStartPrint() || mgr->isState(PrinterState::PRINTING)) { + mgr->requestTransition(PrinterEvent::StartPrint); + } // 高亮切换 changeHighLight(true); - - LogInfo::setRunStatusText("Start print..."); } } void MainWidget::on_m_StopBtn_clicked() { - if(sysPara->status.isPrinting){ - qDebug("Mainwindow: Printing 停止打印"); - }else{ - qDebug("Mainwindow: Non printing 停止打印"); - } - if(sysPara){ if (!sysPara->status.reclainTankReachEnd && !SIMULATE_PRINTING_MODE) { return; } -// sysPara->status.flagOfAbnormalStatus = false; - sysPara->status.isPrinting=false; +// sysPara->status.isPrinting=false;// 打印状态交给状态机修改 + auto mgr = PrinterStateManager::instance(); + if (mgr && mgr->canStopPrint()) { + mgr->requestTransition(PrinterEvent::StopPrint); + } else { + return; + } + sysPara->devOp->printCtrl2(1); sysPara->devOp->printCtrl( PRINT_CTRL_STOP);//:PRINT_CTRL_STOPSYNCNT -// LogInfo::setRunStatusText(tr("停止打印")); + setReclaimCloseBtnStatus(sysPara->status.currReclaimTankPos != 0); setReclaimOpenBtnStatus(sysPara->status.currReclaimTankPos == 0); @@ -1071,7 +1015,7 @@ void MainWidget::on_m_StopBtn_clicked() printintFlag = false; startPrintingFlag = false; updatePrintDisplayLabel(); - sysPara->status. waitHightVolOff = 1; + sysPara->status.waitHightVolOff = 1; sysPara->saveParaToFile(); // 将相关配置保存 if(sysPara->status.RandomBackCnt>5 && (sysPara->status.RandomNum>0)) @@ -1081,16 +1025,11 @@ void MainWidget::on_m_StopBtn_clicked() tr("随机码文本将展出到U盘,请插入U盘"), QMessageBox::Ok | QMessageBox::Cancel); if (ret == QMessageBox::Ok){ -// LogInfo::setRunStatusText("正在导出随机码文件到U盘......"); sysPara->devOp->RandTxtBakup(0); //备份到U盘 -// LogInfo::setRunStatusText("随机码文件导出完成."); - } } // 高亮切换 changeHighLight(false); - - LogInfo::setRunStatusText("Stop print..."); } } @@ -1866,6 +1805,13 @@ void MainWidget::updateGeneralState(AlarmStatus status) } } + // 自检时设为正常, 关机设为正常 + if (!sysPara->status.selfCheckDone + || sysPara->status.powerOffAppending) { + m_stateColor = DEV_STATUS_GREEN; + m_stateStr= tr("正常"); + } + if (m_stateColor == DEV_STATUS_GREEN) { ui.fra_state->setStyleSheet("background-color: #ccffcc;"); } else if (m_stateColor == DEV_STATUS_RED) { @@ -2336,15 +2282,15 @@ void MainWidget::RefreshStatusLight(){//100ms if(sysPara->para.RecycleWarnAction) { if((sysPara->status.currReclaimTankPos != 0) && !sysPara->devOp->isReclaimTankCloseEnable()){ -// on_pushButtonStopPrint_pressed(); on_m_StopBtn_clicked(); -// on_pushButtonReclaimTankClose_pressed(); on_m_LeftBtn_clicked(); - LogInfo::setRunStatusText(tr("回收故障,关闭回收槽,关墨线")); - setRunStatus(tr("回收故障,关闭回收槽,关墨线")); + if (m_warn) { + LogInfo::setRunStatusText(tr("回收故障,关闭回收槽,关墨线")); + setRunStatus(tr("回收故障,关闭回收槽,关墨线"),true,true); + } } } - else setRunStatus(tr("回收故障.")); + else if (m_warn) {setRunStatus(tr("回收故障."),true,true); } } else @@ -2553,6 +2499,62 @@ bool MainWidget::isInExpandedRect(QWidget* widget, const QPoint& globalPos, int return rect.contains(globalPos); } +bool MainWidget::checkTriggerMode() +{ + /******2020/2/29*****/ + if(sysPara->para.printTriggerMode == PRINT_TRIGGER_SYNCHRONIZER) //同步模式下,判断喷印间隔是否设置合理 + { + QSizeF size = QSizeF(sysPara->status.currPrintCol, sysPara->status.currPrintRow); + float stroke,print_len_min; + stroke = sysPara->para.printColDelay/sysPara->para.synPulseNumPerMm; + print_len_min = stroke * size.width(); + if(print_len_min > sysPara->para.synTriggerPrintLenMm && !sysPara->para.charWidthSetEnable) + { + QMessageBox::information(this,tr("错误"),tr("喷印间隔过短,应高于%1!").arg(print_len_min)); + return false; + } + } + /******2020/2/29 end*****/ +#ifndef QT_DEBUG + if(!SIMULATE_PRINTING_MODE){ + if (!sysPara->status.reclainTankReachEnd) { + return; + } + if((sysPara->status.statWarn & WARN_STATUS_HDINT)){ + QMessageBox::information(this,tr("错误"),tr("喷头盖未关,请先关喷头盖!")); + return ; + } + if((sysPara->status.statWarn & WARN_STATUS_INK_SWINT)){ + QMessageBox::information(this,tr("错误"),tr("墨线未开,请先开墨线开关!")); + return ; + } + } +#endif + + if(sysPara->status.currPrintCol > (MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide)){ + QMessageBox::critical(0,tr("错误"),tr("当前总列数 %1 ,支持的总列数为 %2,请减少打印串的长度").arg(sysPara->status.currPrintCol).arg((MaxCol4000?MAX_PRINT_COL_NUM_Normal:MAX_PRINT_COL_NUM_Wide))); + return false; + } + if(!((sysPara->para.printTriggerMode == PRINT_TRIGGER_SYNCHRONIZER) + ||((sysPara->para.printTriggerMode == PRINT_TRIGGER_ELEC_EYE_VOLTATE_LEVEL + ||sysPara->para.printTriggerMode == PRINT_TRIGGER_ELEC_EYE_EDGE) + && sysPara->para.eleEyeTriggerSynPrintEn)) + ) + { + int dotNumPerCol = sysPara->status.currPrintRow*(1 + sysPara->para.printRowDelay) + sysPara->para.printColDelay; + long printTmUs = 1.0f*dotNumPerCol*(1 + sysPara->para.charBold)*sysPara->status.currPrintCol*(2*sysPara->para.divideRatio)/(FPGA_SYS_HZ/1000000); + if((printTmUs/1000 + 3) > (sysPara->para.printDelayMs)\ + && (sysPara->para.timeTriggerPrintMode == TIME_TRIGGER_PRINT_MODE_HEAD_TO_HEAD) + && (sysPara->para.printTriggerMode == PRINT_TRIGGER_TIME ) + ) // 在电眼方式下,是否需要判呢? + { + QMessageBox::critical(0,tr("错误"),tr("打印耗时 %1ms ,触发间隔 :%2ms ,触发间隔至少应当大于打印耗时3ms").arg(printTmUs/1000).arg(sysPara->para.printDelayMs)); + return false; + } + } + return true; +} + void MainWidget::onLabelFaultRusumePressed(){ if(sysPara){ @@ -2640,4 +2642,4 @@ void MainWidget::UpdateUIVersion(){ QString Mac = QString::number(sysPara->status.machineMac); LogInfo::setRunStatusText(QString("Mac:%1").arg(Mac)); LogInfo::showVerionInformation(Mac,VernonBach,fpgaVersion,STM32Ver); -} \ No newline at end of file +} diff --git a/mainwidget.h b/mainwidget.h index e822ce4..0902024 100644 --- a/mainwidget.h +++ b/mainwidget.h @@ -36,6 +36,7 @@ class MainWidget : public QWidget public: MainWidget(QWidget* parent = nullptr); ~MainWidget(); + bool m_warn = false; void bindSysPara(SysPara *SysPara); @@ -85,7 +86,7 @@ public: void generateCharRamDataV2(); - void setRunStatus(QString str, bool enbRoll = true); + void setRunStatus(QString str, bool enbRoll = true, bool warn = false); void enablePrintButton(bool); int getCurrPrintStatus(); @@ -175,9 +176,11 @@ private: qint64 m_lastClickTime = 0; const int m_doubleClickDistance = 25; // 自定义距离阈值(像素) const int m_doubleClickInterval = 500; // 自定义时间阈值(毫秒) + void mousePressEvent(QMouseEvent *event) override; void handleDoubleClick(QMouseEvent *event); bool isInExpandedRect(QWidget* widget, const QPoint& globalPos, int expandSize); + bool checkTriggerMode(); //-------------------- public slots: void powerOffConfirmed(); @@ -245,4 +248,4 @@ signals: void newFileAcquired(); }; -#endif // MainWidget_H \ No newline at end of file +#endif // MainWidget_H diff --git a/myinclude.h b/myinclude.h index e603d42..c4da9b8 100644 --- a/myinclude.h +++ b/myinclude.h @@ -12,7 +12,6 @@ #define MYSAVEFILEDLG // 定义自己的保存文件对话框,解决系统对话框按键不弹起问题 #define LANINTERFACE_NAME "eth0" -// #define FPGA_TEST //#define __RFID_OLD //旧的加密算法 #define __RFID_CARD //刷卡功能 //#define __RFID_IND //允许印度进行二次加密的宏 diff --git a/scene/PicDateItem.h b/scene/PicDateItem.h index 32c01ae..a5d5cad 100644 --- a/scene/PicDateItem.h +++ b/scene/PicDateItem.h @@ -22,6 +22,8 @@ public: bool updateDatetimeStr(); + virtual QRectF boundingRect() const override; + protected: virtual void setCustomAttrs(const QXmlStreamAttributes& attrs) override; @@ -37,8 +39,6 @@ private: QString m_currDateTimeStr; QString m_maxDateTimeStr; QSize m_maxSize; // 缓存最长字符串的像素宽高 - - virtual QRectF boundingRect() const override; }; #endif // PIC_DATE_ITEM_H diff --git a/scene/PicScheduleShiftItem.h b/scene/PicScheduleShiftItem.h index 9e188f0..ed3e2ea 100644 --- a/scene/PicScheduleShiftItem.h +++ b/scene/PicScheduleShiftItem.h @@ -32,6 +32,8 @@ public: bool updateScheduleName(); + virtual QRectF boundingRect() const override; + protected: virtual void setCustomAttrs(const QXmlStreamAttributes& attrs) override; @@ -48,8 +50,6 @@ private: QString m_currScheduleName; QSize m_maxSize; // 缓存最长名称的像素宽高 - virtual QRectF boundingRect() const override; - QSize calcMaxSize(); }; diff --git a/scene/piccodeitem.cpp b/scene/piccodeitem.cpp index ec9140e..703a961 100644 --- a/scene/piccodeitem.cpp +++ b/scene/piccodeitem.cpp @@ -61,6 +61,11 @@ bool PicCodeItem::updateVariants(const QVector counters) return b; } +int PicCodeItem::getHeight() +{ + return m_codeImage.height(); +} + QImage PicCodeItem::itemImage() { return m_codeImage; diff --git a/scene/piccodeitem.h b/scene/piccodeitem.h index 434ce3e..9f3018f 100644 --- a/scene/piccodeitem.h +++ b/scene/piccodeitem.h @@ -20,6 +20,7 @@ public: bool updateVariants(const QVector counters); + int getHeight(); protected: /** * @brief itemImage 子类可以重新实现该方法用于返回已经渲染好了的但未应用方向、水平拉伸的图像 diff --git a/testprintwidget.cpp b/testprintwidget.cpp index fae6be8..a668066 100644 --- a/testprintwidget.cpp +++ b/testprintwidget.cpp @@ -136,10 +136,6 @@ TestPrintWidget::TestPrintWidget(QWidget* parent) connect(ui.btnArrow, &QPushButton::clicked, this, &TestPrintWidget::onBtnArrowClicked); connect(ui.btnNum,&QPushButton::clicked,[this](){ - // on_addButton_pressed(); - // m_TextEdit->clear(); - // emit sendButtonClickedSignal(17); - pPicScene->clearSelection(); QFont font("WenQuanYi7"); @@ -273,10 +269,11 @@ void TestPrintWidget::on_addButton_pressed(const SourceType type) QRectF itemRect= items.at(1)->boundingRect(); textItem->setPos( items.at(1)->scenePos().x()+itemRect.width()+20, items.at(1)->scenePos().y()); } - else textItem->setPos(this->pViewer->mapToScene(0,0));//edit@12-07 + else { + int y = pViewer->height() - textItem->boundingRect().height(); + textItem->setPos(this->pViewer->mapToScene(0,y));//edit@12-07 + } -// textItem->setPlainText("Vernon Bach Printer"); -// ui->saveButton->setEnabled(true); textItem->setPlainText(""); textItem->setSelected(true); } @@ -696,10 +693,13 @@ void TestPrintWidget::onImageLoaderAccepted() PicTextItem* item = new PicImageItem(0, 0, SourceType::IMAGE); item->setHtml(htmlImg); pPicScene->addItem(item); - auto boundingRect = pPicScene->itemsBoundingRect(); - item->setPos(boundingRect.right(), 0.0); - item->setSelected(true); item->setSource(imgPath); + auto boundingRect = pPicScene->itemsBoundingRect(); + int y = sysPara->para.canvasHeight - item->boundingRect().height(); + item->setPos(x_item, y); + x_item = x_item + boundingRect.right() + 5; + item->setSelected(true); + } void TestPrintWidget::onBtnItemConfigClicked() @@ -795,8 +795,11 @@ void TestPrintWidget::onSceneFocusedItemPosChanged(QPoint p) ui.m_lblY->setText(QString::asprintf("Y:%d", p.y())); } + void TestPrintWidget::on_newfileButton_pressed() { + x_item = 0; + // if (maybeSave()) { pPicScene->clear(); pViewer->viewport()->update(); @@ -835,12 +838,17 @@ void TestPrintWidget::slt_BarCodeItemDone() // 添加条形码或二维码 pPicScene->clearSelection(); codeItem = new PicCodeItem(0, 0, SourceType::CODE); + codeItem->setBarcodeViewModel(vm); + auto boundingRect = pPicScene->itemsBoundingRect(); pPicScene->addItem(codeItem); - codeItem->setPos(boundingRect.right(), 0.0); + int y = sysPara->para.canvasHeight - codeItem->boundingRect().height(); + codeItem->setPos(x_item, y); + x_item = x_item + boundingRect.right() + 5; + } else { + codeItem->setBarcodeViewModel(vm); } - codeItem->setBarcodeViewModel(vm); codeItem->setSelected(true); m_printSettingModel.cnt1Settings = vm.counterViewModel.cnt1Settings; @@ -998,7 +1006,9 @@ void TestPrintWidget::addDateTimeItem(const DateItemModel &model, const TextItem item->setHtml(htmlStr); pPicScene->addItem(item); auto boundingRect = pPicScene->itemsBoundingRect(); - item->setPos(boundingRect.right(), 0.0); + int y = sysPara->para.canvasHeight - item->boundingRect().height(); + item->setPos(x_item, y); + x_item = x_item + boundingRect.right() + 5; item->setSelected(true); item->setModel(model); } @@ -1023,11 +1033,14 @@ void TestPrintWidget::addScheduleShiftsItem(QVector schedules, Te PicScheduleShiftItem* item = new PicScheduleShiftItem(); item->setHtml(htmlStr); pPicScene->addItem(item); + item->setTextItemModel(txtModel); auto boundingRect = pPicScene->itemsBoundingRect(); - item->setPos(boundingRect.right(), 0.0); + int y = sysPara->para.canvasHeight - item->boundingRect().height(); + item->setPos(x_item, y+3); + x_item = x_item + boundingRect.right() + 5; item->setSelected(true); item->setSchedules(std::move(schedules)); - item->setTextItemModel(txtModel); + } void TestPrintWidget::addCounterItem(CounterViewModel vm, QSharedPointer f) @@ -1075,12 +1088,14 @@ void TestPrintWidget::addCounterItem(CounterViewModel vm, QSharedPointer pPicScene->clearSelection(); PicCounterItem* item = new PicCounterItem(); pPicScene->addItem(item); + item->setCounter(static_cast(vm.counterType), vm.digitalNum); auto boundingRect = pPicScene->itemsBoundingRect(); - item->setPos(boundingRect.right(), 0.0); + int y = sysPara->para.canvasHeight - item->boundingRect().height(); + item->setPos(x_item, y); + x_item = x_item + boundingRect.right() + 5; item->setSelected(true); item->setLetterSpace(static_cast(font.letterSpacing())); // item->setCustomFont(font.family()); - item->setCounter(static_cast(vm.counterType), vm.digitalNum); if(vm.enbCustomCharWidth) { item->setCharWidth(vm.charWidth); } diff --git a/testprintwidget.h b/testprintwidget.h index 4337b72..8229f21 100644 --- a/testprintwidget.h +++ b/testprintwidget.h @@ -123,7 +123,6 @@ private: void moveSelectedItem(Qt::Key key); PicScene *pPicScene = nullptr; //保存Item的Html - // PicScene *pPicScene2; // 保存Item的Html对应的图片 解决场景模式文本无法放大的问题 QGraphicsView *pViewer = nullptr; PicTextItem *textItem = nullptr; @@ -142,6 +141,7 @@ private: //寻找当前选中的图层,没有选中的就不继续处理 int checkSelectScene(); + int x_item = 0; // 复制 int pasteTime = 1; SourceType m_copiedSourceType = SourceType::UNKNOWN;