Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a55da4047 | ||
|
|
f723e26548 | ||
|
|
6d24c5b0f1 | ||
|
|
92a319b1de | ||
|
|
7939e8988f |
@@ -6,6 +6,10 @@
|
|||||||
#include <string.h> // for strstr
|
#include <string.h> // for strstr
|
||||||
#include <devguid.h>
|
#include <devguid.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <ShlObj.h>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QFileIconProvider>
|
||||||
|
#include <QFileInfo>
|
||||||
#pragma comment(lib, "setupapi.lib")
|
#pragma comment(lib, "setupapi.lib")
|
||||||
|
|
||||||
static void DisableComPort(const char* portName) {
|
static void DisableComPort(const char* portName) {
|
||||||
@@ -140,4 +144,41 @@ static void restartAsAdmin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 解析 .lnk 文件,获取目标路径
|
||||||
|
static QString getShortcutTarget(const QString& shortcutPath) {
|
||||||
|
HRESULT hres;
|
||||||
|
CoInitialize(NULL);
|
||||||
|
IShellLink* psl;
|
||||||
|
QString targetPath;
|
||||||
|
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
|
||||||
|
if (SUCCEEDED(hres)) {
|
||||||
|
IPersistFile* ppf;
|
||||||
|
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
|
||||||
|
if (SUCCEEDED(hres)) {
|
||||||
|
WCHAR wsz[MAX_PATH];
|
||||||
|
shortcutPath.toWCharArray(wsz);
|
||||||
|
wsz[shortcutPath.length()] = 0;
|
||||||
|
hres = ppf->Load(wsz, STGM_READ);
|
||||||
|
if (SUCCEEDED(hres)) {
|
||||||
|
char szTarget[MAX_PATH];
|
||||||
|
WIN32_FIND_DATA wfd;
|
||||||
|
if (SUCCEEDED(psl->GetPath(szTarget, MAX_PATH, &wfd, SLGP_UNCPRIORITY))) {
|
||||||
|
targetPath = QString::fromLocal8Bit(szTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ppf->Release();
|
||||||
|
}
|
||||||
|
psl->Release();
|
||||||
|
}
|
||||||
|
CoUninitialize();
|
||||||
|
return targetPath;
|
||||||
|
}
|
||||||
|
// 获取目标文件图标
|
||||||
|
static QIcon getFileIcon(const QString& filePath, const QSize& size) {
|
||||||
|
QFileIconProvider iconProvider;
|
||||||
|
QFileInfo fileInfo(filePath);
|
||||||
|
QIcon icon = iconProvider.icon(fileInfo);
|
||||||
|
QPixmap pixmap = icon.pixmap(size);
|
||||||
|
return QIcon(pixmap);
|
||||||
|
}
|
||||||
#pragma once
|
#pragma once
|
||||||
+2
-2
@@ -159,7 +159,7 @@ public:
|
|||||||
auto camera = _serviceManager->_cameraManager->getCamera(cameraName);
|
auto camera = _serviceManager->_cameraManager->getCamera(cameraName);
|
||||||
camera->clearCache();
|
camera->clearCache();
|
||||||
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
|
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
|
||||||
QString::number(address[batteryOffset].triggerAddr), sn, 1, camera->config.oriSaveFormat);//创建数据包
|
QString::fromStdString(cameraName), sn, 1, camera->config.oriSaveFormat);//创建数据包
|
||||||
camera->captureImage(data);//拍照
|
camera->captureImage(data);//拍照
|
||||||
data->saveObjectName = saveObjectName;
|
data->saveObjectName = saveObjectName;
|
||||||
generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法
|
generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法
|
||||||
@@ -233,7 +233,7 @@ public:
|
|||||||
auto camera = _serviceManager->_cameraManager->getCamera(cameraName);
|
auto camera = _serviceManager->_cameraManager->getCamera(cameraName);
|
||||||
camera->clearCache();
|
camera->clearCache();
|
||||||
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
|
std::shared_ptr <detData> data = _serviceManager->_detDataManager->createDetData(
|
||||||
QString::number(address[batteryOffset].triggerAddr), sn, 1, camera->config.oriSaveFormat);//创建数据包
|
QString::fromStdString(cameraName), sn, 1, camera->config.oriSaveFormat);//创建数据包
|
||||||
camera->captureImage(data);//拍照
|
camera->captureImage(data);//拍照
|
||||||
data->saveObjectName = saveObjectName;
|
data->saveObjectName = saveObjectName;
|
||||||
generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法
|
generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法
|
||||||
|
|||||||
@@ -219,37 +219,34 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
void saveOri(std::shared_ptr <detData> data) {
|
void saveImage(std::shared_ptr <detData> data) {
|
||||||
|
|
||||||
|
QString oriSavePath= genDirName(data, oriImg, data->_saveMode);//获取文件夹名
|
||||||
|
createDirectoryIfNotExists(oriSavePath);//不存在此文件夹则创建
|
||||||
if (data->oriImgs.size() != 0) {
|
if (data->oriImgs.size() != 0) {
|
||||||
|
|
||||||
QString fileSavePath = genDirName(data, oriImg, data->_saveMode);//获取文件夹名
|
|
||||||
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
|
|
||||||
std::vector<std::string>fileNames = genFileNames(data, oriImg);//按规则为文件创建命名
|
std::vector<std::string>fileNames = genFileNames(data, oriImg);//按规则为文件创建命名
|
||||||
std::shared_ptr<saveJob> job (new saveJob("[ORI_JOB]" + data->SNcode));
|
std::shared_ptr<saveJob> job (new saveJob("[ORI_JOB]" + data->SNcode));
|
||||||
packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(), fileNames, data->oriImgs);//打包数据
|
packageData(job->imgQueue, oriSavePath.toLocal8Bit().toStdString(), fileNames, data->oriImgs);//打包数据
|
||||||
saveThread.addJob(job);
|
saveThread.addJob(job);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
void saveRes(std::shared_ptr <detData> data) {
|
|
||||||
|
|
||||||
QString fileSavePath = genDirName(data, resImg, data->_saveMode);//获取文件夹名
|
QString resultSavePath = genDirName(data, resImg, data->_saveMode);//获取文件夹名
|
||||||
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
|
createDirectoryIfNotExists(resultSavePath);//不存在此文件夹则创建
|
||||||
std::shared_ptr<saveJob> job(new saveJob("[RES_JOB]"+ data->SNcode));
|
std::shared_ptr<saveJob> job(new saveJob("[RES_JOB]"+ data->SNcode));
|
||||||
//结果图保存
|
//结果图保存
|
||||||
if (data->resultImgs.size() != 0) {
|
if (data->resultImgs.size() != 0) {
|
||||||
std::vector<std::string>fileNames = genFileNames(data, resImg);//按规则为文件创建命名
|
std::vector<std::string>fileNames = genFileNames(data, resImg);//按规则为文件创建命名
|
||||||
packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(),fileNames, data->resultImgs);//打包数据
|
packageData(job->imgQueue, resultSavePath.toLocal8Bit().toStdString(),fileNames, data->resultImgs);//打包数据
|
||||||
}
|
}
|
||||||
//SEG原图
|
//SEG原图
|
||||||
if (data->segOriginImgs.size() != 0) {
|
if (data->segOriginImgs.size() != 0) {
|
||||||
std::vector<std::string>fileNames = genFileNames(data, segImg);//按规则为文件创建命名
|
std::vector<std::string>fileNames = genFileNames(data, segImg);//按规则为文件创建命名
|
||||||
packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(),fileNames, data->segOriginImgs);//打包数据
|
packageData(job->imgQueue, oriSavePath.toLocal8Bit().toStdString(), fileNames, data->segOriginImgs);//打包数据
|
||||||
}
|
}
|
||||||
//CLS原图
|
//CLS原图
|
||||||
if (data->clsOriginImgs.size() != 0) {
|
if (data->clsOriginImgs.size() != 0) {
|
||||||
std::vector<std::string>fileNames = genFileNames(data, clsImg);//按规则为文件创建命名
|
std::vector<std::string>fileNames = genFileNames(data, clsImg);//按规则为文件创建命名
|
||||||
packageData(job->imgQueue, fileSavePath.toLocal8Bit().toStdString(), fileNames, data->clsOriginImgs);//打包数据
|
packageData(job->imgQueue, oriSavePath.toLocal8Bit().toStdString(), fileNames, data->clsOriginImgs);//打包数据
|
||||||
}
|
}
|
||||||
saveThread.addJob(job, imgSaveThread::priority);
|
saveThread.addJob(job, imgSaveThread::priority);
|
||||||
//额外储存NG文件夹
|
//额外储存NG文件夹
|
||||||
|
|||||||
@@ -99,8 +99,8 @@ public:
|
|||||||
data->sqlVec.push_back({ "SN", data->SNcode });
|
data->sqlVec.push_back({ "SN", data->SNcode });
|
||||||
data->sqlVec.push_back({ "totalCt", std::to_string(data->algoTime) + "ms" });
|
data->sqlVec.push_back({ "totalCt", std::to_string(data->algoTime) + "ms" });
|
||||||
// 异步保存检测图像
|
// 异步保存检测图像
|
||||||
std::thread([this,data] {_imgSaveThreadManager->saveOri(data); }).detach();
|
std::thread([this,data] {_imgSaveThreadManager->saveImage(data); }).detach();
|
||||||
std::thread([this,data] {_imgSaveThreadManager->saveRes(data); }).detach();
|
//std::thread([this,data] {_imgSaveThreadManager->saveRes(data); }).detach();
|
||||||
}
|
}
|
||||||
#pragma region 注册回调函数
|
#pragma region 注册回调函数
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
// 通用的创建工具按钮函数实现
|
// 通用的创建工具按钮函数实现
|
||||||
bool createToolButton(const QString& iconPath, const QString& text,
|
bool createToolButton(const QString& iconPath, const QString& text,
|
||||||
std::function<void()> clickHandler,
|
std::function<void()> clickHandler,
|
||||||
const QSize& buttonSize = QSize(60, 60), const QSize& iconSize = QSize(30, 30)){
|
const QSize& buttonSize = QSize(100, 60), const QSize& iconSize = QSize(30, 30)){
|
||||||
|
|
||||||
// 参数验证
|
// 参数验证
|
||||||
if (iconPath.isEmpty() || text.isEmpty() || !clickHandler) {
|
if (iconPath.isEmpty() || text.isEmpty() || !clickHandler) {
|
||||||
@@ -105,10 +105,75 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
btn->setIcon(icon);
|
btn->setIcon(icon);
|
||||||
btn->setText(text);
|
btn->setText(text);
|
||||||
btn->setIconSize(iconSize);
|
btn->setIconSize(iconSize);
|
||||||
btn->setFixedSize(buttonSize.width() + 20, buttonSize.height() + 20); // 增加高度以容纳文字
|
btn->setFixedSize(buttonSize.width(), buttonSize.height()); // 增加高度以容纳文字
|
||||||
|
btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); // 文字在图标下方
|
||||||
|
|
||||||
|
// 设置按钮样式
|
||||||
|
btn->setStyleSheet(R"(
|
||||||
|
QToolButton {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
font-family: "微软雅黑";
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
QToolButton:hover {
|
||||||
|
background-color: black;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
|
||||||
|
btnLayout->addWidget(btn);
|
||||||
|
btnLayout->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
// 连接点击事件
|
||||||
|
if (!connect(btn, &QToolButton::clicked, clickHandler)) {
|
||||||
|
delete btn;
|
||||||
|
delete btnLayout;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加到按钮布局容器中
|
||||||
|
buttonsLayout->addLayout(btnLayout);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool createToolButton(QIcon icon, const QString& text,
|
||||||
|
std::function<void()> clickHandler,
|
||||||
|
const QSize& buttonSize = QSize(100, 60), const QSize& iconSize = QSize(30, 30)) {
|
||||||
|
|
||||||
|
// 参数验证
|
||||||
|
if (text.isEmpty() || !clickHandler) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建布局
|
||||||
|
QVBoxLayout* btnLayout = new QVBoxLayout();
|
||||||
|
if (!btnLayout) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
btnLayout->setSpacing(0);
|
||||||
|
btnLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// 使用 QToolButton 来实现图标在上文字在下的效果
|
||||||
|
QToolButton* btn = new QToolButton(this);
|
||||||
|
if (!btn) {
|
||||||
|
delete btnLayout;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置图标,检查图标是否加载成功
|
||||||
|
|
||||||
|
btn->setIcon(icon);
|
||||||
|
btn->setText(text);
|
||||||
|
btn->setIconSize(iconSize);
|
||||||
|
btn->setFixedSize(buttonSize.width(), buttonSize.height()); // 增加高度以容纳文字
|
||||||
btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); // 文字在图标下方
|
btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); // 文字在图标下方
|
||||||
|
|
||||||
// 设置按钮样式
|
// 设置按钮样式
|
||||||
@@ -364,7 +429,20 @@ public:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
#pragma region 读取bin目录下的tools文件夹并展示
|
||||||
|
{
|
||||||
|
std::vector<std::string> files;
|
||||||
|
fileManager::getAllFiles("./tools", files, "lnk");
|
||||||
|
for (auto& lnkPath : files) {
|
||||||
|
std::string fileName = fileManager::getFileName(lnkPath);
|
||||||
|
auto exePath = getShortcutTarget(QString::fromStdString(lnkPath));
|
||||||
|
auto icon = getFileIcon(exePath, QSize(30, 30));
|
||||||
|
_toolBarWidget->createToolButton(icon, QString::fromLocal8Bit(fileName.c_str()), [=]() {
|
||||||
|
QProcess::startDetached(exePath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#pragma endregion
|
||||||
vLayout->addWidget(_toolBarWidget);
|
vLayout->addWidget(_toolBarWidget);
|
||||||
|
|
||||||
vLayout->addWidget(&_ImageWidgetManager);
|
vLayout->addWidget(&_ImageWidgetManager);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <opencv.hpp>
|
#include <opencv.hpp>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QTimer>
|
||||||
#include <qmessagebox.h>
|
#include <qmessagebox.h>
|
||||||
#include <qmutex.h>
|
#include <qmutex.h>
|
||||||
#include <uiModule/components/fancyButton.h>
|
#include <uiModule/components/fancyButton.h>
|
||||||
@@ -302,6 +303,18 @@ class ImageWidget : public QWidget {
|
|||||||
public:
|
public:
|
||||||
QComboBox switchBox;
|
QComboBox switchBox;
|
||||||
QMutex switchViewerMutex;
|
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) {
|
ImageWidget(QWidget* parent = nullptr) : QWidget(parent) {
|
||||||
qRegisterMetaType<cv::Mat>("cv::Mat");
|
qRegisterMetaType<cv::Mat>("cv::Mat");
|
||||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||||
@@ -324,6 +337,28 @@ public:
|
|||||||
/* auto spaceItem = new QSpacerItem(100, 1);
|
/* auto spaceItem = new QSpacerItem(100, 1);
|
||||||
hLayout->addSpacerItem(spaceItem);*/
|
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 = new QLabel(u8"相机标签");
|
||||||
label->setAlignment(Qt::AlignLeft);
|
label->setAlignment(Qt::AlignLeft);
|
||||||
label->setFont(font);
|
label->setFont(font);
|
||||||
@@ -387,6 +422,32 @@ public:
|
|||||||
map.insert(name, QPixmap());
|
map.insert(name, QPixmap());
|
||||||
switchBox.addItem(name);
|
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:
|
public slots:
|
||||||
//combobox切换槽
|
//combobox切换槽
|
||||||
void switchViewType(QString name)
|
void switchViewType(QString name)
|
||||||
@@ -455,6 +516,71 @@ public slots:
|
|||||||
viewer->setImg(px);
|
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:
|
protected:
|
||||||
void wheelEvent(QWheelEvent* event) override {
|
void wheelEvent(QWheelEvent* event) override {
|
||||||
if (event->modifiers() & Qt::ControlModifier) {
|
if (event->modifiers() & Qt::ControlModifier) {
|
||||||
@@ -547,20 +673,35 @@ public:
|
|||||||
ImageWidgetList.push_back(ImageView);
|
ImageWidgetList.push_back(ImageView);
|
||||||
map.insert({ windowName,ImageView });
|
map.insert({ windowName,ImageView });
|
||||||
ImageView->setTitle(windowName);
|
ImageView->setTitle(windowName);
|
||||||
if (xPos <= 0 || yPos <= 0)
|
if (xPos < 0 || yPos < 0){
|
||||||
Layout->addWidget(ImageView);
|
Layout->addWidget(ImageView);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
|
// 指定位置布局
|
||||||
Layout->addWidget(ImageView, yPos, xPos);
|
Layout->addWidget(ImageView, yPos, xPos);
|
||||||
|
ImageView ->setParentGridLayout(Layout, yPos, xPos, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& viewer : viewers)
|
for (auto& viewer : viewers)
|
||||||
ImageView->createViewer(QString::fromStdString(viewer));
|
ImageView->createViewer(QString::fromStdString(viewer));
|
||||||
|
|
||||||
return ImageView;
|
return ImageView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateAllZoomButtonsVisibility() {
|
||||||
|
for (auto* widget : ImageWidgetList) {
|
||||||
|
widget->updateZoomButtonVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QGridLayout* Layout = new QGridLayout();
|
||||||
ImageWidgetManager()
|
ImageWidgetManager()
|
||||||
{
|
{
|
||||||
this->setLayout(Layout);
|
this->setLayout(Layout);
|
||||||
Layout->setContentsMargins(0, 0, 0, 0);
|
Layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
// 设置布局属性,允许窗口缩放
|
||||||
|
/*Layout->setColumnStretch(0, 1);
|
||||||
|
Layout->setColumnStretch(1, 1);
|
||||||
|
Layout->setColumnStretch(2, 1);*/
|
||||||
}
|
}
|
||||||
~ImageWidgetManager()
|
~ImageWidgetManager()
|
||||||
{
|
{
|
||||||
@@ -578,72 +719,47 @@ public:
|
|||||||
}
|
}
|
||||||
void adjustImageWidget() {
|
void adjustImageWidget() {
|
||||||
if (ImageWidgetList.isEmpty()) return;
|
if (ImageWidgetList.isEmpty()) return;
|
||||||
|
std::vector<std::vector<ImageWidget*>> vec(Layout->rowCount(), std::vector<ImageWidget*>(Layout->columnCount(),nullptr));
|
||||||
// 清除现有布局中的所有部件
|
for (auto& data : map) {
|
||||||
QLayoutItem* item;
|
vec[data.second->originalRow][data.second->originalColumn] = data.second;
|
||||||
while ((item = Layout->takeAt(0)) != nullptr) {
|
|
||||||
if (item->widget()) {
|
|
||||||
Layout->removeWidget(item->widget());
|
|
||||||
}
|
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
|
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) {
|
||||||
|
|
||||||
int total = ImageWidgetList.size();
|
vec[row][col - 1]->originalColumnSpan++;
|
||||||
|
Layout->removeWidget(vec[row][col - 1]);
|
||||||
// 计算最佳的网格布局行列数
|
Layout->addWidget(vec[row][col - 1],
|
||||||
int cols = static_cast<int>(std::ceil(std::sqrt(static_cast<double>(total))));
|
vec[row][col - 1]->originalRow,
|
||||||
int rows = static_cast<int>(std::ceil(static_cast<double>(total) / cols));
|
vec[row][col - 1]->originalColumn,
|
||||||
|
vec[row][col - 1]->originalRowSpan,
|
||||||
// 创建一个二维数组来跟踪布局占用情况
|
vec[row][col - 1]->originalColumnSpan);
|
||||||
QVector<QVector<bool>> occupied(rows, QVector<bool>(cols, false));
|
vec[row][col] = vec[row][col - 1];
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 如果左侧扩展不可行,尝试上方部件是否可以纵向扩展
|
else if (col < vec[row].size() - 1) {
|
||||||
else if (row > 0 && occupied[row-1][col]) {
|
if (vec[row][col + 1] != nullptr) {
|
||||||
int spanX = widgetSpans[row-1][col].x();
|
|
||||||
int spanY = widgetSpans[row-1][col].y();
|
vec[row][col + 1]->originalRow--;
|
||||||
QLayoutItem* item = Layout->itemAtPosition(row-1, col);
|
vec[row][col + 1]->originalColumnSpan++;
|
||||||
if (item && item->widget()) {
|
Layout->removeWidget(vec[row][col + 1]);
|
||||||
Layout->removeItem(item);
|
Layout->addWidget(vec[row][col + 1],
|
||||||
Layout->addWidget(item->widget(), row-1, col, spanY + 1, spanX);
|
vec[row][col + 1]->originalRow,
|
||||||
widgetSpans[row-1][col].setY(spanY + 1);
|
vec[row][col + 1]->originalColumn,
|
||||||
occupied[row][col] = true;
|
vec[row][col + 1]->originalRowSpan,
|
||||||
|
vec[row][col + 1]->originalColumnSpan);
|
||||||
|
vec[row][col] = vec[row][col + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新布局
|
// 更新布局
|
||||||
Layout->update();
|
Layout->update();
|
||||||
|
updateAllZoomButtonsVisibility();
|
||||||
}
|
}
|
||||||
QGridLayout* Layout = new QGridLayout();
|
|
||||||
private:
|
private:
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
QList< ImageWidget*>ImageWidgetList;
|
QList< ImageWidget*>ImageWidgetList;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <581_YiCiZhuYe_canye.h>
|
#include <581_YiCiZhuYe_canye.h>
|
||||||
|
|
||||||
void exceptionResume(std::shared_ptr<detData> data, canyeParams* _detParams, sx_581_address address) {
|
void exceptionResume(std::shared_ptr<detData> data, canyeParams* _detParams, sx_581_address address,QString why = "") {
|
||||||
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode);
|
qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode)<< why;
|
||||||
cv::Mat Paint;
|
cv::Mat Paint;
|
||||||
data->oriImgs[0].copyTo(Paint);
|
data->oriImgs[0].copyTo(Paint);
|
||||||
if (Paint.channels() == 1)
|
if (Paint.channels() == 1)
|
||||||
@@ -18,7 +18,7 @@ bool yizhuCanYe(std::shared_ptr<detData> data, canyeParams* _detParams, sx_581_a
|
|||||||
{
|
{
|
||||||
if (!_detParams->DOGLIVE)
|
if (!_detParams->DOGLIVE)
|
||||||
{
|
{
|
||||||
exceptionResume(data, _detParams, address);
|
exceptionResume(data, _detParams, address,"未插加密狗");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -66,7 +66,7 @@ bool yizhuCanYe(std::shared_ptr<detData> data, canyeParams* _detParams, sx_581_a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CATCH_EXCEPTIONS
|
CATCH_EXCEPTIONS
|
||||||
exceptionResume(data, _detParams, address);
|
exceptionResume(data, _detParams, address,"检测程序异常");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
Reference in New Issue
Block a user