如何正确调整 QGraphicsView 的大小?

How to resize QGraphicsView properly?

我尝试使用 QGraphicsView 创建一个简单的应用程序。应用程序可以在视图中加载不同比例的图形文件。我想实现以下功能:在应用程序 window 调整大小时,视图的内容也应调整大小并居中。我不太了解 Qt 的这一部分,所以我可以调整内容的大小,但我不能将它居中。我该如何解决?

MainWindow.h 片段:

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);
}

pic2.png 的测试结果:

缩放图像时,它是相对于左上角完成的,因此如果高度小于前缀,它将始终向上查找;如果宽度更小,它将始终向右查找。

解决方法是在最终的QPixmap中间重新绘制缩放后的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);
}