Qt下的OpenGL 编程(11)Qt实例hellogl代码解析
2012-12-15 20:41
411 查看
一、提要
还记得我们在第一篇教程中运行的例子吗?那是那个可以到处转的大Q,今天我们就来分析一下这个Qt自带的OpenGL例子。
二、文件结构
如上图,项目中共有三个类.
glwidget:opengl的渲染窗口,主要负责图形的绘制,同时响应键盘鼠标事件;
window:主窗口类,负责界面的布局,一些信号和槽的实现;
qtlogo:图形类,负责logo的绘制。
三、glwidget类的分析
首先来看glwidget的头文件:
[cpp] view
plaincopy
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
class QtLogo;
//! [0]
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget(QWidget *parent = 0);
~GLWidget();
QSize minimumSizeHint() const;
QSize sizeHint() const;
//! [0]
//! [1]
public slots:
void setXRotation(int angle);
void setYRotation(int angle);
void setZRotation(int angle);
signals:
void xRotationChanged(int angle);
void yRotationChanged(int angle);
void zRotationChanged(int angle);
//! [1]
//! [2]
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
//! [2]
//! [3]
private:
QtLogo *logo;
int xRot;
int yRot;
int zRot;
QPoint lastPos;
QColor qtGreen;
QColor qtPurple;
};
//! [3]
#endif
首先是类的构造函数和析构函数,构造函数中可以对成员进行初始化,析够函数
可以在不再需要这个对象的时候将不再需要的数据删除掉。
接下来的
QSize minimumSizeHint() const;
QSize sizeHint() const;
用来设置窗口的最小尺寸。
接下来的三个signal和三个slot分别对应三个方向的旋转:X,Y,Z。
protected成员中有三个最主要的函数:initializeGL()负责初始化,paintGL()
负责渲染窗口,resizeGL(int width, int height)在窗口大小变化时调用。后面两个
则是定义鼠标点击和移动的事件。
剩下的一些私有变量则是用来记录旋转角度,或是用来初始化logo的变量。
接下来看一下它的实现:
[cpp] view
plaincopy
#include <QtGui>
#include <QtOpenGL>
#include <math.h>
#include "glwidget.h"
#include "qtlogo.h"
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
//! [0]
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
logo = 0;
xRot = 0;
yRot = 0;
zRot = 0;
qtGreen = QColor::fromCmykF(0.40, 0.0, 1.0, 0.0);
qtPurple = QColor::fromCmykF(0.39, 0.39, 0.0, 0.0);
}
//! [0]
//! [1]
GLWidget::~GLWidget()
{
}
//! [1]
//! [2]
QSize GLWidget::minimumSizeHint() const
{
return QSize(50, 50);
}
//! [2]
//! [3]
QSize GLWidget::sizeHint() const
//! [3] //! [4]
{
return QSize(400, 400);
}
//! [4]
static void qNormalizeAngle(int &angle)
{
while (angle < 0)
angle += 360 * 16;
while (angle > 360 * 16)
angle -= 360 * 16;
}
//! [5]
void GLWidget::setXRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != xRot) {
xRot = angle;
emit xRotationChanged(angle);
updateGL();
}
}
//! [5]
void GLWidget::setYRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != yRot) {
yRot = angle;
emit yRotationChanged(angle);
updateGL();
}
}
void GLWidget::setZRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != zRot) {
zRot = angle;
emit zRotationChanged(angle);
updateGL();
}
}
//! [6]
void GLWidget::initializeGL()
{
qglClearColor(qtPurple.dark());
logo = new QtLogo(this, 64);
logo->setColor(qtGreen.dark());
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_MULTISAMPLE);
static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
}
//! [6]
//! [7]
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0, 0.0, -10.0);
glRotatef(xRot / 16.0, 1.0, 0.0, 0.0);
glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);
logo->draw();
}
//! [7]
//! [8]
void GLWidget::resizeGL(int width, int height)
{
int side = qMin(width, height);
glViewport((width - side) / 2, (height - side) / 2, side, side);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#ifdef QT_OPENGL_ES_1
glOrthof(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
#else
glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
#endif
glMatrixMode(GL_MODELVIEW);
}
//! [8]
//! [9]
void GLWidget::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
}
//! [9]
//! [10]
void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
int dx = event->x() - lastPos.x();
int dy = event->y() - lastPos.y();
if (event->buttons() & Qt::LeftButton) {
setXRotation(xRot + 8 * dy);
setYRotation(yRot + 8 * dx);
} else if (event->buttons() & Qt::RightButton) {
setXRotation(xRot + 8 * dy);
setZRotation(zRot + 8 * dx);
}
lastPos = event->pos();
}
构造函数中首先对几个私有变量进行了初始化,析够函数中什么都没有做(自动回收?),
接下来的qNormalizeAngle函数,是用于纠正角度的,因为在旋转了很多圈之后,角度会变得很大,需要对其进行纠正。
接下来是对三个槽函数的定义,在调用之前都要对角度进行纠正,然后改变相应的角度的值,接着发出角度改变的信号。
这个信号最后是和window类中的控制滑动条的槽链接起来了,当logo发生旋转的时候,就会把旋转的角度告诉给window,然后
window的槽执行相应的语句,滑动条位置发生改变。
相反,当window的滑动条数值发生改变的时候,也会发出相应的信号给glwiget的三个槽函数,然后logo执行旋转。
initializeGL中对logo进行了初始化,还定义了灯光等的参数,比较好理解。
paintGL中我们主要来看一下坐标的变换:首先是把绘制点移到了(0,0,-10)的
位置,然后绕三个轴进行旋转,做后将logo绘制出来(logo的绘制还是有点麻烦,有兴趣的同学可以慢慢研究一下qtlogo类)。
mouseMoveEvent则是对鼠标拖动的响应,左键拖动和右键拖动分别绕不同的方向旋转。
调用的是之前定义的set槽函数。
所以这个类的槽函数有两个作用:1.当作一般的函数;2.响应某个信号。
三、参考
QT帮助。
还记得我们在第一篇教程中运行的例子吗?那是那个可以到处转的大Q,今天我们就来分析一下这个Qt自带的OpenGL例子。
二、文件结构
如上图,项目中共有三个类.
glwidget:opengl的渲染窗口,主要负责图形的绘制,同时响应键盘鼠标事件;
window:主窗口类,负责界面的布局,一些信号和槽的实现;
qtlogo:图形类,负责logo的绘制。
三、glwidget类的分析
首先来看glwidget的头文件:
[cpp] view
plaincopy
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
class QtLogo;
//! [0]
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget(QWidget *parent = 0);
~GLWidget();
QSize minimumSizeHint() const;
QSize sizeHint() const;
//! [0]
//! [1]
public slots:
void setXRotation(int angle);
void setYRotation(int angle);
void setZRotation(int angle);
signals:
void xRotationChanged(int angle);
void yRotationChanged(int angle);
void zRotationChanged(int angle);
//! [1]
//! [2]
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
//! [2]
//! [3]
private:
QtLogo *logo;
int xRot;
int yRot;
int zRot;
QPoint lastPos;
QColor qtGreen;
QColor qtPurple;
};
//! [3]
#endif
首先是类的构造函数和析构函数,构造函数中可以对成员进行初始化,析够函数
可以在不再需要这个对象的时候将不再需要的数据删除掉。
接下来的
QSize minimumSizeHint() const;
QSize sizeHint() const;
用来设置窗口的最小尺寸。
接下来的三个signal和三个slot分别对应三个方向的旋转:X,Y,Z。
protected成员中有三个最主要的函数:initializeGL()负责初始化,paintGL()
负责渲染窗口,resizeGL(int width, int height)在窗口大小变化时调用。后面两个
则是定义鼠标点击和移动的事件。
剩下的一些私有变量则是用来记录旋转角度,或是用来初始化logo的变量。
接下来看一下它的实现:
[cpp] view
plaincopy
#include <QtGui>
#include <QtOpenGL>
#include <math.h>
#include "glwidget.h"
#include "qtlogo.h"
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
//! [0]
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
logo = 0;
xRot = 0;
yRot = 0;
zRot = 0;
qtGreen = QColor::fromCmykF(0.40, 0.0, 1.0, 0.0);
qtPurple = QColor::fromCmykF(0.39, 0.39, 0.0, 0.0);
}
//! [0]
//! [1]
GLWidget::~GLWidget()
{
}
//! [1]
//! [2]
QSize GLWidget::minimumSizeHint() const
{
return QSize(50, 50);
}
//! [2]
//! [3]
QSize GLWidget::sizeHint() const
//! [3] //! [4]
{
return QSize(400, 400);
}
//! [4]
static void qNormalizeAngle(int &angle)
{
while (angle < 0)
angle += 360 * 16;
while (angle > 360 * 16)
angle -= 360 * 16;
}
//! [5]
void GLWidget::setXRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != xRot) {
xRot = angle;
emit xRotationChanged(angle);
updateGL();
}
}
//! [5]
void GLWidget::setYRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != yRot) {
yRot = angle;
emit yRotationChanged(angle);
updateGL();
}
}
void GLWidget::setZRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != zRot) {
zRot = angle;
emit zRotationChanged(angle);
updateGL();
}
}
//! [6]
void GLWidget::initializeGL()
{
qglClearColor(qtPurple.dark());
logo = new QtLogo(this, 64);
logo->setColor(qtGreen.dark());
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_MULTISAMPLE);
static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
}
//! [6]
//! [7]
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0, 0.0, -10.0);
glRotatef(xRot / 16.0, 1.0, 0.0, 0.0);
glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);
logo->draw();
}
//! [7]
//! [8]
void GLWidget::resizeGL(int width, int height)
{
int side = qMin(width, height);
glViewport((width - side) / 2, (height - side) / 2, side, side);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#ifdef QT_OPENGL_ES_1
glOrthof(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
#else
glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
#endif
glMatrixMode(GL_MODELVIEW);
}
//! [8]
//! [9]
void GLWidget::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
}
//! [9]
//! [10]
void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
int dx = event->x() - lastPos.x();
int dy = event->y() - lastPos.y();
if (event->buttons() & Qt::LeftButton) {
setXRotation(xRot + 8 * dy);
setYRotation(yRot + 8 * dx);
} else if (event->buttons() & Qt::RightButton) {
setXRotation(xRot + 8 * dy);
setZRotation(zRot + 8 * dx);
}
lastPos = event->pos();
}
构造函数中首先对几个私有变量进行了初始化,析够函数中什么都没有做(自动回收?),
接下来的qNormalizeAngle函数,是用于纠正角度的,因为在旋转了很多圈之后,角度会变得很大,需要对其进行纠正。
接下来是对三个槽函数的定义,在调用之前都要对角度进行纠正,然后改变相应的角度的值,接着发出角度改变的信号。
这个信号最后是和window类中的控制滑动条的槽链接起来了,当logo发生旋转的时候,就会把旋转的角度告诉给window,然后
window的槽执行相应的语句,滑动条位置发生改变。
相反,当window的滑动条数值发生改变的时候,也会发出相应的信号给glwiget的三个槽函数,然后logo执行旋转。
initializeGL中对logo进行了初始化,还定义了灯光等的参数,比较好理解。
paintGL中我们主要来看一下坐标的变换:首先是把绘制点移到了(0,0,-10)的
位置,然后绕三个轴进行旋转,做后将logo绘制出来(logo的绘制还是有点麻烦,有兴趣的同学可以慢慢研究一下qtlogo类)。
mouseMoveEvent则是对鼠标拖动的响应,左键拖动和右键拖动分别绕不同的方向旋转。
调用的是之前定义的set槽函数。
所以这个类的槽函数有两个作用:1.当作一般的函数;2.响应某个信号。
三、参考
QT帮助。
相关文章推荐
- Qt下的OpenGL 编程(11)Qt实例hellogl代码解析
- Qt下的OpenGL 编程(11)Qt实例hellogl代码解析
- QT 多线程和 QSocket 网络编程实例解析
- QT 多线程和 QSocket 网络编程实例解析
- 续实例解析SOCKET编程模型之异步通信篇(上) 代码
- Qt网络编程之实例一GET方式 .
- Qt下的OpenGL 编程(6)混合、雾、抗锯齿
- Qt网络编程之实例一GET方式
- C#中异步Socket通信编程代码实例
- Qt下的OpenGL 编程(2)动手搭建Qt下的OpenGL编程框架
- 用python3+PyQt5改写Python Qt GUI快速编程的第6章实例主窗口
- 低功耗蓝牙4.0BLE编程-nrf51822开发(11)-蓝牙串口代码分析
- C#接口编程实例解析[转]
- Qt OpenGL:学习现代3D图形编程之一,画一个三角形
- Java编程几个循环实例代码分享
- c# winform 应用编程代码总结 11
- python 解析XML python模块xml.dom解析xml实例代码
- python 解析XML python模块xml.dom解析xml实例代码
- 由画板实例来把握代码编写格式和提高编程能力以及OOP思想的实践
- 初学者入门 JAVA 的 XML 编程实例解析-Java基础-Java-编程开发