Как увеличить / подогнать изображение к GraphicsView - PullRequest
0 голосов
/ 10 октября 2019

Я прочитал много постов / тем, но не могу заставить его работать.

Я бы хотел разместить каждое изображение в GraphicsView независимо от того, меньше оно или больше, чем представление.

Что не так?

void frmMain::on_btLoadImage_clicked()
{
    QGraphicsScene *scene;
    QPixmap image;

    QString imgPath = "O:/IMG_0001.JPG";
    QRectF sceneRect = ui->imgMain->sceneRect();

    image.load(imgPath);

    image.scaled (sceneRect.width (),sceneRect.height (), Qt::KeepAspectRatio, Qt::SmoothTransformation);

    scene = new QGraphicsScene(this);
    scene->addPixmap(image);
    scene->setSceneRect(sceneRect); //image.rect());

    //ui->imgMain->fitInView (scene->itemsBoundingRect(), Qt::KeepAspectRatio); //ui->imgMain->width (), ui->imgMain->height ());
    ui->imgMain->setScene(scene);
}

1 Ответ

0 голосов
/ 11 октября 2019

Вот базовая пользовательская реализация QGraphicsView, которая отображает одно изображение и сохраняет его размер / масштаб в соответствии с доступным пространством области просмотра. Обратите внимание, что изображение необходимо изменять каждый раз, когда изменяется размер области просмотра, поэтому проще всего переопределить сам QGraphicsView и изменить масштаб в resizeEvent(). Хотя это можно сделать внутри пользовательского QGraphicsScene. (Или, действительно, ряд других способов в зависимости от конкретных потребностей.)

Тот же метод можно использовать, чтобы сохранить QGraphicsWidget в качестве корневого элемента в сцене, чтобы всегда занимать все пространство. Затем макет можно использовать в виджете для выравнивания / изменения размера / расположения дочерних элементов и т. Д.

#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>

class GrpahicsImageView : public QGraphicsView
{
    Q_OBJECT
    public:
        using QGraphicsView::QGraphicsView;

    public slots:
        void setImage(const QString &imageFile)
        {
            if (m_imageFile != imageFile) {
                m_imageFile = imageFile;
                loadImage(viewport()->contentsRect().size());
            }
        }

        void setImageScaleMode(int mode)
        {
            if (m_scaleMode != Qt::AspectRatioMode(mode)) {
                m_scaleMode = Qt::AspectRatioMode(mode);
                if (m_item)
                    loadImage(viewport()->contentsRect().size());
            }
        }

        void loadImage(const QSize &size)
        {
            if (!scene())
                return;
            if (m_imageFile.isEmpty()) {
                // remove existing image, if any
                removeItem();
                return;
            }

            // Load image at original size
            QPixmap pm(m_imageFile);
            if (pm.isNull()) {
                // file not found/other error
                removeItem();
                return;
            }
            // Resize the image here.
            pm = pm.scaled(size, m_scaleMode, Qt::SmoothTransformation);
            if (createItem())
                m_item->setPixmap(pm);
        }

    protected:
        void resizeEvent(QResizeEvent *e) override
        {
            QGraphicsView::resizeEvent(e);
            if (!scene())
                return;
            // Set scene size to fill the available viewport size;
            const QRect sceneRect(viewport()->contentsRect());
            scene()->setSceneRect(sceneRect);
            // Keep the root item sized to fill the viewport and scene;
            if (m_item)
                loadImage(sceneRect.size());
        }

    private:
        bool createItem() {
            if (m_item)
                return true;
            if (!m_item && scene()) {
                m_item = new QGraphicsPixmapItem();
                scene()->addItem(m_item);
                return true;
            }
            return false;
        }

        void removeItem()
        {
            if (m_item) {
                if (scene())
                    scene()->removeItem(m_item);
                delete m_item;
                m_item = nullptr;
            }
        }

        Qt::AspectRatioMode m_scaleMode = Qt::KeepAspectRatio;
        QString m_imageFile;
        QGraphicsPixmapItem *m_item = nullptr;
};

Пример использования:

#include <QApplication>
#include <QtWidgets>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QDialog d;
    d.setLayout(new QVBoxLayout);
    d.resize(350, 350);

    GrpahicsImageView *view = new GrpahicsImageView(new QGraphicsScene, &d);

    QComboBox *imgCb = new QComboBox(&d);
    imgCb->addItems({
        "./so-logo.png",
        "./se-logo.png",
        "./su-logo.png"
    });

    QComboBox *scaleCb = new QComboBox(&d);
    scaleCb->addItems({
        "IgnoreAspectRatio",
        "KeepAspectRatio",
        "KeepAspectRatioByExpanding"
    });
    QHBoxLayout *cbLayout = new QHBoxLayout;
    cbLayout->setSpacing(9);
    cbLayout->addWidget(imgCb);
    cbLayout->addWidget(scaleCb);

    d.layout()->addItem(cbLayout);
    d.layout()->addWidget(view);

    QObject::connect(imgCb, QOverload<const QString &>::of(&QComboBox::currentIndexChanged), view, &GrpahicsImageView::setImage);
    QObject::connect(scaleCb, QOverload<int>::of(&QComboBox::currentIndexChanged), view, &GrpahicsImageView::setImageScaleMode);

    view->setImageScaleMode(scaleCb->currentIndex());
    view->setImage(imgCb->currentText());

    return d.exec();
}

https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png
https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/se-logo.png
https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/su-logo.png

enter image description here

...