QT, содержащий изменение размера окна изображения, останавливается каждые несколько пикселей - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть простое диалоговое окно с горизонтальной разметкой и QLable в нем. QLable содержит изображение. Я использую событие изменения размера, чтобы масштабировать это изображение, чтобы соответствовать размеру окна.

Я использовал код из примера QT. Заголовок:

#ifndef SCALEIMGDIALOG_H
#define SCALEIMGDIALOG_H

#include <QDialog>
#include <QLabel>

namespace Ui {
    class ScaleImgDialog;
}

class ScaleImgDialog : public QDialog
{
    Q_OBJECT

public:
    explicit ScaleImgDialog(QWidget *parent = 0);
    ~ScaleImgDialog();

protected:
    void resizeEvent(QResizeEvent *event) override;

private:
    Ui::ScaleImgDialog *ui;
    QPixmap testImg;
};

#endif

и исходный файл:

#include <QDebug>
#include "scaleImgDialog.h"
#include "ui_scaleImgDialog.h"
// main dialog window name is ScaleImgDialog ui_scaleImgDialog.h is generated automatically

ScaleImgDialog::ScaleImgDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ScaleImgDialog),
    testImg(":/images/testImg.jpeg")
{
    ui->setupUi(this);
    setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint);
    setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);
}

ScaleImgDialog::~ScaleImgDialog()
{
    delete ui;
}

void ScaleImgDialog::resizeEvent(QResizeEvent *)
{
    int newHeight = height();
    newHeight -= newHeight / 10;   // to prevent recursive resizing
    // Image heigh is much bigger then width so i use scaling by it
    ui->imgDisplayLabel->setPixmap(testImg.scaledToHeight(newHeight));
}

Увеличение размера работает хорошо. Но я столкнулся со следующей проблемой: когда я пытаюсь сделать окно меньше, оно не работает должным образом. Окно немного сжимается и изменение размера останавливается. При следующей попытке он немного сжимается и снова останавливается, и так далее: scaling problem И еще одна странная вещь: если вы не отпустите кнопку мыши, можно свободно изменить размер окна, пока оно не станет больше размера в начале. Кнопка «Развернуть окно» и возврат к предыдущему размеру также хорошо работает. free resize with pressed mouse button Как это исправить и сделать окно нормальным?

Ответы [ 2 ]

1 голос
/ 15 апреля 2020

Я бы вообще отбросил resizeEvent и переопределил paintEvent, чтобы использовать сам диалог в качестве устройства рисования и рисовать растровое изображение прямо на нем (что делает QLabel ненужным).

Что-то вроде:

#include <QPainter>
void ScaleImgDialog::paintEvent(QPaintEvent *event)
{
    QSize size(width() - 20, height() - 20);
    QPixmap pixmap = testImg.scaled(size, Qt::KeepAspectRatio);
    QRect area(rect().center() - pixmap.rect().center(), pixmap.rect().size());
    QPainter painter(this);
    painter.drawPixmap(area, pixmap);
}
0 голосов
/ 15 апреля 2020

Итак, похоже, я нашел ответ: использовать paintEvent () вместо изменения изображения в resizeEvent ():

class ScaleImgDialog : public QDialog {
    Q_OBJECT
public:
    explicit ScaleImgDialog(QWidget *parent = 0);
    ~ScaleImgDialog();

protected:
    void paintEvent(QPaintEvent *) override;
    void resizeEvent(QResizeEvent *) override;
private:
    Ui::ScaleImgDialog *ui;
    QPixmap testImg;

    int imageWidth;
    int imageHeight;

    int widthOffset;
    int heightOffset;
};

И Источник:

ScaleImgDialog::ScaleImgDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ScaleImgDialog),
    testImg(":/images/testImg.jpeg")
{
    ui->setupUi(this);
    setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint);
    setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);

    resizeEvent(nullptr);
}

ScaleImgDialog::~ScaleImgDialog()
{
    delete ui;
}

void ScaleImgDialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap(widthOffset, heightOffset, imageWidth, imageHeight, testImg);
}

void ScaleImgDialog::resizeEvent(QResizeEvent *) {
    QSize winSize = size();
    imageHeight = testImg.height();
    imageWidth  = testImg.width();

    if (testImg.height() > winSize.height()) {
        double heightRatio = (double)winSize.height() / testImg.height();
        imageHeight = (int)(testImg.height() * heightRatio);
        imageWidth  = (int)(testImg.width()  * heightRatio);
    }

    if (imageWidth > winSize.width()) {
        double widthRatio = (double)winSize.width() / imageWidth;
        imageHeight = (int)(imageHeight * widthRatio);
        imageWidth  = (int)(imageWidth  * widthRatio);
    }

    widthOffset  = winSize.width()  > imageWidth  ? ((winSize.width()  - imageWidth)  / 2) : 0;
    heightOffset = winSize.height() > imageHeight ? ((winSize.height() - imageHeight) / 2) : 0;
}

Так что все размеры вычисления выполняются в resizeEvent () (только тогда, когда они нужны), а само рисование происходит в paintEvent (). Этот код сохраняет соотношение размеров изображения и добавляет некоторые «пробелы» к границам, если необходимо:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...