zoukankan      html  css  js  c++  java
  • Qt中OpenGL的初步使用

    结果预览:

    一.代码5个文件

    //glwidget.h
    #ifndef GLWIDGET_H
    #define GLWIDGET_H
    #include <QGLWidget>
    
    
    class GLWidget:public QGLWidget
    {
        Q_OBJECT
    public:
        explicit GLWidget(QWidget *parent = 0);
    
        int xRotation() const { return xRot; }
        int yRotation() const { return yRot; }
        int zRotation() const { return zRot; }
    
    signals:
        void xRotationChanged( int angle);
        void yRotationChanged( int angle);
        void zRotationChanged( int angle);
        public slots:
            void setXRotation(int angle);
            void setYRotation(int angle);
            void setZRotation(int angle);
    protected:
        void initializeGL();
        void paintGL();
        void resizeGL(int w, int h);
        void mousePressEvent(QMouseEvent *event);
        void mouseMoveEvent(QMouseEvent *event);
    
        private slots:
            void alwaysRotate();
            void drawTriangle();
    
    private:
        void normalizeAngle(int &angle);
        int xRot;
        int yRot;
        int zRot;
        QColor faceColors[4];
        QPoint lastPos;
        QColor qtGreen,    qtPurple;
    };
    
    #endif
    View Code
    //glwidget.cpp
    #include <QtGui>
    #include <QtOpenGL>
    #include<math.h>
    #include"glwidget.h"
    
    #ifndef GL_MULTISAMPLE
    #define GL_MULTISAMPLE  0x809D
    #endif
    
    GLWidget::GLWidget(QWidget *parent):QGLWidget(parent)
    {
    
        xRot = 0;
        yRot = 0;
        zRot = 0;
    
        faceColors[0] = Qt::red;
        faceColors[1] = Qt::green;
        faceColors[2] = Qt::blue;
        faceColors[3] = Qt::yellow;
    
        qtGreen = QColor::fromCmykF(0.40, 0.0, 1.0, 0.0);
        qtPurple = QColor::fromCmykF(0.39, 0.39, 0.0, 0.0);
    
        QTimer *timer = new QTimer(this);
        connect(timer , SIGNAL(timeout()), this,SLOT(alwaysRotate()));
        timer->start(70);
    }
    void GLWidget::initializeGL()
    {
        qglClearColor(qtPurple.dark());
        glShadeModel(GL_SMOOTH);
        glEnable(GL_DEPTH);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_MULTISAMPLE);
        glEnable(GL_CULL_FACE);
    
    }
    void GLWidget::paintGL()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glPushMatrix();
        drawTriangle();
        glPopMatrix();
    }
    
    void GLWidget::resizeGL(int w, int h)
    {
        int side = qMin(w,h);
        glViewport((width() - side) / 2, (height() - side)/2, side, side);
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum( -1.2, 1.2, -1.2, 1.2,5.0, 60.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0, 0.0, -40.0);
    
    }
    
    void GLWidget::mousePressEvent(QMouseEvent *event)
    {
        lastPos = event->pos();
    }
    void GLWidget::mouseMoveEvent(QMouseEvent *event)
    {
        int dx = event->x() - lastPos.x();
        int dy = event->y() - lastPos.y();
    
        if (event->buttons()&Qt::LeftButton)
        {
            setYRotation(yRot + 4*dy);
        } else if (event->buttons()&Qt::RightButton)
        {
            setZRotation(zRot + 4*dx);
        }
        lastPos = event->pos();
    }
    
    void GLWidget::drawTriangle()
    {
        static const GLfloat P1[3] = { 0.0, -1.0, +2.0 };
        static const GLfloat P2[3] = { +1.73, -1.0, -1.0 };
        static const GLfloat P3[3] = { -1.73, -1.0, -1.0 };
        static const GLfloat P4[3] = { 0.0, +2.0, 0.0 };
    
        static const GLfloat * const coords[4][3] = {
            { P1, P2, P3 }, { P1, P3, P4 }, { P1, P4, P2 }, { P2, P4, P3 }
        };
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslated( 0.0 , 0.0, -10.0);
        glRotatef(xRot, 1.0, 0.0, 0.0);
        glRotatef(yRot, 0.0, 1.0, 0.0);
        glRotatef(zRot, 0.0, 0.0,1.0);
    
    
        for (int i = 0; i != 4; ++i)
        {
            glBegin(GL_TRIANGLES);
            qglColor(faceColors[i]);
            for (int j = 0; j<3;++j)
                glVertex3f(coords[i][j][0], coords[i][j][1], coords[i][j][2]);
            glEnd();
        }
    
    }
    
    void GLWidget::normalizeAngle(int &angle)
    {
        while (angle<0)
            angle +=360*16;
        while (angle>360*16)
            angle -=360*16;
    }
    
    void GLWidget::setXRotation(int angle)
    {
        normalizeAngle(angle);
        if ( angle!=xRot)
        {
            xRot = angle;
            emit xRotationChanged(angle);
            updateGL();
        }
    }
    void GLWidget::setYRotation(int angle)
    {
        normalizeAngle(angle);
        if ( angle != yRot ) {
            yRot = angle;
            emit yRotationChanged(angle);
            updateGL();
        }
    }
    
    void GLWidget::setZRotation(int angle)
    {
        normalizeAngle(angle);
        if ( angle != zRot ) {
            zRot = angle;
            emit zRotationChanged(angle);
            updateGL();
        }
    }
    
    void GLWidget::alwaysRotate()
    {
        zRot +=12;
        if (zRot>16*360)        zRot = 0; 
        emit zRotationChanged(zRot);
        updateGL();
    }
    View Code
    //mainwindow.h
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    class QAction;
    class QLabel;
    class QMenu;
    class QSlider;
    class QScrollArea;
    
    class GLWidget;
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
        private slots:
            void renderIntoPixmap();
            void grabFrameBuffer();
            void clearPixmap();
            void about();
    
    private:
    
        void createMenus();
        void createActions();
    
        QSlider *createSlider(const char *changedSignal, const char *setterSlot);
        void setPixmap(const QPixmap &pixmap);
        QSize getSize();
    
        QWidget *centralWidget;
        QScrollArea *glWidgetArea;
        QScrollArea *pixmapLabelArea;
        GLWidget *glWidget;
        QLabel *pixmapLabel;
        QSlider *xSlider;
        QSlider *ySlider;
        QSlider *zSlider;
    
        QMenu *fileMenu;
        QMenu *helpMenu;
        QAction *renderIntoPixmapAction;
        QAction *grabFrameBufferAction;
        QAction *clearPixmapAction;
        QAction *exitAction;
        QAction *aboutAction;
        QAction *aboutQtAction;
    
    };
    
    #endif // MAINWINDOW_H
    View Code
    //mainwindow.cpp
    #include <QtOpenGL>
    #include <QAction>
    #include <QLabel>
    #include <QMenu>
    #include <QSlider>
    #include <QScrollArea>
    #include <QMenuBar>
    #include <QApplication>
    
    
    #include "mainwindow.h"
    #include "glwidget.h"
    #include <time.h>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        centralWidget = new QWidget;
        setCentralWidget(centralWidget);
    
        glWidget = new GLWidget;
        pixmapLabel = new QLabel;
    
        glWidgetArea = new QScrollArea;
        glWidgetArea->setWidget(glWidget);
        //glWidgetArea->viewport()->setBackgroundRole(QPalette::Dark);
        glWidgetArea->setWidgetResizable(true);
        glWidgetArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        glWidgetArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        glWidgetArea->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
        glWidgetArea->setMinimumSize(50, 50);
    
        pixmapLabelArea = new QScrollArea;
        pixmapLabelArea->setWidget(pixmapLabel);
        pixmapLabelArea->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
        pixmapLabelArea->setMinimumSize(50, 50);
    
        //在构造一个QSlider时将QGLWidget的信号和槽传给这个函数的形参,这样就可以在QMainWindow中
        //控制OpenGL的动作了,而让GLWidget类只完成绘图工作。
        xSlider = createSlider(SIGNAL(xRotationChanged(int)),
                               SLOT(setXRotation(int)));
        ySlider = createSlider(SIGNAL(yRotationChanged(int)),
                               SLOT(setYRotation(int)));
        zSlider = createSlider(SIGNAL(zRotationChanged(int)),
                               SLOT(setZRotation(int)));
    
        /*
        xSlider = new QSlider(Qt::Horizontal);
        ySlider = new QSlider(Qt::Horizontal);
        zSlider = new QSlider(Qt::Horizontal);
        */
    
        QGridLayout *centralLayout = new QGridLayout;
        centralLayout->addWidget(glWidgetArea, 0, 0);
        centralLayout->addWidget(pixmapLabelArea, 0, 1);
        centralLayout->addWidget(xSlider, 1, 0, 1, 2);
        centralLayout->addWidget(ySlider, 2, 0, 1, 2);
        centralLayout->addWidget(zSlider, 3, 0, 1, 2);
        centralWidget->setLayout(centralLayout);
    
        createActions();
        createMenus();
    
        xSlider->setValue(15 * 16);
        ySlider->setValue(345 * 16);
        zSlider->setValue(0 * 16);
    
        setWindowTitle(tr("Grabeer"));
        resize(480, 360);
    }
    
    void MainWindow::setPixmap(const QPixmap &pixmap)
    {
        //截图到磁盘
        time_t curTime = time(NULL);
        QString path1 = "E:\",path2=".jpg";
        QString path = QString::number(curTime, 10)+path2;
        
        pixmapLabel->setPixmap(pixmap);
        pixmap.save(path, 0, -1);
            QSize size = pixmap.size();
        if (size - QSize(1, 0) == pixmapLabelArea->maximumViewportSize())
            size -= QSize(1, 0);
        pixmapLabel->resize(size);
    }
    
    QSize MainWindow::getSize()
    {
        bool ok;
        QString text = QInputDialog::getText(this, tr("Grabber"),
                                             tr("Enter Pixmap Size:"),
                                             QLineEdit::Normal,
                                             tr("%1 x %2").arg(glWidget->width())
                                                          .arg(glWidget->height()),
                                             &ok);
        if (!ok)
            return QSize();
    
        QRegExp regExp(tr("([0-9]+) *x *([0-9]+)"));
        if (regExp.exactMatch(text)) {
            int width = regExp.cap(1).toInt();
            int height = regExp.cap(2).toInt();
            if (width > 0 && width < 2048 && height > 0 && height < 2048)
                 return QSize(width, height);
        }
        return glWidget->size();
    }
    
    void MainWindow::renderIntoPixmap()
    {
        QSize size = getSize();
        if (size.isValid()) {
            QPixmap pixmap = glWidget->renderPixmap(size.width(), size.height());
            setPixmap(pixmap);
        }
    }
    
    void MainWindow::grabFrameBuffer()
    {
        //QGLWidget有一个返回其帧缓冲区的QImage图片的函数
        QImage image = glWidget->grabFrameBuffer();
        //QPixmap的fromImage函数把一个QImage转换成QPixmap
        setPixmap(QPixmap::fromImage(image));
    }
    
    void MainWindow::clearPixmap()
    {
        setPixmap(QPixmap()); //给它传一个空的对象
    }
    
    void MainWindow::about()
    {
        QMessageBox::about(this, tr("About Grabber"),
                 tr("The <b>Grabber</b> example demonstrates two approaches for "
                    "rendering OpenGL into a Qt pixmap."));
    }
    
    QSlider *MainWindow::createSlider(const char *changedSignal,
                                      const char *setterSlot)
    {
        QSlider *slider = new QSlider(Qt::Horizontal);
        slider->setRange(0, 16 * 360);
        slider->setSingleStep(16);
        slider->setPageStep(15 * 16);
        slider->setTickInterval(15 * 16);
        slider->setTickPosition(QSlider::TicksRight);
    
        //这种经典的用法一定要小心,报错:glWidget的槽函数在传进来的时候已经被强制转换成SLOT了,
        //所以setterSlot不用SLOT修饰;同样,changedSignal也不能再拿SIGNAL修饰
        connect(slider, SIGNAL(valueChanged(int)), glWidget, setterSlot);
        connect(glWidget, changedSignal, slider, SLOT(setValue(int)));
    
        return slider;
    }
    
    void MainWindow::createActions()
    {
        renderIntoPixmapAction = new QAction(tr("&Render into Pixmap..."), this);
        renderIntoPixmapAction->setShortcut(tr("Ctrl+R"));
        renderIntoPixmapAction->setToolTip(tr("yes, triggerd it"));
        connect(renderIntoPixmapAction, SIGNAL(triggered()),
                this, SLOT(renderIntoPixmap()));
    
        grabFrameBufferAction = new QAction(tr("&Grab Frame Buffer"), this);
        grabFrameBufferAction->setShortcut(tr("Ctrl+G"));
        connect(grabFrameBufferAction, SIGNAL(triggered()),
                this, SLOT(grabFrameBuffer()));
    
        clearPixmapAction = new QAction(tr("&Clear Pixmap"), this);
        clearPixmapAction->setShortcut(tr("Ctrl+L"));
        connect(clearPixmapAction, SIGNAL(triggered()), this, SLOT(clearPixmap()));
    
        exitAction = new QAction(tr("E&xit"), this);
        exitAction->setShortcuts(QKeySequence::Quit);
        connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
    
        aboutAction = new QAction(tr("&About"), this);
        connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
    
        aboutQtAction = new QAction(tr("About &Qt"), this);
        connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
    }
    
    void MainWindow::createMenus()
    {
        fileMenu = menuBar()->addMenu(tr("&File"));
        fileMenu->addAction(renderIntoPixmapAction);
        fileMenu->addAction(grabFrameBufferAction);
        fileMenu->addAction(clearPixmapAction);
        fileMenu->addSeparator();
        fileMenu->addAction(exitAction);
    
        helpMenu = menuBar()->addMenu(tr("&Help"));
        helpMenu->addAction(aboutAction);
        helpMenu->addAction(aboutQtAction);
    }
    
    MainWindow::~MainWindow()
    { 
    }
    View Code
    //main.cpp
    #include <QApplication>
    #include <QDesktopWidget>
    
    #include "mainwindow.h"
    #include "glwidget.h"
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        MainWindow window;
        window.show();
        //GLWidget widegt;
        //widegt.show();
        return app.exec();
    }
    View Code

    二.介绍

    1.GLWidget控件类的实现

    a.继承QGLWidget类

    b.实例虚构OpenGL函数

    protected:
        void initializeGL();
        void paintGL();
        void resizeGL(int w, int h);
        void mousePressEvent(QMouseEvent *event);
        void mouseMoveEvent(QMouseEvent *event);

    c.根据相关的功能添加函数和变量

    d.c++语法两个,其一

    int xRotation() const { return xRot; }
        int yRotation() const { return yRot; }
        int zRotation() const { return zRot; }
    //const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰.
    //常成员函数, 它不改变对象的成员变量.                    
    //也不能调用类中任何非const成员函数.

    其二

    explicit GLWidget(QWidget *parent = 0);
    //声明为explicit的构造函数不能在隐式转换中使用。

    2.mainwindow类的实现.

     a.实现鼠标拖动和slider保持一致.

    举个简单的例子:

    #include<QApplication>
    #include <QHBoxLayout>
    #include <QSlider>
    #include <QSpinBox>
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        QWidget *window = new QWidget;
        window->setWindowTitle("Enter a Number");
    
        QSpinBox *spinbox = new QSpinBox;
        QSlider *slider = new QSlider(Qt::Horizontal);
        spinbox->setRange(0, 130);
        slider->setRange(0, 130);
    
        QObject::connect(spinbox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
        QObject::connect(slider,SIGNAL(valueChanged(int)), spinbox, SLOT(setValue(int)));
        spinbox->setValue(35);
    
        QHBoxLayout *layout = new QHBoxLayout;
        layout->addWidget(spinbox);
        layout->addWidget(slider);
        window->setLayout(layout);
    
        window->show();
        return app.exec();
    }

     b.截图功能实现的工作原理..........

  • 相关阅读:
    ZOJ 1002 Fire Net (火力网)
    UVa OJ 117 The Postal Worker Rings Once (让邮差只走一圈)
    UVa OJ 118 Mutant Flatworld Explorers (变体扁平世界探索器)
    UVa OJ 103 Stacking Boxes (嵌套盒子)
    UVa OJ 110 MetaLoopless Sorts (无循环元排序)
    第一次遇到使用NSNull的场景
    NSURL使用浅析
    从CNTV下载《小小智慧树》
    NSDictionary and NSMutableDictionary
    Category in static library
  • 原文地址:https://www.cnblogs.com/lwngreat/p/4345163.html
Copyright © 2011-2022 走看看