QT界面中的区域以及图像大小,想随着QT界面的放大缩小变化,如何实现?
原始界面
原始界面ui文本长这样:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="processButton">
<property name="geometry">
<rect>
<x>100</x>
<y>360</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>处理图像</string>
</property>
</widget>
<widget class="QScrollArea" name="scrollArea">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>391</width>
<height>241</height>
</rect>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>389</width>
<height>239</height>
</rect>
</property>
<widget class="QLabel" name="originalLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>361</width>
<height>81</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</widget>
</widget>
<widget class="QScrollArea" name="scrollArea_2">
<property name="geometry">
<rect>
<x>390</x>
<y>10</y>
<width>411</width>
<height>241</height>
</rect>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>409</width>
<height>239</height>
</rect>
</property>
<widget class="QLabel" name="processedLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>391</width>
<height>81</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</widget>
</widget>
<widget class="QPushButton" name="loadButton">
<property name="geometry">
<rect>
<x>100</x>
<y>320</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>加载图像</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
原始代码
mainwindow.cpp
具体如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <opencv2/opencv.hpp>
#include <QImage>
#include <QPixmap>
#include <QFileDialog>
#include <QMessageBox>
using namespace cv;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->loadButton, &QPushButton::clicked, this, &MainWindow::loadImage);
connect(ui->processButton, &QPushButton::clicked, this, &MainWindow::processImage);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::loadImage()
{
QString fileName = QFileDialog::getOpenFileName(this, "Open Image File", "", "Image Files (*.png *.jpg *.bmp)");
if (!fileName.isEmpty()) {
src = imread(fileName.toStdString());
if (!src.empty()) {
QImage qimg(src.data, src.cols, src.rows, src.step, QImage::Format_BGR888);
ui->originalLabel->setPixmap(QPixmap::fromImage(qimg));
}
}
}
void MainWindow::processImage()
{
try {
if (src.empty()) throw std::runtime_error("No image loaded.");
Mat denoised, gray, laplacian, sharpened;
fastNlMeansDenoisingColored(src, denoised, 10, 10, 7, 21);
cvtColor(denoised, gray, COLOR_BGR2GRAY);
Laplacian(gray, laplacian, CV_16S, 3);
convertScaleAbs(laplacian, laplacian);
// Convert denoised to grayscale to match the channel number
Mat denoisedGray;
cvtColor(denoised, denoisedGray, COLOR_BGR2GRAY);
addWeighted(denoisedGray, 1, laplacian, 0.3, 0, sharpened);
QImage qimg(sharpened.data, sharpened.cols, sharpened.rows, sharpened.step, QImage::Format_Grayscale8);
ui->processedLabel->setPixmap(QPixmap::fromImage(qimg));
} catch (const std::exception &e) {
QMessageBox::critical(this, "Error", e.what());
} catch (...) {
QMessageBox::critical(this, "Error", "An unknown error occurred.");
}
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QImage>
#include <opencv2/opencv.hpp>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void loadImage();
void processImage();
private:
Ui::MainWindow *ui;
cv::Mat src;
};
#endif // MAINWINDOW_H
.pro文件
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
TRANSLATIONS += \
ceshi_qingxiceng_zh_CN.ts
CONFIG += lrelease
CONFIG += embed_translations
INCLUDEPATH += D:/Qt_project/ceshi_qingxiceng/opencv/include
LIBS += -LD:/Qt_project/ceshi_qingxiceng/opencv/x64/vc16/lib \
-lopencv_core455 \
-lopencv_imgproc455 \
-lopencv_photo455 \
-lopencv_highgui455 \
-lopencv_imgcodecs455
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
区域大小调整
要使界面中的区域大小随着窗口的放大缩小而变化,需要使用适当的布局管理。我们可以使用布局管理器(如 QVBoxLayout
、QHBoxLayout
、QGridLayout
等)来组织窗口中的小部件,而不是直接设置它们的几何属性。
以下是修改后的 .ui
文件,并添加了一些必要的布局管理以实现自动调整大小:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>388</width>
<height>239</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="originalLabel">
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollArea_2">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>388</width>
<height>239</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="processedLabel">
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="loadButton">
<property name="text">
<string>加载图像</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="processButton">
<property name="text">
<string>处理图像</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
解释
- 布局管理器:
- 使用
QVBoxLayout
和QHBoxLayout
来组织窗口中的小部件。 verticalLayout
将整个窗口分为两个部分:上半部分为图像显示区域,下半部分为按钮区域。horizontalLayout
用于在上半部分放置两个QScrollArea
,分别显示原始图像和处理后的图像。horizontalLayout_2
用于在下半部分放置两个按钮。
- 使用
QScrollArea
和QLabel
:- 使用
QScrollArea
来包含QLabel
,使得图像可以自动调整大小并在滚动区域内显示。 QLabel
的alignment
属性设置为Qt::AlignCenter
,以确保图像居中显示。
- 使用
调整图像大小
在你的代码中,当加载或处理图像后,需要调整 QLabel
中显示的图像尺寸,以适应 QScrollArea
的大小。你可以使用 QImage::scaled
方法来实现这一点。
void MainWindow::loadImage()
{
try {
QString fileName = QFileDialog::getOpenFileName(this, "Open Image File", "", "Image Files (*.png *.jpg *.bmp)");
if (!fileName.isEmpty()) {
src = imread(fileName.toStdString());
if (!src.empty()) {
QImage qimg(src.data, src.cols, src.rows, src.step, QImage::Format_BGR888);
QImage scaledImg = qimg.scaled(ui->originalLabel->size(), Qt::KeepAspectRatio);
ui->originalLabel->setPixmap(QPixmap::fromImage(scaledImg));
} else {
throw std::runtime_error("Failed to load image.");
}
}
} catch (const std::exception &e) {
QMessageBox::critical(this, "Error", e.what());
} catch (...) {
QMessageBox::critical(this, "Error", "An unknown error occurred.");
}
}
void MainWindow::processImage()
{
try {
if (src.empty()) throw std::runtime_error("No image loaded.");
Mat denoised, gray, laplacian, sharpened;
fastNlMeansDenoisingColored(src, denoised, 10, 10, 7, 21);
cvtColor(denoised, gray, COLOR_BGR2GRAY);
Laplacian(gray, laplacian, CV_16S, 3);
convertScaleAbs(laplacian, laplacian);
Mat denoisedGray;
cvtColor(denoised, denoisedGray, COLOR_BGR2GRAY);
addWeighted(denoisedGray, 1, laplacian, 0.3, 0, sharpened);
QImage qimg(sharpened.data, sharpened.cols, sharpened.rows, sharpened.step, QImage::Format_Grayscale8);
QImage scaledImg = qimg.scaled(ui->processedLabel->size(), Qt::KeepAspectRatio);
ui->processedLabel->setPixmap(QPixmap::fromImage(scaledImg));
} catch (const std::exception &e) {
QMessageBox::critical(this, "Error", e.what());
} catch (...) {
QMessageBox::critical(this, "Error", "An unknown error occurred.");
}
}
通过这些改动,你的界面和图像将能够随着窗口的放大缩小而自动调整大小。