代码之家  ›  专栏  ›  技术社区  ›  Lex Sergeev

如何正确调整QGraphicsView的大小?

  •  2
  • Lex Sergeev  · 技术社区  · 6 年前

    我尝试创建一个简单的应用程序 QGraphicsView 。应用程序可以在视图中加载不同比率的图形文件。我想实现以下功能:在应用程序窗口调整大小时,视图的内容也应该调整大小并居中。我不太了解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 : Test result for the <code>pic2.png</code>

    1 回复  |  直到 6 年前
        1
  •  2
  •   eyllanesc Yonghwan Shin    6 年前

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

    解决方案是在最终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);
    }