如何缩放图像/使其适合GraphicsView

时间:2019-10-10 07:43:25

标签: qt qgraphicsview

我阅读了很多帖子/主题,但无法正常工作。

我想使每个图像都适合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 :(得分:0)

这是一个基本的自定义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