2
votes

I try to create a simple application with QGraphicsView. The application can load graphical files with different ratios in the view. I would like to implement the following feature: on the application window resize, the content of the view should be also resized and centered. I do not know this part of the Qt well, so I can resize the content, but I cannot center it. How can I fix it?

MainWindow.h snippet:

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void resizeEvent(QResizeEvent *event) override;

public slots:
    void onButtonClicked();

private:
    bool m_flag = false;
    QGraphicsPixmapItem *m_item = nullptr;
    QGraphicsView *m_view = nullptr;
    QPixmap m_pixmap;
};

MainWindow.cpp:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    auto central = new QWidget(this);
    setCentralWidget(central);

    // layouts
    auto mainLayout = new QVBoxLayout;
    mainLayout->setAlignment(Qt::AlignTop);
    central->setLayout(mainLayout);

    // top layout
    auto topLayout = new QHBoxLayout;
    topLayout->setAlignment(Qt::AlignLeft);
    mainLayout->addLayout(topLayout);
    auto btn = new QPushButton(this);
    btn->setText("Test");
    connect(btn, &QPushButton::clicked, this, &MainWindow::onButtonClicked);
    topLayout->addWidget(btn);

    m_view = new QGraphicsView;
    mainLayout->addWidget(m_view);
    auto scene = new QGraphicsScene;
    m_view->setScene(scene);
    m_view->setMinimumSize(800, 600);
    m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    QString name = ":/pic1.jpg";
    m_pixmap = QPixmap{ name }.scaled(800, 600, Qt::KeepAspectRatio);
    m_item = scene->addPixmap(m_pixmap);
    m_view->viewport()->resize(m_pixmap.size());
}

void MainWindow::onButtonClicked()
{
    m_flag = !m_flag;
    QString name = m_flag ? ":/pic2.png" : ":/pic1.jpg";
    m_pixmap = QPixmap{ name }.scaled(m_view->size(), Qt::KeepAspectRatio);
    m_item->setPixmap(m_pixmap);
    m_view->fitInView(m_item, Qt::KeepAspectRatio);
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    QMainWindow::resizeEvent(event);
    m_view->fitInView(m_item, Qt::KeepAspectRatio);
}

Test result for the pic2.png: Test result for the <code>pic2.png</code>

1
Do you want the item that shows the image to be centered vertically? - eyllanesc
@eyllanesc Yes, I'd like to center it vertically! Now, it is on the top. - Lex Sergeev

1 Answers

2
votes

When an image is scaled, it is done with respect to the top left, so it will always look up if the height is smaller than the prefix or to the right if the width is smaller.

The solution is to repaint the scaled QPixmap in the middle of the final QPixmap.

const QSize pixmap_size{800, 600};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    auto central = new QWidget(this);
    setCentralWidget(central);

    // layouts
    auto mainLayout = new QVBoxLayout;
    mainLayout->setAlignment(Qt::AlignTop);
    central->setLayout(mainLayout);

    // top layout
    auto topLayout = new QHBoxLayout;
    topLayout->setAlignment(Qt::AlignLeft);
    mainLayout->addLayout(topLayout);
    auto btn = new QPushButton(this);
    btn->setText("Test");
    connect(btn, &QPushButton::clicked, this, &MainWindow::onButtonClicked);
    topLayout->addWidget(btn);

    m_view = new QGraphicsView;
    mainLayout->addWidget(m_view);
    auto scene = new QGraphicsScene;
    m_view->setScene(scene);
    m_view->setMinimumSize(pixmap_size);
    m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_pixmap = QPixmap(pixmap_size);
    m_pixmap.fill(Qt::transparent);
    m_item = new QGraphicsPixmapItem;
    m_view->scene()->addItem(m_item);
    show();
    onButtonClicked();
}

QPixmap MainWindow::createPixmap(const QString & filename, const QSize & size) const{

    QPixmap tmp = QPixmap{ filename }.scaled(size, Qt::KeepAspectRatio);
    QPixmap pixmap(size);
    pixmap.fill(Qt::transparent);
    QPainter p(&pixmap);
    QPoint point(QRect({}, size).center()-tmp.rect().center());
    p.drawPixmap(point, tmp);
    p.end();
    return pixmap;
}

void MainWindow::onButtonClicked()
{
    QString name = m_flag ? ":/pic2.png" : ":/pic1.jpg";
    m_item->setPixmap(createPixmap(name, pixmap_size));
    m_flag = !m_flag;
    m_view->fitInView(m_item, Qt::KeepAspectRatio);
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    QMainWindow::resizeEvent(event);
    m_view->fitInView(m_item, Qt::KeepAspectRatio);
}