zoukankan      html  css  js  c++  java
  • Qt Examples

    QT自带例程Boxes使用QT Graphics View框架实现了2D图形和3D图形的混合渲染,综合性比较强,整合知识较多,值得学习。

    • 可以使用鼠标通过以下方式控制演示中的元素:
    • 按住鼠标左键的同时拖动鼠标可以旋转中心的Box。
    • 按住鼠标右键的同时拖动鼠标会旋转卫星箱。
    • 按住鼠标滚轮的同时拖动鼠标会旋转整个3D背景层。
    • 滚动鼠标滚轮可放大和缩小场景。

    选项窗格可用于微调Demo中的各种参数,包括颜色和像素着色器

     

    原始的在Widget中绘图通过重写paintEvent绘图响应函数,在其中使用QPainter来绘制。

    存在问题:

    1、 支持更多的图形时函数体会很长

    2、 移动操作图形时会很费劲

     

    Graphics View基本架构 

    Graphics View设计为管理大量2D图形,每一个2D图形都是一个item,其类为QGraphicsItem,QT内置了椭圆、矩形、直线、路径、图像、多边形和文本等基本item,可以通过派生QGraphicsItem来实现自定义的item,需要重写boundingRect以及paint函数。

     

    QGraphicsScene场景类包含所有的items,并且充当了一个view与items之间的接口桥梁。其拥有所有的图形item,可以传播绘制事件以及其他鼠标事件,而且提供了定位和管理图形item的各种方便的方法。

    场景初始化:

    QGraphicsScene *scene = new QGraphicsScene(this);

    scene->setSceneRect(-100, -100, 201, 201);

    场景中添加图形item:

    QGraphicsItem *item = scene->addRect(20, 20, 60, 60,

    QPen(Qt::red, 3),

    QBrush(Qt::green));

    QGraphicsView视图类widget充当了显示一个场景(场景是虚拟的)的视口。

    QGraphicsView *view = new QGraphicsView();

    QGraphicsScene *scene = setupScene();

    view->setScene(scene);

    为了能在场景中添加QT基本的图形组件(如PushButton、LineEdit等),QT提供了QGraphicsWidget类,为了进一步能使得图形item使用信号-槽的功能,QT又提供了QGraphicsObject类,非常的全面周到。

    QGraphicsProxyWidget *button = scene->addWidget(new QPushButton(tr("Click me!")));

    button->setPos(20, -30);

    图形项item交互操作

    图形项item的flags控制着它们如何可以与之互动

    • ItemIsMovable     -  一个方便的功能,原始鼠标事件方法让用户拖动
    • ItemIsSelectable   - 使用setSelected和QGraphicsScene :: setSelectionArea方法选择
    • ItemIsFocusable   - 获取键盘焦点

    场景通过BSP树管理图形项item,二进制空间分区树存储图形项于一棵树中,主要取决于它们在空间的位置。

     绘制各种2D图形项

     

    OpenGL渲染

    为了使用OpenGL渲染场景,需要更改view的视口widget:

    QGraphicsView *view = new QGraphicsView();

    view->setViewport(new QGLWidget);

                     

    绘制3D图形项

    一般地,图形项的绘制时在paint函数中使用QPainter来绘制,QPainer是绘制2D图形的类,而想绘制3D图形则需要使用OpenGL API,同样滴,在paint中是OpenGL命令代码如下:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    class MyItem : public QGraphicsItem
    {
    public:
        MyItem( QGraphicsItem *parent = 
    0 ) : QGraphicsItem(parent), w(200), h(200) {}
        
    void paint(QPainter *painter,
                   
    const QStyleOptionGraphicsItem *option,
                   QWidget *widget)
        {
            painter->drawRect(boundingRect());
            painter->beginNativePainting();
            
    /* Reset The Current Viewport And Perspective Transformation */

            glViewport(
    2020, w, h);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            gluPerspective(
    45.0f, (GLfloat)w / (GLfloat)h, 0.1f, 100.0f);
            glMatrixMode(GL_MODELVIEW);

            glLoadIdentity();
            glTranslatef(
    0.0f , 0.0f, -6.0f);
            glBegin(GL_TRIANGLES);
            glVertex3f(
    0.0f, 1.0f, 0.0f);
            glVertex3f(-
    1.0f, -1.0f, 0.0f);
            glVertex3f(
    1.0f, -1.0f, 0.0f);
            glEnd();

            painter->endNativePainting();
        }

        QRectF boundingRect () 
    const
        {
            
    return QRectF(2020, w, h);
        }

    private:
        
    int w, h;
    };

    绘制3D场景

    QGraphicsScene类提供了三个层面:背景层、图元层和前景层。上面2D图形项的绘制都是在图元层,是一个2D场景,如果我们想要实现一个3D场景,则可以在背景或前景层使用OpenGL命令,而底层是3D场景,上面是2D场景的情况很类似于我们玩网络游戏的情景,所以常在背景层绘制3D场景。各层绘制顺序:背景层-图元层-前景层

     C++ Code 
    1
    2
    3
    4
    5
    6
     
    void QGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)
    {
        painter->beginNativePainting();
        
    // do opengl draw…
        painter->endNativePainting();
    }

     

    Box例程学习:

    在Windows上安装的QT版本在build该例程时会出现错误,提示缺少opengl-desktop版本的支持,这是由于windows的发布版本QT没有使用该选项(只能重新编译QT源代码了),而linux版本使用了该选项可以正常构建运行。

    Qt Graphics View + OpenGL Render:

    QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers));

    widget->makeCurrent();

    Scene scene(1024, 768, maxTextureSize);

    GraphicsView view;

    view.setViewport(widget);

    view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);

    view.setScene(&scene);

    view.show();

     

    类图:

  • 相关阅读:
    关于初入.NET的那些事
    有趣的接口和抽象类
    类型转换的那些趣事(is和as)
    【项目实践】SpringBoot三招组合拳,手把手教你打出优雅的后端接口
    【项目实践】一文带你搞定Session和JWT的登录认证方式
    【项目实践】后端接口统一规范的同时,如何优雅得扩展规范
    羊车门问题简析
    对于python这门课程的一些想法、计划、期望
    Android 4.1果冻豆新特性详解
    使用include实现布局(layout)复用
  • 原文地址:https://www.cnblogs.com/MakeView660/p/11356638.html
Copyright © 2011-2022 走看看