抽离场景打开逻辑、添加编辑界面的左右拖动功能
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include"myinclude.h"
|
||||
#include<iostream>
|
||||
#include<string>
|
||||
#include "scene/PicSceneLoader.h"
|
||||
|
||||
DialogFileOperation::DialogFileOperation(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@@ -78,8 +79,11 @@ void DialogFileOperation::on_listViewFile_entered(const QModelIndex &index)
|
||||
}
|
||||
else if(filePath.endsWith(".xml"))
|
||||
{
|
||||
emit createSceneImage(filePath);
|
||||
ui->textEditView->setHtml(QString("<img src='%1'/>").arg("./printSceneView.png"));
|
||||
QImage previewImg = PicSceneLoader::previewSceneFromFile(filePath);
|
||||
ui->textEditView->clear();
|
||||
auto cursor = ui->textEditView->textCursor();
|
||||
cursor.insertImage(previewImg);
|
||||
ui->textEditView->setTextCursor(cursor);
|
||||
}
|
||||
else {
|
||||
QFile file(filePath);
|
||||
|
||||
+9
-9
@@ -1008,8 +1008,15 @@ void InkJetPrinter::timerHandler(void){
|
||||
}
|
||||
|
||||
// byons: 时间类型图元更新 @2026年4月11日
|
||||
auto updateArea = m_MainWidget->variableItemsUpdate();
|
||||
if (!updateArea.isNull()) {
|
||||
// byons: 变量类图元现在优化为局部更新,避免每次都要把整个打印内容发送给FPGA,现在只发送被更新的列区间 2026年7月16日
|
||||
auto updateAreas = m_MainWidget->variableItemsUpdate();
|
||||
if(sysPara->status.isPrinting && !updateAreas.isEmpty()){
|
||||
for(const auto& area : updateAreas) {
|
||||
m_MainWidget->SendPrintDataToFpga(0, area.left(), area.width());
|
||||
}
|
||||
}
|
||||
|
||||
if (!updateAreas.isEmpty() && m_StackedWidget->currentWidget() == m_MainWidget) {
|
||||
// // 统计追踪更新频率
|
||||
// static QElapsedTimer bnsTimer;
|
||||
// static int toogleCount = 0;
|
||||
@@ -1019,15 +1026,8 @@ void InkJetPrinter::timerHandler(void){
|
||||
// qDebug() << (QString("timeHandler avg elapsed: %1 s").arg(elapsed / qreal(toogleCount) / 1000.0));
|
||||
// toogleCount = 0;
|
||||
// }
|
||||
|
||||
if(sysPara->status.isPrinting) {
|
||||
m_MainWidget->SendPrintDataToFpga(0, updateArea.left(), updateArea.width());
|
||||
}
|
||||
|
||||
if(m_StackedWidget->currentWidget() == m_MainWidget) {
|
||||
m_MainWidget->updatePrintDisplayLabel();
|
||||
}
|
||||
}
|
||||
|
||||
// if (modbus->getModbusStatus() == 1) {
|
||||
// refreshModbusStatus();
|
||||
|
||||
+1
-1
@@ -649,7 +649,7 @@ void PrintSetting::applyPrintSettingsToSysPara(bool showTip)
|
||||
if(res != -1 && showTip) {
|
||||
QMessageBox box(QMessageBox::Icon::Information, tr("提示"), tr("应用成功"), QMessageBox::Ok, nullptr);
|
||||
auto btn = box.button(QMessageBox::Ok);
|
||||
// btn->setFixedSize(80, 40);
|
||||
btn->setFixedSize(80, 40);
|
||||
|
||||
box.exec();
|
||||
}
|
||||
|
||||
@@ -123,6 +123,7 @@ HEADERS += Public.h \
|
||||
scene/pictextitem.h \
|
||||
scene/picscene.h \
|
||||
scene/myview.h \
|
||||
scene/PicSceneLoader.h \
|
||||
scene/ItemGeneralSettings.h \
|
||||
scene/DateReplaceEditor.h \
|
||||
DialogSaveFile.h \
|
||||
@@ -277,6 +278,7 @@ SOURCES +=\
|
||||
scene/pictextitem.cpp \
|
||||
scene/picscene.cpp \
|
||||
scene/myview.cpp \
|
||||
scene/PicSceneLoader.cpp \
|
||||
scene/ItemGeneralSettings.cpp \
|
||||
scene/ScheduleShiftsEditor.cpp \
|
||||
scene/PicScheduleShiftItem.cpp \
|
||||
|
||||
+37
-10
@@ -10,6 +10,7 @@
|
||||
#include <QRgb>
|
||||
#include <QDebug>
|
||||
#include <QScrollBar>
|
||||
#include <algorithm>
|
||||
#include <QFontMetrics>
|
||||
#include <QChar>
|
||||
#include <stdlib.h>
|
||||
@@ -507,10 +508,10 @@ void MainWidget::generateCharRamData()
|
||||
|
||||
}
|
||||
|
||||
QRect MainWidget::variableItemsUpdate()
|
||||
QList<QRect> MainWidget::variableItemsUpdate()
|
||||
{
|
||||
if(!pPicScene) {
|
||||
return QRect();
|
||||
return QList<QRect>();
|
||||
}
|
||||
|
||||
int totalOfProcessedDots = 0;
|
||||
@@ -518,7 +519,7 @@ QRect MainWidget::variableItemsUpdate()
|
||||
int nbInvaliedDatetimePreview = 0;
|
||||
int nbClipDatetimePreview = 0;
|
||||
|
||||
QRect updateArea = {0, 0, 0, 0};
|
||||
QList<QRect> updateAreas;
|
||||
|
||||
auto items = pPicScene->items();
|
||||
for(auto i : items) {
|
||||
@@ -594,10 +595,36 @@ QRect MainWidget::variableItemsUpdate()
|
||||
|
||||
totalOfProcessedDots += imageToPrintData(img, (int)itemRect.left(), (int)itemRect.top());
|
||||
|
||||
updateArea = updateArea.united(itemRect);
|
||||
updateAreas.append(itemRect);
|
||||
}
|
||||
|
||||
return updateArea;
|
||||
if(updateAreas.isEmpty())
|
||||
return updateAreas;
|
||||
|
||||
// 把 updateAreas 里 x 轴相交或相连的矩形合并,避免某些区域重复更新而导致的串口资源浪费
|
||||
std::sort(updateAreas.begin(), updateAreas.end(), [](const QRect &a, const QRect &b) {
|
||||
if (a.left() != b.left())
|
||||
return a.left() < b.left();
|
||||
return a.right() < b.right();
|
||||
});
|
||||
|
||||
QList<QRect> mergedAreas;
|
||||
mergedAreas.append(updateAreas.first());
|
||||
for (int i = 1; i < updateAreas.size(); ++i) {
|
||||
QRect current = updateAreas.at(i);
|
||||
QRect &last = mergedAreas.last();
|
||||
if (last.right() + 1 >= current.left()) {
|
||||
int left = qMin(last.left(), current.left());
|
||||
int right = qMax(last.right(), current.right());
|
||||
int top = qMin(last.top(), current.top());
|
||||
int bottom = qMax(last.bottom(), current.bottom());
|
||||
last = QRect(QPoint(left, top), QPoint(right, bottom));
|
||||
} else {
|
||||
mergedAreas.append(current);
|
||||
}
|
||||
}
|
||||
|
||||
return mergedAreas;
|
||||
}
|
||||
|
||||
int MainWidget::imageToPrintData(QImage &image, int startX, int startY)
|
||||
@@ -619,7 +646,7 @@ int MainWidget::imageToPrintData(QImage &image, int startX, int startY)
|
||||
unsigned char c = 0;
|
||||
int hStart = startY;
|
||||
|
||||
c = dat[(wStart)*5 + (hStart)/8];
|
||||
c = dat[wStart * MAX_PRINT_ROW_BYTE_NUM + (hStart) / 8];
|
||||
|
||||
for(int k = 0; k < height; k++)
|
||||
{
|
||||
@@ -634,14 +661,14 @@ int MainWidget::imageToPrintData(QImage &image, int startX, int startY)
|
||||
}
|
||||
|
||||
if(hStart % 8 == 7) {
|
||||
dat[(wStart)*5 + (hStart)/8] = c;
|
||||
c = dat[(wStart)*5 + (hStart + 1)/8];
|
||||
dat[wStart * MAX_PRINT_ROW_BYTE_NUM + (hStart) / 8] = c;
|
||||
c = dat[wStart * MAX_PRINT_ROW_BYTE_NUM + (hStart + 1) / 8];
|
||||
++totalOfProcessedDots;
|
||||
}
|
||||
hStart++;
|
||||
}
|
||||
|
||||
dat[(wStart)*5 + (hStart)/8] = c;
|
||||
dat[wStart * MAX_PRINT_ROW_BYTE_NUM + (hStart) / 8] = c;
|
||||
wStart++;
|
||||
totalOfProcessedDots++;
|
||||
}
|
||||
@@ -1348,7 +1375,7 @@ void MainWidget::slt_setNum()
|
||||
void MainWidget::slt_clearCnt()
|
||||
{
|
||||
if (sysPara) {
|
||||
sysPara->devOp->clearProductCnt(3 | 0x10);// 重新计米
|
||||
sysPara->devOp->clearProductCnt(1);//当前产品计数器立即清零
|
||||
ui.labelProductCnt->setText("0");
|
||||
// SendPrintDataToFpga(0);
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ public:
|
||||
* @return 返回需要更新的区域
|
||||
* @remark 判断返回值用于决定是否SendPrintDataToFpga
|
||||
*/
|
||||
QRect variableItemsUpdate();
|
||||
QList<QRect> variableItemsUpdate();
|
||||
|
||||
/**
|
||||
* @brief 向FPGA print 数据缓冲区写入image
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
#include "PicSceneLoader.h"
|
||||
#include "picscene.h"
|
||||
#include "pictextitem.h"
|
||||
#include "PicImageItem.h"
|
||||
#include "PicDateItem.h"
|
||||
#include "PicScheduleShiftItem.h"
|
||||
#include "piccodeitem.h"
|
||||
#include "PicCounterItem.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamAttributes>
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <QScopedPointer>
|
||||
#include <cmath>
|
||||
|
||||
namespace {
|
||||
|
||||
PicTextItem* createSceneItem(SourceType sourceType)
|
||||
{
|
||||
switch (sourceType) {
|
||||
case IMAGE:
|
||||
return new PicImageItem();
|
||||
case DATETIME:
|
||||
return new PicDateItem();
|
||||
case SCHEDULE_SHIFT:
|
||||
return new PicScheduleShiftItem();
|
||||
case CODE:
|
||||
return new PicCodeItem();
|
||||
case COUNTER:
|
||||
return new PicCounterItem();
|
||||
case TEXT:
|
||||
case UNKNOWN:
|
||||
default:
|
||||
return new PicTextItem(nullptr, nullptr, sourceType);
|
||||
}
|
||||
}
|
||||
|
||||
SourceType sourceTypeFromAttrs(const QXmlStreamAttributes& attrs)
|
||||
{
|
||||
if (!attrs.hasAttribute("sourceType")) {
|
||||
return SourceType::UNKNOWN;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
int value = attrs.value("sourceType").toInt(&ok);
|
||||
if (!ok) {
|
||||
return SourceType::UNKNOWN;
|
||||
}
|
||||
|
||||
if (value < SourceType::UNKNOWN || value > SourceType::COUNTER) {
|
||||
return SourceType::UNKNOWN;
|
||||
}
|
||||
|
||||
return static_cast<SourceType>(value);
|
||||
}
|
||||
|
||||
bool parseVbFileElement(QXmlStreamReader& reader, PicScene* scene)
|
||||
{
|
||||
float posX = 0.0f;
|
||||
float posY = 0.0f;
|
||||
bool condition = false;
|
||||
int catchStartValue = -1;
|
||||
int catchValue = -1;
|
||||
QXmlStreamAttributes itemAttrs;
|
||||
QString htmlCData;
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = reader.readNext();
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
const QString elementName = reader.name().toString();
|
||||
if (elementName == "pointer_x") {
|
||||
posX = reader.readElementText().toDouble();
|
||||
} else if (elementName == "pointer_y") {
|
||||
posY = reader.readElementText().toDouble();
|
||||
} else if (elementName == "Condition") {
|
||||
condition = reader.readElementText().toInt() != 0;
|
||||
} else if (elementName == "CatchStartValue") {
|
||||
catchStartValue = reader.readElementText().toInt();
|
||||
} else if (elementName == "CatchValue") {
|
||||
catchValue = reader.readElementText().toInt();
|
||||
} else if (elementName == "itemAttrs") {
|
||||
itemAttrs = reader.attributes();
|
||||
reader.skipCurrentElement();
|
||||
} else if (elementName == "html_src") {
|
||||
reader.skipCurrentElement();
|
||||
} else {
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
} else if (reader.isCDATA()) {
|
||||
htmlCData += reader.text().toString();
|
||||
} else if (token == QXmlStreamReader::EndElement && reader.name() == "VBfile") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SourceType sourceType = sourceTypeFromAttrs(itemAttrs);
|
||||
PicTextItem* item = createSceneItem(sourceType);
|
||||
if (!item) {
|
||||
qWarning() << "PicSceneLoader: skip invalid VBfile item";
|
||||
return true;
|
||||
}
|
||||
|
||||
item->setAttrs(itemAttrs);
|
||||
item->setPos(posX, posY);
|
||||
item->SpecialConditions = condition;
|
||||
item->CatchCnt1StartValue = catchStartValue;
|
||||
item->CatchCnt1CurrValue = catchValue;
|
||||
|
||||
if (!htmlCData.isEmpty()) {
|
||||
item->setHtml(htmlCData);
|
||||
}
|
||||
|
||||
scene->addItem(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace PicSceneLoader {
|
||||
|
||||
PicScene* createSceneFromFile(const QString& xmlFilename)
|
||||
{
|
||||
QFile file(xmlFilename);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qWarning() << "PicSceneLoader: failed to open" << xmlFilename << file.errorString();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QXmlStreamReader reader(&file);
|
||||
PicScene* scene = new PicScene();
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
if (reader.isStartElement() && reader.name() == "VBfiles") {
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "VBfile") {
|
||||
if (!parseVbFileElement(reader, scene)) {
|
||||
delete scene;
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError()) {
|
||||
qWarning() << "PicSceneLoader: XML parse error" << reader.errorString()
|
||||
<< "at" << reader.lineNumber() << ":" << reader.columnNumber();
|
||||
delete scene;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
QImage previewSceneFromFile(const QString &xmlFilename)
|
||||
{
|
||||
QScopedPointer<PicScene> scene(createSceneFromFile(xmlFilename));
|
||||
if (!scene) {
|
||||
return QImage();
|
||||
}
|
||||
|
||||
QRectF contentRect = scene->itemsBoundingRect();
|
||||
if (!contentRect.isValid() || contentRect.isEmpty()) {
|
||||
return QImage(1, 1, QImage::Format_ARGB32_Premultiplied);
|
||||
}
|
||||
|
||||
QSize imageSize(qMax<int>(1, int(std::ceil(contentRect.width()))),
|
||||
qMax<int>(1, int(std::ceil(contentRect.height()))));
|
||||
QImage image(imageSize, QImage::Format_ARGB32_Premultiplied);
|
||||
image.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&image);
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
|
||||
scene->render(&painter, QRectF(QPointF(0, 0), imageSize), contentRect);
|
||||
painter.end();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
} // namespace PicSceneLoader
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef PICSCENELOADER_H
|
||||
#define PICSCENELOADER_H
|
||||
|
||||
#include <QImage>
|
||||
#include <QString>
|
||||
|
||||
class PicScene;
|
||||
|
||||
namespace PicSceneLoader {
|
||||
|
||||
PicScene* createSceneFromFile(const QString& xmlFilename);
|
||||
|
||||
QImage previewSceneFromFile(const QString& xmlFilename);
|
||||
|
||||
} // namespace PicSceneLoader
|
||||
|
||||
#endif // PICSCENELOADER_H
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "myview.h"
|
||||
#include <QWheelEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollBar>
|
||||
#include "picscene.h"
|
||||
#include <QDebug>
|
||||
MyView::MyView(QWidget *parent) :
|
||||
@@ -44,6 +46,63 @@ void MyView::ZoomIn(void)
|
||||
//// rotate(90); //视图旋转顺时针90度
|
||||
//}
|
||||
|
||||
void MyView::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
m_isPressing = true;
|
||||
const QPointF scenePos = mapToScene(event->pos());
|
||||
const bool hasSelectedItem = scene() && !scene()->selectedItems().isEmpty();
|
||||
m_pressOnItem = hasSelectedItem || (scene() && scene()->itemAt(scenePos, transform()) != nullptr);
|
||||
m_lastPanPoint = event->pos();
|
||||
}
|
||||
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void MyView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (m_isPressing && !m_pressOnItem && !m_isPanning) {
|
||||
const bool noSelectedItems = scene() && scene()->selectedItems().isEmpty();
|
||||
if (noSelectedItems) {
|
||||
QPoint delta = event->pos() - m_lastPanPoint;
|
||||
if (std::abs(delta.x()) >= MyView::PanStartDistance && std::abs(delta.x()) > std::abs(delta.y())) {
|
||||
m_isPanning = true;
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_isPanning) {
|
||||
int deltaX = event->pos().x() - m_lastPanPoint.x();
|
||||
if (deltaX != 0) {
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - deltaX);
|
||||
m_lastPanPoint = event->pos();
|
||||
}
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QGraphicsView::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void MyView::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (m_isPanning && event->button() == Qt::LeftButton) {
|
||||
m_isPanning = false;
|
||||
m_isPressing = false;
|
||||
setCursor(Qt::ArrowCursor);
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
m_isPressing = false;
|
||||
m_pressOnItem = false;
|
||||
}
|
||||
|
||||
QGraphicsView::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void MyView::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
//event->accept();
|
||||
|
||||
+9
-3
@@ -14,15 +14,21 @@ public:
|
||||
//char getzoomRatio(){return zoomRatio;}
|
||||
private:
|
||||
char zoomRatio;
|
||||
bool m_isPanning = false;
|
||||
bool m_isPressing = false;
|
||||
bool m_pressOnItem = false;
|
||||
QPoint m_lastPanPoint;
|
||||
static constexpr int PanStartDistance = 8;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
protected :
|
||||
// void wheelEvent(QWheelEvent *event);
|
||||
// void mousePressEvent(QMouseEvent *event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user