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

区域大小调整

要使界面中的区域大小随着窗口的放大缩小而变化,需要使用适当的布局管理。我们可以使用布局管理器(如 QVBoxLayoutQHBoxLayoutQGridLayout 等)来组织窗口中的小部件,而不是直接设置它们的几何属性。

以下是修改后的 .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 用于在下半部分放置两个按钮。

  • QScrollAreaQLabel
    • 使用 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.");
    }
}

通过这些改动,你的界面和图像将能够随着窗口的放大缩小而自动调整大小。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深耕AI

谢谢鼓励~我将继续创作优质博文

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值