Files
eUi/src/launcher/GUI/uiModule/uiModule_imageView.h
T
2025-06-11 10:00:09 +08:00

462 lines
14 KiB
C++

#pragma once
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QPixmap>
#include <QWheelEvent>
#include <QKeyEvent>
#include <opencv.hpp>
#include <QMenu>
#include <QAction>
#include <qmessagebox.h>
#include <qmutex.h>
#include <uiModule/components/fancyButton.h>
#include "qscrollbar.h"
#include "global.h"
#include <qqueue.h>
#include <qthread.h>
#include <qcombobox.h>
#include <qmutex.h>
#include <qmap.h>
#include <qbuffer.h>
#include <qimagewriter.h>
#include <qgraphicsproxywidget.h>
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 = std::max(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<float>(imageWidth) / FOV.width();
float scaleY = static_cast<float>(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<QGraphicsRectItem*>(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>(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<QPixmap>(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<QString,std::shared_ptr<QPixmap>> map;
std::map<QString, cv::Mat>imgShowMap;
};
//总
class ImageWidgetManager :public QWidget
{
public:
ImageWidget* createViewer(QString windowName, std::vector<std::string> 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_map<QString, ImageWidget*>map;
};
//预设