Qt5下利用freeglut实现最基本OpenGL程序(图文解释)
来源:互联网 发布:手机压缩文件解压软件 编辑:程序博客网 时间:2024/05/16 23:46
编程环境:
Qt5.8.0 + Windows10(64bit) + freeglut
(Qt下载版本)
前言(可略过……):
最近计算机图形学作业要求编写带下拉菜单栏menu的OpenGL程序,推荐用Qt,但也可以用MFC或者其他GUI库。但是据说Qt比 其他的使用起来更简单,所以下载了Qt。
因为之前都是在VS2015下利用freeglut进行编程,转换到Qt平台下当然也希望能用freeglut(OpenGL1.0)编程,虽然Qt已经支持OpenGL3.0。但是网上貌似找不到Qt + freeglut的教程。另外,网上大部分教程、代码都是Qt4版本(在Qt5中,引入了QOpenGL*系列类,以取代Qt4时代的QGL*系列类),两个版本差别还是挺大的,用Qt4时代的QGL*系列类会报各种错。有些QOpenGL*系列类的教程也介绍得很不全面。简言之,就是,网上的教程参差不齐(我也花了两天时间才把下面这最简单的程序框架实现)。
总之,下面实现的这份代码可以直接作为任何Qt下openGL程序的标准框架来使用。
程序基本功能:
显示简单图形 + 能检测键盘、鼠标输入 + 下拉菜单选择不同功能
实现方法:
1、Qt下新建Qt Widgets Application项目,选择QMainWindow作为基类。创建好项目后,系统已经帮我们生成了mainwindow.h、mainwindow.cpp、main.cpp三份代码文件以及界面文件mainwindow.ui(用于设计)。在做菜单栏之前,前三份代码基本上都是不需要做什么修改的。
2、项目右键->添加新文件-> C++ -> C++ Class ->输入class name :如openglwindow。之后就会生成openglwindow.h、openglwindow.cpp,即我们用于编程的主要文件。
openglwindow.h :
#ifndef OPENGLWINDOW_H#define OPENGLWINDOW_H#include <QOpenGLWidget>#include <QKeyEvent>#include <QMouseEvent>class openglwindow : public QOpenGLWidget { Q_OBJECTpublic: openglwindow(QWidget *parent = 0); ~openglwindow(); //用于菜单栏回调,改变方块颜色 void changeColorGreen(); void changeColorYellow();protected: void initializeGL(); void resizeGL(int width, int height); void paintGL(); void keyPressEvent(QKeyEvent * e); //需要先在.ui里面设置Widget的focusPolicy void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);private: void drawQuads(int r, int g, int b); GLfloat eyeX, eyeY, eyeZ; //摄像机位置 GLfloat rotateAngle; //正方体旋转角度 int redChannel;};#endif // OPENGLWINDOW_H
openglwindow.cpp :
#include "openglwindow.h"#include "iostream"#include <gl/freeglut.h>using namespace std;float int2float(int intensity) { return (float)intensity / 255.0f;}openglwindow::openglwindow(QWidget *parent) :QOpenGLWidget(parent){ rotateAngle = 0; eyeX = eyeY = eyeZ = 0.5f; redChannel = 0;}openglwindow::~openglwindow() {}void openglwindow::drawQuads(int r, int g, int b) { const GLfloat x1 = -0.05f, x2 = 0.05f; const GLfloat y1 = -0.05f, y2 = 0.05f; const GLfloat point[4][2] = { { x1,y1 },{ x1,y2 },{ x2,y2 },{ x2,y1 } }; glColor3f(int2float(r), int2float(g), int2float(b)); glBegin(GL_QUADS); for (int i = 0; i < 4; i++) { glVertex2fv(point[i]); } glEnd();}void openglwindow::initializeGL() { glClearColor( 0.0, 0.0, 0.0, 0.0 ); glEnable( GL_DEPTH_TEST );}void openglwindow::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(eyeX, eyeY, eyeZ, 0, 0, 0, 0, 1, 0); //front glPushMatrix(); glTranslatef(-0.4f, 0, 0); drawQuads(redChannel, 255, 0); glPopMatrix(); rotateAngle += 1.0f;// cout << "rotateAngle " << rotateAngle << endl; glRotatef(rotateAngle, 0, 1, 0); //front glPushMatrix(); glTranslatef(0, 0, 0.05f); drawQuads(0, 255, 0); glPopMatrix(); //behind glPushMatrix(); glTranslatef(0, 0, -0.05f); drawQuads(255, 255, 0); glPopMatrix(); //left glPushMatrix(); glTranslatef(-0.05f, 0, 0); glRotatef(90, 0, 1, 0); drawQuads(0, 255, 255); glPopMatrix(); //right glPushMatrix(); glTranslatef(0.05f, 0, 0); glRotatef(270, 0, 1, 0); drawQuads(255, 0, 0); glPopMatrix(); //top glPushMatrix(); glTranslatef(0, 0.05f, 0); glRotatef(90, 1, 0, 0); drawQuads(0, 0, 255); glPopMatrix(); //bottom glPushMatrix(); glTranslatef(0, -0.05f, 0); glRotatef(270, 1, 0, 0); drawQuads(255, 0, 255); glPopMatrix(); //repaint update();}void openglwindow::resizeGL(int width, int height) { if ( height == 0 ) height = 1; glViewport( 0, 0, (GLint)width, (GLint)height ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity();}void openglwindow::keyPressEvent(QKeyEvent * e) { switch (e->key()) { case Qt::Key_W: cout << "w" << endl; break; case Qt::Key_A: cout << "a" << endl; break; case Qt::Key_S: cout << "s" << endl; break; case Qt::Key_D: cout << "d" << endl; break; default: break; }}void openglwindow::mousePressEvent(QMouseEvent *event) { if (event->buttons() == Qt::LeftButton) { cout << "LeftButton mousePos (" << event->pos().x() << ", " << event->pos().y() << ")" << endl; } else if (event->buttons() & Qt::RightButton) { cout << "RightButton mousePos (" << event->pos().x() << ", " << event->pos().y() << ")" << endl; }}void openglwindow::mouseMoveEvent(QMouseEvent *event) {}void openglwindow::mouseReleaseEvent(QMouseEvent *event) {}void openglwindow::changeColorGreen() { cout << "###### change Color Green!" << endl; redChannel = 0;}void openglwindow::changeColorYellow() { cout << "###### change Color Yellow!" << endl; redChannel = 255;}相信有过freeglut编程的同学,认真看下代码也能大概搞清怎么写的了。
(1)简单图形显示:主要是initializeGL(); resizeGL(int width, int height); paintGL(); 三个函数。应该不用多说了,逻辑跟普通的OpenGL程序类似,但有一点是paintGL()里面调用了update()方法,为重新绘制。由于代码是让正方体绕y轴自动旋转,如果不加update()会静止不动,update()为重新绘制场景(旋转角时刻改变)。
(2)检测键盘、鼠标输入:即keyPressEvent(QKeyEvent * e) 、mousePressEvent(QMouseEvent *event) 那4个方法(注意include的头文件)。这几个方法也不难理解,逻辑也跟普通的OpenGL程序类似。
(3)下拉菜单选择不同功能:这个在下面说了ui界面之后再回头说。
3、有了这两份代码,还不能直接跑!需要在mainwindow.ui给程序设置一个显示窗口:
双击mainwindow.ui -> 左边的空间栏找到Widget,拖到设计界面,设置大小。
此时我们发现右边栏,centralWidget下多了一个子widget:
在widget上右键,提升为/提升的窗口部件-> 输入类名称openglwindow -> 添加、提升:
看到widget那一行改成openglwindow 名字,即为提升成功。
此时,运行程序。应该就能看到图形了!
4、不过,此时是不是发现鼠标、键盘没响应?
由于在Qt下,widget只有获取焦点focus才能响应鼠标、键盘事件。我们回到.ui文件,点击上面的widget,看右下方属性栏,发现focusPolicy一栏为NoFocus,从这就可以知道原因了。点击,改为ClickFocus,保存,运行。就能检测到两种事件了:
5、最后为下拉菜单:
(1)先还是在界面文件内,可以看到中间设计界面上方,有个“在这里输入”按钮,就可以编辑菜单啦:
(2)做成上面这样的时候,可以看到右边栏,已经在menuBar下生产子menu了:
6、问题来了,怎么能让点击的菜单按钮跟代码方法连接起来呢?
从上面的openglwindow.h、openglwindow.cpp我们可以看到两个方法void changeColorGreen(); void changeColorYellow(); 也就是改变颜色,这个好写。还记得我上面说了,做菜单栏之前,mainwindow.h、mainwindow.cpp、main.cpp三份代码基本上不需要做什么修改。但是若要加菜单栏,就需要在这几个文件做文章了。(其实main.cpp也没做什么改动)
main.cpp :
#include "mainwindow.h"#include "openglwindow.h"#include <QApplication>int main(int argc, char *argv[]) { QApplication a(argc, argv); a.setApplicationName("My First openGL Widget"); MainWindow w; w.show(); return a.exec();}
mainwindow.h :
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>namespace Ui { class MainWindow;}class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void changeColorGreen(); void changeColorYellow(); private: Ui::MainWindow *ui;};#endif // MAINWINDOW_H
mainwindow.cpp :
#include "mainwindow.h"#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){ ui->setupUi(this); connect(ui->actionGreen_2, SIGNAL(triggered()), this, SLOT(changeColorGreen())); connect(ui->actionYellow_2, SIGNAL(triggered()), this, SLOT(changeColorYellow()));}MainWindow::~MainWindow(){ delete ui;}void MainWindow::changeColorGreen() { ui->widget->changeColorGreen();}void MainWindow::changeColorYellow() { ui->widget->changeColorYellow();}
改动的地方就是在.h文件了加了private slots两个方法,在.cpp文件里实现两个方法,并且用connect方法做连接(具体用法, 请鼠标靠近函数名按F1查看)。我们可以看到actionGreen_2、actionYellow_2、widget三个都是在ui文件里几个对象的名称:
好了,连接做好了,运行点击试试看~~~
7、最后放上整个项目文件结构:
但是值得一提的是,点击上面的“项目”,选择文件系统,会发现有个ui_mainwindow.h文件(mainwindow.cpp会include),可以点开研究下,对整个窗口、菜单之间串联连接会有更深理解的。
好了,关于Qt的OpenGL程序就介绍到这了。上面的框架可以直接使用哦~~~
- Qt5下利用freeglut实现最基本OpenGL程序(图文解释)
- Qt5下OpenGL程序的新写法
- Qt5下OpenGL程序的新写法
- Qt5下OpenGL程序的新写法
- Qt5下OpenGL程序的新写法
- CodeBlocks下的freeglut环境配置(一)(附图文)
- ubuntu 14.04 安装OpenGL(基于freeglut)
- OpenGL开发学习指南一(freeglut+glew)
- win7+VS2012下openGL开发环境配置(freeglut版)
- 在Windows/Ubuntu下安装OpenGL环境(GLUT/freeglut)与跨平台编译(mingw/g++)
- 在 visual studio 2015 下配置 opengl (GLU/GLUT以及glew/freeglut)
- windows下配置OpenGL环境(glut、freeglut、glew等工具)
- 配置自己的OpenGL库,glew、freeglut库编译,库冲突解决(附OpenGL Demo程序)
- Ubuntu下利用Python开发Opengl程序
- Installing freeglut and OpenGL
- OpenGL配置之freeglut
- OpenGL学习笔记(freeglut)
- OpenGL学习笔记--freeglut
- 十一种通用滤波算法
- LeedCode 之 Remove Duplicates from Sorted List
- python 列表推导式
- 使用反射机制调用构造函数
- 面向对象娱乐版Tab栏切换
- Qt5下利用freeglut实现最基本OpenGL程序(图文解释)
- 基于Google的NotePad改写的记事本应用
- Java Web简单的注册登陆界面(mysql+servlet+jsp)
- 【好东西】ACM在线模版-f-zyj
- hdu5608 function
- activiti工作流数据库表详细介绍(23张表)
- Iterator (迭代器)
- "java.util.NoSuchElementException: No value present" 问题解决:重写hashCode 和 equals 方法
- 【多线程】多线程教程之三---线程的死锁