This commit is contained in:
2025-10-15 11:19:49 +08:00
parent 7939e8988f
commit 92a319b1de
+157 -60
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
@@ -12,6 +12,7 @@
#include <opencv.hpp>
#include <QMenu>
#include <QAction>
#include <QTimer>
#include <qmessagebox.h>
#include <qmutex.h>
#include <uiModule/components/fancyButton.h>
@@ -302,6 +303,18 @@ class ImageWidget : public QWidget {
public:
QComboBox switchBox;
QMutex switchViewerMutex;
//缩放状态相关
QPushButton* zoombtn;
bool isZoomed = false;
QSize originalSize;
QPoint originalPosition;
QGridLayout* parentGridLayout = nullptr;
int originalRow = -1;
int originalColumn = -1;
int originalRowSpan = 1;
int originalColumnSpan = 1;
ImageWidget(QWidget* parent = nullptr) : QWidget(parent) {
qRegisterMetaType<cv::Mat>("cv::Mat");
QVBoxLayout* layout = new QVBoxLayout(this);
@@ -324,6 +337,28 @@ public:
/* auto spaceItem = new QSpacerItem(100, 1);
hLayout->addSpacerItem(spaceItem);*/
zoombtn = new QPushButton();
zoombtn->setFixedSize(16, 16);
zoombtn
->setStyleSheet(
R"(
QPushButton {
background-color: rgba(0, 0, 0, 0.5);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 3px;
}
QPushButton:hover {
background-color: rgba(0, 0, 0, 0.7);
border: 1px solid rgba(255, 255, 255, 0.5);
}
)"
);
zoombtn->setIcon(QPixmap(":icon/icon/fullscreen.png"));
zoombtn->setToolTip("放大窗口");
hLayout->addWidget(zoombtn);
connect(zoombtn, &QPushButton::clicked, this, &ImageWidget::toggleZoom);
label = new QLabel(u8"相机标签");
label->setAlignment(Qt::AlignLeft);
label->setFont(font);
@@ -387,6 +422,32 @@ public:
map.insert(name, QPixmap());
switchBox.addItem(name);
}
//设置父网格布局和位置信息
void setParentGridLayout(QGridLayout* gridLayout, int row, int column, int rowSpan, int columnSpan) {
parentGridLayout = gridLayout;
originalRow = row;
originalColumn = column;
originalRowSpan = rowSpan;
originalColumnSpan = columnSpan;
originalSize = this->size();
}
void updateZoomButtonVisibility() {
if (parentGridLayout) {
int rowCount = parentGridLayout->rowCount();
int columnCount = parentGridLayout->columnCount();
if (rowCount < 3 && columnCount < 3) {
zoombtn->hide();
}
else {
zoombtn->show();
}
}
}
public slots:
//combobox切换槽
void switchViewType(QString name)
@@ -455,6 +516,71 @@ public slots:
viewer->setImg(px);
}
}
//缩放
void toggleZoom() {
if (!parentGridLayout) return;
if (!isZoomed) {
zoomIn();// 放大
}
else {
zoomOut();//缩小
}
}
// 放大窗口
void zoomIn() {
if (isZoomed) return;
if (!parentGridLayout) return;
// 保存原始状态
originalSize = this->size();
// 在网格布局中重新放置,占据更多空间
parentGridLayout->removeWidget(this);
//计算父布局的总行数和总列数
int maxRowSpan = parentGridLayout->rowCount();// 父布局总行数
int maxColSpan = parentGridLayout->columnCount();// 父布局总列数
//放大后的跨度
int zoomColSize = maxColSpan - 1;
int zoomRowSize = maxRowSpan - 1;
if (originalRow >= zoomRowSize -1 || originalColumn >= zoomColSize -1) {
int x = qMax(0, originalRow - (zoomRowSize - 1));
int y = qMax(0, originalColumn - (zoomColSize - 1));
parentGridLayout->addWidget(this, x, y, zoomRowSize, zoomColSize);
}
else{
parentGridLayout->addWidget(this, originalRow, originalColumn, zoomRowSize, zoomColSize);
}
this->raise();
// 更新按钮状态
isZoomed = true;
zoombtn->setIcon(QIcon(":/icon/icon/fullscreen-exit.png"));
zoombtn->setToolTip("缩小窗口");
// 强制更新布局
parentGridLayout->update();
this->update();
}
// 缩小窗口
void zoomOut() {
if (!isZoomed) return;
// 恢复原始布局位置
parentGridLayout->removeWidget(this);
parentGridLayout->addWidget(this, originalRow, originalColumn, originalRowSpan, originalColumnSpan);
//更新按钮状态
isZoomed = false;
zoombtn->setIcon(QIcon(":/icon/icon/fullscreen.png"));
zoombtn->setToolTip("放大窗口");
//强制更新布局
parentGridLayout->update();
this->update();
}
protected:
void wheelEvent(QWheelEvent* event) override {
if (event->modifiers() & Qt::ControlModifier) {
@@ -547,20 +673,35 @@ public:
ImageWidgetList.push_back(ImageView);
map.insert({ windowName,ImageView });
ImageView->setTitle(windowName);
if (xPos <= 0 || yPos <= 0)
if (xPos == -1 || yPos == -1){
Layout->addWidget(ImageView);
else
}
else {
// 指定位置布局
Layout->addWidget(ImageView, yPos, xPos);
ImageView ->setParentGridLayout(Layout, yPos, xPos, 1, 1);
}
for (auto& viewer : viewers)
ImageView->createViewer(QString::fromStdString(viewer));
return ImageView;
}
void updateAllZoomButtonsVisibility() {
for (auto* widget : ImageWidgetList) {
widget->updateZoomButtonVisibility();
}
}
QGridLayout* Layout = new QGridLayout();
ImageWidgetManager()
{
this->setLayout(Layout);
Layout->setContentsMargins(0, 0, 0, 0);
// 设置布局属性,允许窗口缩放
/*Layout->setColumnStretch(0, 1);
Layout->setColumnStretch(1, 1);
Layout->setColumnStretch(2, 1);*/
}
~ImageWidgetManager()
{
@@ -578,72 +719,28 @@ public:
}
void adjustImageWidget() {
if (ImageWidgetList.isEmpty()) return;
// 清除现有布局中的所有部件
QLayoutItem* item;
while ((item = Layout->takeAt(0)) != nullptr) {
if (item->widget()) {
Layout->removeWidget(item->widget());
}
delete item;
std::vector<std::vector<ImageWidget*>> vec(Layout->rowCount(), std::vector<ImageWidget*>(Layout->columnCount(),nullptr));
for (auto& data : map) {
vec[data.second->originalRow][data.second->originalColumn] = data.second;
}
int total = ImageWidgetList.size();
// 计算最佳的网格布局行列数
int cols = static_cast<int>(std::ceil(std::sqrt(static_cast<double>(total))));
int rows = static_cast<int>(std::ceil(static_cast<double>(total) / cols));
// 创建一个二维数组来跟踪布局占用情况
QVector<QVector<bool>> occupied(rows, QVector<bool>(cols, false));
QVector<QVector<QPoint>> widgetSpans(rows, QVector<QPoint>(cols, QPoint(1, 1)));
// 首先按基本网格放置部件
int index = 0;
for (int row = 0; row < rows && index < total; ++row) {
for (int col = 0; col < cols && index < total; ++col) {
Layout->addWidget(ImageWidgetList[index], row, col);
occupied[row][col] = true;
index++;
}
}
// 查找和填充空缺
for (int row = 0; row < rows; ++row) {
for (int col = 0; col < cols; ++col) {
if (!occupied[row][col]) {
// 优先检查左侧部件是否可以横向扩展
if (col > 0 && occupied[row][col-1]) {
int spanX = widgetSpans[row][col-1].x();
int spanY = widgetSpans[row][col-1].y();
QLayoutItem* item = Layout->itemAtPosition(row, col-1);
if (item && item->widget()) {
Layout->removeItem(item);
Layout->addWidget(item->widget(), row, col-1, spanY, spanX + 1);
widgetSpans[row][col-1].setX(spanX + 1);
occupied[row][col] = true;
for (int row = 0; row < vec.size(); row++) {
for (int col = 0; col < vec[row].size(); col++) {
if (vec[row][col] == nullptr) {
if (col > 0) {
if (vec[row][col - 1] != nullptr) {
Layout->span
}
}
// 如果左侧扩展不可行,尝试上方部件是否可以纵向扩展
else if (row > 0 && occupied[row-1][col]) {
int spanX = widgetSpans[row-1][col].x();
int spanY = widgetSpans[row-1][col].y();
QLayoutItem* item = Layout->itemAtPosition(row-1, col);
if (item && item->widget()) {
Layout->removeItem(item);
Layout->addWidget(item->widget(), row-1, col, spanY + 1, spanX);
widgetSpans[row-1][col].setY(spanY + 1);
occupied[row][col] = true;
}
else {
}
}
}
}
// 更新布局
Layout->update();
updateAllZoomButtonsVisibility();
}
QGridLayout* Layout = new QGridLayout();
private:
QMutex mutex;
QList< ImageWidget*>ImageWidgetList;