【问题标题】:How to resize QGraphicsView properly?如何正确调整 QGraphicsView 的大小?
【发布时间】:2018-05-06 14:46:57
【问题描述】:

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

MainWindow.hsn-p:

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 的测试结果:

【问题讨论】:

  • 你想让显示图像的项目垂直居中吗?
  • @eyllanesc 是的,我想垂直居中!现在,它在顶部。

标签: c++ qt qt5 qgraphicsview


【解决方案1】:

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

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

【讨论】:

  • 非常感谢!它似乎工作!我玩了一点代码并有一个问题。您能否解释一下为什么构造函数中的show(); 行很重要?我尝试将其注释掉或与下一行 (onButtonClicked();) 交换,但应用程序有点崩溃。
  • @LexSergeev 即使您指出大小、形状、颜色等,这些特征也不会立即应用,但在必要时,在您的情况下,QGraphicsView 的视口会在显示时更新。如果我的回答对您有所帮助,不要忘记将其标记为正确,这是最好的感谢方式。如果您不知道如何操作,请查看tour
  • 当然,答案对我有帮助,但我不明白它是如何工作的。例如,不清楚为什么顺序很重要。当然,我知道如何标记答案,谢谢你的笔记和旅游参考。但目前答案还很模糊。
  • @LexSergeev 顺序很重要,因为有必要建立视图的参数。正如我在之前的评论中所说,Qt出于效率的原因不会立即应用更改,例如,您表示您更改大小,您是否认为您可以在视图尚未显示时更新大小,所以您是如果它仍然没有大小,则要更改大小,Qt 所做的就是保存所需的大小并在必要时使用它。
  • @LexSergeev [cont] 在本例中是在 showEvent() 方法中,所以在执行该行之后你只看到正确的大小,我调用 show(),强制调用 showEvent(),只有当更改更新时才能正确绘制。
猜你喜欢
  • 1970-01-01
  • 2019-05-15
  • 1970-01-01
  • 2021-02-01
  • 2020-06-15
  • 1970-01-01
  • 1970-01-01
  • 2018-01-14
  • 1970-01-01
相关资源
最近更新 更多