Qt中OpenGL的初步使用

时间:2022-06-20 14:48:45

结果预览:

Qt中OpenGL的初步使用

一.代码5个文件

//glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget> class GLWidget:public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget *parent = ); 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[];
QPoint lastPos;
QColor qtGreen, qtPurple;
}; #endif
//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 = ;
yRot = ;
zRot = ; faceColors[] = Qt::red;
faceColors[] = Qt::green;
faceColors[] = Qt::blue;
faceColors[] = 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();
}
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) / , (height() - side)/, 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 + *dy);
} else if (event->buttons()&Qt::RightButton)
{
setZRotation(zRot + *dx);
}
lastPos = event->pos();
} void GLWidget::drawTriangle()
{
static const GLfloat P1[] = { 0.0, -1.0, +2.0 };
static const GLfloat P2[] = { +1.73, -1.0, -1.0 };
static const GLfloat P3[] = { -1.73, -1.0, -1.0 };
static const GLfloat P4[] = { 0.0, +2.0, 0.0 }; static const GLfloat * const coords[][] = {
{ 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 = ; i != ; ++i)
{
glBegin(GL_TRIANGLES);
qglColor(faceColors[i]);
for (int j = ; j<;++j)
glVertex3f(coords[i][j][], coords[i][j][], coords[i][j][]);
glEnd();
} } void GLWidget::normalizeAngle(int &angle)
{
while (angle<)
angle +=*;
while (angle>*)
angle -=*;
} 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 +=;
if (zRot>*) zRot = ;
emit zRotationChanged(zRot);
updateGL();
}
//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 = );
~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
//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(, ); pixmapLabelArea = new QScrollArea;
pixmapLabelArea->setWidget(pixmapLabel);
pixmapLabelArea->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
pixmapLabelArea->setMinimumSize(, ); //在构造一个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, , );
centralLayout->addWidget(pixmapLabelArea, , );
centralLayout->addWidget(xSlider, , , , );
centralLayout->addWidget(ySlider, , , , );
centralLayout->addWidget(zSlider, , , , );
centralWidget->setLayout(centralLayout); createActions();
createMenus(); xSlider->setValue( * );
ySlider->setValue( * );
zSlider->setValue( * ); setWindowTitle(tr("Grabeer"));
resize(, );
} void MainWindow::setPixmap(const QPixmap &pixmap)
{
//截图到磁盘
time_t curTime = time(NULL);
QString path1 = "E:\\",path2=".jpg";
QString path = QString::number(curTime, )+path2; pixmapLabel->setPixmap(pixmap);
pixmap.save(path, , -);
QSize size = pixmap.size();
if (size - QSize(, ) == pixmapLabelArea->maximumViewportSize())
size -= QSize(, );
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().toInt();
int height = regExp.cap().toInt();
if (width > && width < && height > && height < )
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(, * );
slider->setSingleStep();
slider->setPageStep( * );
slider->setTickInterval( * );
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()
{
}
//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();
}

二.介绍

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);

Qt中OpenGL的初步使用

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 = );
//声明为explicit的构造函数不能在隐式转换中使用。

2.mainwindow类的实现.

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

举个简单的例子:

Qt中OpenGL的初步使用

#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(, );
slider->setRange(, ); QObject::connect(spinbox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
QObject::connect(slider,SIGNAL(valueChanged(int)), spinbox, SLOT(setValue(int)));
spinbox->setValue(); QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(spinbox);
layout->addWidget(slider);
window->setLayout(layout); window->show();
return app.exec();
}

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

相关文章