#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qscrollbar.h" #include "global.h" #include #include #include #include #include #include #include #include class ImageWidgetManager; //单画幅 class SonGraphicsView : public QGraphicsView { public: explicit SonGraphicsView(const QString& nameIn) : name(nameIn), scene(new QGraphicsScene(this)), //rectGroup(new QGraphicsItemGroup()), imageWidth(1), imageHeight(1), m_isPan(false), rightClicked(false) { QMutexLocker locker(&mutex); setDragMode(QGraphicsView::NoDrag); setInteractive(false); setEnabled(false); setObjectName("SonGraphicsView"); //scene->addItem(rectGroup); setScene(scene); setStyleSheet(R"( QGraphicsView#SonGraphicsView { background: transparent; background-image: url(:/icon/icon/waitting.png); background-repeat: no-repeat; background-position: center center; })"); } void setImg(const QPixmap& pixmap) { showImg(pixmap); } void resetImage() { QMutexLocker locker(&mutex); scene->clear(); pixmapItem = nullptr; setEnabled(false); } protected: void wheelEvent(QWheelEvent* event) override { if (scene->items().isEmpty()) return; QPoint numDegrees = event->angleDelta() / 8; if (!numDegrees.isNull()) { zoom(numDegrees / 15); centerOn(currentPos); } event->accept(); } void keyPressEvent(QKeyEvent* event) override { // 可以添加快捷键重置视图等操作 } void mousePressEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton) { togglePan(true, event->pos()); event->accept(); } else if (event->button() == Qt::RightButton) { startPos = mapToScene(event->pos()); rightClicked = true; //rectItem = new QGraphicsRectItem(QRectF(startPos, QSizeF(0, 0))); //rectItem->setPen(QPen(Qt::red, 5, Qt::DashLine)); //rectGroup->addToGroup(rectItem); update(); } else { event->ignore(); } } void mouseMoveEvent(QMouseEvent* event) override { currentPos = mapToScene(event->pos()); /* if (rightClicked && rectItem) { QPointF endPos = currentPos; qreal width = endPos.x() - startPos.x(); qreal height = endPos.y() - startPos.y(); rectItem->setRect(startPos.x(), startPos.y(), width, height); }*/ if (m_isPan) { pan(event->pos()); event->accept(); } else { event->ignore(); } } void mouseReleaseEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton) { togglePan(false); event->accept(); } //else if (event->button() == Qt::RightButton) { // rightClicked = false; // QPointF endPos = mapToScene(event->pos()); // qreal width = endPos.x() - startPos.x(); // qreal height = endPos.y() - startPos.y(); // deleteAllRect(); // if (width != 0 && height != 0) { // double scaleRate = getMax(width == 0 ? 1.0 : rect().width() / width,height == 0 ? 1.0 : rect().height() / height); // scale(scaleRate, scaleRate); // centerOn(startPos + QPointF(width / 2, height / 2)); // } //} else { event->ignore(); } } private: QString name; QGraphicsScene* scene = nullptr; //QGraphicsItemGroup* rectGroup = nullptr; //QGraphicsRectItem* rectItem = nullptr; // QLabel* imgLabel = nullptr; // 删除 QGraphicsPixmapItem* pixmapItem = nullptr; int imageWidth = 1; int imageHeight = 1; QPointF currentPos; QPointF startPos; bool rightClicked = false; bool m_isPan = false; QPoint m_prevPan; QMutex mutex; void showImg(const QPixmap& img) { QMutexLocker locker(&mutex); setEnabled(true); setMouseTracking(true); imageWidth = img.width(); imageHeight = img.height(); if (pixmapItem) { scene->removeItem(pixmapItem); delete pixmapItem; pixmapItem = nullptr; } pixmapItem = new QGraphicsPixmapItem(img); scene->addItem(pixmapItem); setSceneRect(img.rect()); fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio); } void zoom(const QPoint& factor) { QRectF FOV = mapToScene(rect()).boundingRect(); float scaleX = static_cast(imageWidth) / FOV.width(); float scaleY = static_cast(imageHeight) / FOV.height(); double currentScale = transform().m11(); if ((factor.y() > 0 && currentScale > 10.0) || (factor.y() < 0 && currentScale < 0.1)) return; scale(factor.y() > 0 ? 1.2 : 0.8, factor.y() > 0 ? 1.2 : 0.8); } void togglePan(bool pan, const QPoint& startPos = QPoint()) { if (pan == m_isPan) return; m_isPan = pan; m_prevPan = pan ? startPos : QPoint(0, 0); setCursor(pan ? Qt::ClosedHandCursor : Qt::ArrowCursor); } void pan(const QPoint& panTo) { QPoint delta = panTo - m_prevPan; m_prevPan = panTo; horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x()); verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y()); } void deleteAllRect() { /*if (!rectGroup) return; for (QGraphicsItem* item : rectGroup->childItems()) { QGraphicsRectItem* rect = qgraphicsitem_cast(item); if (rect) { rectGroup->removeFromGroup(rect); scene->removeItem(rect); delete rect; } }*/ } }; //切换窗口 在切换时用pixmap替换现有的以实现 class ImageWidget : public QWidget { Q_OBJECT public: fancyButton* switchBtn; QComboBox switchBox; QMutex switchBoxMutex; ImageWidget(QWidget* parent = nullptr) : QWidget(parent) { QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(5, 5, 5, 5); viewer = new SonGraphicsView(""); this->setMaximumSize(9999, 9999); QPalette palette; palette.setColor(QPalette::WindowText, Qt::white); QFont font("微软雅黑", 12, QFont::Bold); QHBoxLayout* hLayout = new QHBoxLayout(); label = new QLabel(u8"相机1"); label->setAlignment(Qt::AlignLeft); label->setFont(font); label->setPalette(palette); switchBox.setFont(font); switchBox.setPalette(palette); connect(&switchBox, &QComboBox::currentTextChanged, [=](QString type) { switchViewType(type); }); hLayout->addWidget(label); hLayout->addWidget(&switchBox); hLayout->setContentsMargins(0, 0, 0, 0); switchBtn = new fancyButton( 30, 30, QIcon(":/icon/icon/switch.png"), "切换结果图与原图" ); //hLayout->addWidget(switchBtn); layout->addLayout(hLayout); layout->addWidget(viewer); viewer->setDragMode(QGraphicsView::ScrollHandDrag); viewer->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); viewer->setRenderHint(QPainter::Antialiasing); viewer->setRenderHint(QPainter::SmoothPixmapTransform); viewer->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); viewer->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //item = new QGraphicsPixmapItem(); //scene->addItem(item); //view->fitInView(item, Qt::KeepAspectRatio); //view->setBackgroundBrush(QBrush(QColor(0, 0, 0))); //QPixmap backgroundImage(".//icon//watting.png"); // 替换为你的背景图片路径 //QGraphicsPixmapItem* backgroundItem = new QGraphicsPixmapItem(backgroundImage); //view->scene->addItem(backgroundItem); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &QWidget::customContextMenuRequested, this, &ImageWidget::showContextMenu); switchBtn->click();//切换结果图 } ~ImageWidget() { } void setTitle(const QString& text) { label->setText(text); } void createViewer(QString name) { map.insert(name, std::make_shared(QPixmap())); switchBox.addItem(name); } public slots: //combobox切换槽 void switchViewType(QString name) { QMutexLocker locker(&switchBoxMutex); auto& it = map.find(name); if (it == map.end()) { QString listName; for (auto it = map.begin(); it != map.end(); ++it)listName.append(it.key() + ","); qDebug() << u8"未找到对应的viewer,输入:" << name << u8" 现有:"<< listName; return; } if (it.value()->isNull() == false) viewer->setImg(*it.value()); else viewer->resetImage(); } void sendImg(QString type,QPixmap resImgInput) { std::string typer = type.toStdString(); auto& it = map.find(type); if (it == map.end()) { QString listName; for (auto it = map.begin(); it != map.end(); ++it)listName.append(it.key() + ","); qDebug() << u8"未找到对应的viewer,输入:" << type << u8" 现有:" << listName; return; } if (resImgInput.isNull()) { return; } it.value() = std::make_shared(resImgInput); QMutexLocker locker(&switchBoxMutex); if (type == switchBox.currentText()) showImgOnGraphicsView(resImgInput); } //无视当前类型直接显示 void showImgOnGraphicsView(QPixmap imageMat) { viewer->setImg(imageMat); } protected: void wheelEvent(QWheelEvent* event) override { if (event->modifiers() & Qt::ControlModifier) { double scaleFactor = 1.15; if (event->angleDelta().y() < 0) { scaleFactor = 1.0 / scaleFactor; } viewer->scale(scaleFactor, scaleFactor); event->accept(); } else { QWidget::wheelEvent(event); } } private: void paintEvent(QPaintEvent* event) override { QWidget::paintEvent(event); QPainter painter(this); painter.setPen(QPen(Qt::white, 1)); painter.drawRect(rect().adjusted(1, 1, -2, -2)); } void showContextMenu(const QPoint& pos) { //QMenu contextMenu(tr("Context Menu"), this); //QAction* action1 = new QAction(u8"切换原图/结果图", this); //contextMenu.addAction(action1); //QAction* selectedAction = contextMenu.exec(mapToGlobal(pos)); //if (selectedAction == action1) { // //switchOriAndRes();/以后改成存储当前图片 //} } int in = 0; QLabel* label; SonGraphicsView* viewer; QMap> map; std::mapimgShowMap; }; //总 class ImageWidgetManager :public QWidget { public: ImageWidget* createViewer(QString windowName, std::vector viewers, int xPos = -1, int yPos = -1) { ImageWidget* ImageView = new ImageWidget(); ImageWidgetList.push_back(ImageView); map.insert({ windowName,ImageView }); ImageView->setTitle(windowName); if (xPos == -1 || yPos == -1) Layout->addWidget(ImageView); else Layout->addWidget(ImageView, yPos, xPos); for (auto& viewer : viewers) ImageView->createViewer(QString::fromStdString(viewer)); return ImageView; } QGridLayout* Layout = new QGridLayout(); ImageWidgetManager() { this->setLayout(Layout); Layout->setContentsMargins(0, 0, 0, 0); } ~ImageWidgetManager() { } void disableAllSwitchBtn() { for (auto widget : ImageWidgetList) widget->switchBtn->hide(); } bool showImg(QPixmap img, QString nickName, QString _type ="null") { if (map.find(nickName) == map.end()) return false; if (_type == "null") map[nickName]->showImgOnGraphicsView(img); map[nickName]->sendImg(_type, img); return true; } bool new_showImg(QString windowName, QString _type,cv::Mat img) { if (map.find(windowName) == map.end()) { qDebug() << "未找到对应窗口 请检查配置文件 windowName->" << windowName << " _type->" << _type; return false; } //if (_type == "null") // map[_type]->showImgOnGraphicsView(img); //map[_type]->sendImg(_type, img); return true; } private: QMutex mutex; QList< ImageWidget*>ImageWidgetList; std::unordered_mapmap; }; //预设