QGraphicsView 窗口自适应Items

前言

在这里插入图片描述
绘制或导入的QGraphicsItem可能会很大或很小,我们想要根据现实窗口的大小自适应显示item,基于个人对QGraphics Scene、Graphics Item、Graphics View关系1的理解,发现一种方法使用可以解决需求。

一、原理介绍

在这里插入图片描述

如图所示情况下Item大于view显示的范围,那么我们需要按照一定比例缩放view来保证item完整显示,所用函数为:

m_view->fitInView(rectItem, Qt::KeepAspectRatio);

缩放模式选择配置参数说明如下所示(来自Qt Assistant)

在这里插入图片描述

但是直接按照items的外轮廓适应窗口会得到如下结果:

在这里插入图片描述

只适应了横向或纵向中的一个,如何让横向纵向同时适应呢?

在这里插入图片描述

使红色虚线框的横纵比和蓝色边框的横纵比相同,对红色边框宽或高适当放大,并依旧保持Item在中心位置再调用fitInview即可整体适应。

二、初始准备工作

新开一个QWidget,新建QGraphicsScene并添加QGraphicsView到QWidget,绘制一个特定形状的QGraphicsItem添加到QGraphicsScene中。

代码实现

新建窗口:

/****************************************************************
 Doc    :   main.cpp
 Author :   BingLee
 Date   :   2020-9-25
 Info   :   QGraphicsView auto fit.
 https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/

#include "mainwindow.h"
#include <QApplication>


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    w.resize(300, 300);

    return a.exec();
}

创建scene,view和item:

#include "mainwindow.h"
#include "mygraphicview.h"
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QMenu>

#include <math.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    m_vBoxLayout = new QVBoxLayout();
    m_centralWidget = new QWidget(this);
    setCentralWidget(m_centralWidget);
    m_centralWidget->setLayout(m_vBoxLayout);

    DrawDemo();
    this->setWindowTitle("Demo1");
}
void MainWindow::DrawDemo()
{
    QGraphicsScene *scene = new QGraphicsScene();   // 定义一个场景,设置背景色为白色
    scene->setBackgroundBrush(Qt::white);

    QPen pen;   // 定义一个画笔,设置画笔颜色和宽度
    pen.setColor(QColor(0, 160, 230));
    pen.setWidth(10);

    QGraphicsPolygonItem *polygonItem = new QGraphicsPolygonItem(); // 定义一个多边形图元
    QPolygonF polygon;
    polygon << QPointF(-100.0, -400.0) << QPointF(100.0, -400.0)
            << QPointF(200.0, 400.0) << QPointF(0.0, 400);
    polygonItem->setPolygon(polygon);
    pen.setColor(QColor(50, 120, 230));
    polygonItem->setPen(pen);
    polygonItem->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(polygonItem);   // 把多边形图元添加到场景

    m_view = new MyGraphicView(scene); // 定义一个视图,并把场景添加到视图
    m_view->setDragMode(QGraphicsView::RubberBandDrag); //设置view橡皮筋框选区域
    m_vBoxLayout->addWidget(m_view);
}

三、关键实现

自定义QGraphicsView

代码如下:

/****************************************************************
 Doc    :   mygraphicsview.h
 Author :   BingLee
 Date   :   2020-9-25
 Info   :   QGraphicsView auto fit.
 https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/

#ifndef MYGRAPHICVIEW_H
#define MYGRAPHICVIEW_H

#include <QGraphicsView>

class QGraphicsScene;
class QMouseEvent;
class MyGraphicView : public QGraphicsView
{
    Q_OBJECT
public:
    MyGraphicView(QGraphicsScene *scene);

public slots:
    void slot_zoomIn();//  { scale(1.2, 1.2); }
    void slot_zoomOut();// { scale(1/1.2, 1/1.2); }
    void slot_rotateLeft();// { rotate(-30); }
    void slot_rotateRight();// { rotate(30); }
    void slot_reset();

protected:
    virtual void mousePressEvent(QMouseEvent *event);

private:
    MyGraphicView* m_view;
};

#endif // MYGRAPHICVIEW_H

窗口自适应

代码如下:

void MyGraphicView::slot_reset()
{
    QRectF rectItem = scene()->itemsBoundingRect();
    QRectF rectView = m_view->rect();
    qreal ratioView = rectView.height() / rectView.width();
    qreal ratioItem = rectItem.height() / rectItem.width();
    if (ratioView > ratioItem)
    {
        rectItem.moveTop(rectItem.width()*ratioView - rectItem.height());
        rectItem.setHeight(rectItem.width()*ratioView);

        rectItem.setWidth(rectItem.width() * 1.2);
        rectItem.setHeight(rectItem.height() * 1.2);
    }
    else
    {
        rectItem.moveLeft(rectItem.height()/ratioView - rectItem.width());
        rectItem.setWidth(rectItem.height()/ratioView);

        rectItem.setWidth(rectItem.width() * 1.2);
        rectItem.setHeight(rectItem.height() * 1.2);
    }

    m_view->fitInView(rectItem, Qt::KeepAspectRatio);
}

在这里插入图片描述

总结

以上就是今天要讲的内容,本文简单介绍了QGraphcisView自适应窗口大小的实现.
如果本文帮助到你了的话请帮忙点赞、评论、关注三连哦~

源代码下载链接:QGraphicsViewAutofit.zip


  1. QGraphics Scene、Graphics Item、Graphics View关系及一个实例 ↩︎

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐