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.截图功能实现的工作原理..........

  • 相关阅读:
    向IPython Notebook中导入.py文件
    python--时间日期
    python--条件和循环
    python--输入输出
    python--字符串
    python--内置函数
    python--异常
    python--模块
    python--数据结构
    pybrain
  • 原文地址:https://www.cnblogs.com/lwngreat/p/4345163.html
Copyright © 2011-2022 走看看