我在 Qt 中有一个 OpenGL 小部件(从 QGLWidget 继承),具有 2 种渲染模式:
- 渲染默认立方体 (
#define CUBE_MODE 0
)。 - 渲染 opencv 图像 (
#define IMAGE_MODE 1
)。
我有一个公共方法来设置要呈现的模式(void setRenderMode(int mode)
)。
我还有一个组合框,其中包含 2 个项目:立方体和图像。
我希望当我单击组合框中的一个项目(例如多维数据集)时,openGL 小部件显示多维数据集,当我单击另一个项目(图像)时,小部件显示图像。所以我使用插槽/信号系统来做到这一点。
窗口正确启动,并显示多维数据集,但是当我切换到图像时,小部件不显示图像,当我尝试返回多维数据集项目时,它不显示。(当我在没有组合框的情况下单独使用它们时,这两种模式可以正常工作)。
这是我的代码片段:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui -> setupUi(this);
openglWidget = new GLWidget();
openglWidget->setRenderMode(0);
ui->verticalLayout->addWidget(openglWidget);
connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(showModel(int)));
}
void MainWindow::showModel(int index)
{
switch(index)
{
case 0:
openglWidget->setRenderMode(0);
break;
case 1:
openglWidget->setRenderMode(1);
break;
}
}
paintGL 方法是:
void GLWidget::paintGL()
{
makeCurrent();
if( !mSceneChanged )
return;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
switch( mPaintMode )
{
case POINT_CLOUD_MODE:
{
renderPointCloud();
}
break;
case IMAGE_MODE:
renderImage();
break;
default:
renderDefaultCube();
}
}
更新
渲染图像代码:
void GLWidget::renderImage()
{
makeCurrent();
glClear (GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
if (!mImage.isNull())
{
glLoadIdentity();
glPushMatrix();
{
int imW = mImage.width();
int imH = mImage.height();
bool resized = false;
if( imW != this->size().width() &&
imH != this->size().height() )
{
mImage = mImage.scaled( this->size(),
Qt::KeepAspectRatio,
Qt::FastTransformation );
resized = true;
}
//Centering image in draw area
int posX = (this->size().width()-imW)/2;
int posY = (this->size().height()-imH)/2;
glRasterPos2i( posX, posY );
//Centering image in draw area
glDrawPixels( mImage.width(), mImage.height(),
GL_RGBA, GL_UNSIGNED_BYTE, mImage.bits());
if( resized)
{
imW = mImage.width();
imH = mImage.height();
}
}
glPopMatrix();
glFlush();
}
glEnable(GL_DEPTH_TEST);
}
和 setFrame 方法:
void GLWidget::setFrameImage(Mat img )
{
if( !img.data )
{
qDebug( "Warning: No Image to be set");
return;
}
if( img.channels() == 3)
mImage = QImage((const unsigned char*)(img.data), img.cols, img.rows,
img.step, QImage::Format_RGB888);
else if( img.channels() == 1)
mImage = QImage((const unsigned char*)(img.data), img.cols, img.rows,
img.step, QImage::Format_Indexed8);
else
return;
mImage = QGLWidget::convertToGLFormat(mImage);
mSceneChanged = true;
updateGL();
}
更新#2
我将paintGL修改为:
void GLWidget::paintGL()
{
makeCurrent();
if( !mSceneChanged )
return;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
switch( mPaintMode )
{
case CUBE_MODE:
{
renderDefaultCube();
}
break;
case IMAGE_MODE:
renderImage();
break;
}
}
当我设置 openglWidget -> setRenderMode(0); 我只能看到立方体,但是当我单击组合框上的图像项时,我什么也看不到,反之亦然,当我设置 openglWidget -> setRenderMode(1)。
更新#3:完整的源代码
GLWidget.h
#include <map>
#include <string>
#include <QtOpenGL/QGLWidget>
#include <QtOpenGL/QtOpenGL>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "rk_geometry.h"
using namespace std;
using namespace cv;
#define CUBE_MODE 0
#define IMAGE_MODE 1
#define PLANE_XY 0
#define PLANE_XZ 1
#define PLANE_YZ 2
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget(QWidget *parent = 0);
protected:
void initializeGL();
void paintGL();
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void keyPressEvent ( QKeyEvent * event );
void resizeGL(int width, int height);
void renderImage();
void renderDefaultCube();
private:
void drawAxis();
void drawGridXY();
void drawGridXZ();
void drawGridYZ();
void drawCameraTargetSphere();
void drawCloudBox( cloud_rgb_t::Ptr cloud, int r, int g, int b);
public slots:
void doPitch(double angle);
void doRoll(double angle);
void doYaw(double angle);
void updateScene();
void setRenderMode( int renderMode );
void setFrameImage( Mat img );
void resetView( bool update=false );
void topView();
bool showCameraTarget( bool show=true);
bool showGrid( int idx, bool show=true );
bool showBoxes(bool show=true);
private:
float mZoom;
rkGeom::CPoint position;
rkGeom::CVector forward;
rkGeom::CVector up;
rkGeom::CVector right;
int mPtSize;
QColor qtBlack;
QPoint lastPos;
bool mShowGrid[3];
bool mDrawBoxes;
int mPaintMode;
QImage mImage;
bool mShowCameraTarget;
};
GLWidget.cpp
#include "GLWidget.h"
#define MIN_CAM_DIST 0.25f
#define MOV_STEP 0.05f
GLWidget::GLWidget(QWidget *parent) :
QGLWidget(QGLFormat(QGL::SampleBuffers), parent),
position(0,0,0),
forward(0, 0, -1),
up(0, 1, 0),
right(1, 0, 0)
{
mZoom = MIN_CAM_DIST;
mDrawBoxes = false;
qtBlack = QColor::fromRgb(0, 0, 0);
mPaintMode = -1;
setFocusPolicy( Qt::ClickFocus );
mShowCameraTarget = true;
mPtSize = 1;
mShowGrid[0] = true;
mShowGrid[1] = false;
mShowGrid[2] = false;
resetView(false);
}
void GLWidget::initializeGL()
{
makeCurrent();
qglClearColor(qtBlack.darker());
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
}
void GLWidget::resizeGL(int width, int height)
{
makeCurrent();
glViewport(0, 0, (GLint)width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if( mPaintMode == CUBE_MODE )
gluPerspective( 60.0, double(width)/height, 0.01, 200000 );
else if( mPaintMode == IMAGE_MODE )
glOrtho(0, width, 0, height, 0, 1);
glMatrixMode(GL_MODELVIEW);
}
void GLWidget::paintGL()
{
makeCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
switch( mPaintMode )
{
case CUBE_MODE:
{
renderDefaultCube();
}
break;
case IMAGE_MODE:
renderImage();
break;
}
}
void GLWidget::mousePressEvent(QMouseEvent *event)
{
if( mPaintMode == IMAGE_MODE )
return;
lastPos = event->pos();
}
void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
if( mPaintMode == IMAGE_MODE )
return;
float dx = (float)(event->x() - lastPos.x());
float dy = (float)(event->y() - lastPos.y());
if (event->buttons() & Qt::LeftButton)
{
doPitch( DEG2RAD(dy));
doYaw( DEG2RAD(-dx));
updateGL();
}
else if (event->buttons() & Qt::RightButton)
{
mZoom += dx*0.1;
if( mZoom < MIN_CAM_DIST )
mZoom = MIN_CAM_DIST;
updateGL();
}
else if (event ->buttons() & Qt::MidButton)
{
if (dx > 0)
position.z += 100;
if (dx < 0)
position.z -= 100;
updateGL();
}
lastPos = event->pos();
}
void GLWidget::keyPressEvent ( QKeyEvent * event )
{
float dx, dy, dz;
dx = dy = dz = 0.0f;
if ( event->key() == Qt::Key_A )
{
doRoll(DEG2RAD(1));
} else if ( event->key() == Qt::Key_D )
{
doRoll(DEG2RAD(-1));
}
else if ( event->key() == Qt::Key_Up )
{
position += MOV_STEP*forward;
}else if ( event->key() == Qt::Key_Down )
{
position -= MOV_STEP*forward;
}
else if ( event->key() == Qt::Key_Left )
{
position -= MOV_STEP*right;
}
else if ( event->key() == Qt::Key_Right )
{
position += MOV_STEP*right;
}
else if ( event->key() == Qt::Key_Home )
{
position.z += MOV_STEP;
}
else if ( event->key() == Qt::Key_End )
{
position.z -= MOV_STEP;
}
else if ( event->key() == Qt::Key_PageUp )
{
position.y += MOV_STEP;
}
else if ( event->key() == Qt::Key_PageDown )
{
position.y -= MOV_STEP;
}
else if ( event->key() == Qt::Key_Minus )
{
mPtSize--;
if( mPtSize<1 )
mPtSize=1;
}
else if ( event->key() == Qt::Key_Plus )
{
mPtSize++;
if( mPtSize>10 )
mPtSize=10;
}
updateGL();
}
void GLWidget::doPitch(double angle)
{
forward = unit(forward * cos(angle) + up * sin(angle));
up = right.cross(forward);
}
void GLWidget::doRoll(double angle)
{
right = unit(right * cos(angle) + up * sin(angle));
up = right.cross(forward);
}
void GLWidget::doYaw(double angle)
{
right = unit(right * cos(angle) + forward * sin(angle));
forward = up.cross(right);
}
void GLWidget::updateScene()
{
if( this->isVisible() )
updateGL();
}
void GLWidget::setRenderMode( int renderMode )
{
mPaintMode = renderMode;
updateGL();
}
void GLWidget::renderDefaultCube()
{
makeCurrent();
static const int coords[5][4][3] =
{
{ { +1, -1, -1 }, { -1, -1, -1 }, { -1, +1, -1 }, { +1, +1, -1 } },
{ { +1, -1, 0 }, { -1, -1, 0 }, { -1, +1, 0 }, { +1, +1, 0 } },
{ { +1, -1, +1 }, { -1, -1, +1 }, { -1, +1, +1 }, { +1, +1, +1 } },
{ { 0, -1, -1 }, { +1, 0, -1 }, { 0, +1, -1 }, { -1, 0, -1 } },
{ { 0, -1, +1 }, { +1, 0, +1 }, { 0, +1, +1 }, { -1, 0, +1 } }
};
glPointSize(mPtSize);
glScalef(0.01f,0.01f,0.01f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( position.x-mZoom*forward.i, position.y-mZoom*forward.j, position.z-mZoom*forward.k,
position.x, position.y, position.z,
up.i, up.j, up.k);
glPushMatrix();
glColor3ub( 0, 255, 0 );
glBegin(GL_POINTS);
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 4; ++j)
{
glVertex3d(coords[i][j][0], coords[i][j][1], coords[i][j][2]);
}
}
glEnd();
glPopMatrix();
glPointSize(mPtSize);
}
void GLWidget::drawCameraTargetSphere()
{
glColor4f( 0.8,0.8,0.8,0.3);
glPushMatrix();
glTranslatef( position.x, position.y, position.z );
static GLUquadric* quad = gluNewQuadric();
gluSphere( quad, 0.025f, 16, 16 );
glPopMatrix();
}
void GLWidget::renderImage()
{
makeCurrent();
glClear (GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
if (!mImage.isNull())
{
glLoadIdentity();
glPushMatrix();
{
int imW = mImage.width();
int imH = mImage.height();
bool resized = false;
if( imW != this->size().width() &&
imH != this->size().height() )
{
mImage = mImage.scaled( this->size(),
Qt::KeepAspectRatio,
Qt::FastTransformation );
resized = true;
}
int posX = (this->size().width()-imW)/2;
int posY = (this->size().height()-imH)/2;
glRasterPos2i( posX, posY );
glDrawPixels( mImage.width(), mImage.height(),
GL_RGBA, GL_UNSIGNED_BYTE, mImage.bits());
if( resized)
{
imW = mImage.width();
imH = mImage.height();
}
}
glPopMatrix();
glFlush();
}
glEnable(GL_DEPTH_TEST);
}
void GLWidget::setFrameImage(Mat img )
{
if( !img.data )
{
qDebug( "Warning: No Image to be set");
return;
}
if( img.channels() == 3)
mImage = QImage((const unsigned char*)(img.data), img.cols, img.rows,
img.step, QImage::Format_RGB888);
else if( img.channels() == 1)
mImage = QImage((const unsigned char*)(img.data), img.cols, img.rows,
img.step, QImage::Format_Indexed8);
else
return;
mImage = QGLWidget::convertToGLFormat(mImage);
updateGL();
}
void GLWidget::resetView( bool update )
{
position.x = -0.311778;
position.y = 0.242323;
position.z = 0.441647;
forward.i = 0.284576;
forward.j = -0.414646;
forward.k = 0.864341;
up.i = -0.020237;
up.j = -0.904017;
up.k = -0.427017;
right.i = 0.95844;
right.j = 0.104027;
right.k = -0.265653;
mZoom = MIN_CAM_DIST;
if( update )
updateGL();
}
void GLWidget::topView()
{
position.x = position.y = 0;
position.z = 5.0;
forward.i = 0;
forward.j = 0;
forward.k = -1;
up.i = 0;
up.j = 1;
up.k = 0;
right.i = 1;
right.j = 0;
right.k = 0;
mZoom = MIN_CAM_DIST;
updateGL();
}
void GLWidget::drawAxis()
{
float limit = 10.0f;
float limitAxe = 0.3f;
glLineWidth( 1.0 );
glBegin( GL_LINES );
{
glColor4f( 0.20, 0.20, 0.20, 0.5 );
glVertex3f( -limit, 0, 0 );
glVertex3f( 0, 0, 0 );
glVertex3f( limitAxe, 0, 0 );
glVertex3f( limit, 0, 0 );
glVertex3f( 0, -limit, 0 );
glVertex3f( 0, 0, 0 );
glVertex3f( 0, limitAxe, 0 );
glVertex3f( 0, limit, 0 );
glVertex3f( 0, 0, -limit );
glVertex3f( 0, 0, 0 );
glVertex3f( 0, 0, limitAxe );
glVertex3f( 0, 0, limit );
}
glEnd();
glLineWidth( 3.0 );
glBegin( GL_LINES );
{
glColor4f( 1.0, 0, 0, 0.5 );
glVertex3f( 0, 0, 0 );
glVertex3f( limitAxe, 0, 0 );
glColor4f( 0, 1.0, 0, 0.5 );
glVertex3f( 0, 0, 0 );
glVertex3f( 0, limitAxe, 0 );
glColor4f( 0, 0, 1.0, 0.5 );
glVertex3f( 0, 0, 0 );
glVertex3f( 0, 0, limitAxe );
}
glEnd();
}
void GLWidget::drawGridXY()
{
float limit = 10.0f;
float gridSize = 1.0f;
glColor4f( 0.4,0.4,0.4,0.5);
float x = -limit;
float y = -limit;
glLineWidth( 1.0 );
glBegin( GL_LINES );
{
while( x<=limit )
{
while( y<=limit )
{
if( y!=0 )
{
glVertex3f( -limit, y, 0 );
glVertex3f( limit, y, 0 );
}
y+=gridSize;
}
if( x!=0 )
{
glVertex3f( x, -limit, 0 );
glVertex3f( x, limit, 0 );
}
x+=gridSize;
}
}
glEnd();
}
void GLWidget::drawGridXZ()
{
float limit = 10.0f;
float gridSize = 1.0f;
glColor4f( 0.4,0.4,0.4,0.5);
float x = -limit;
float z = -limit;
glLineWidth( 1.0 );
glBegin( GL_LINES );
{
while( x<=limit )
{
while( z<=limit )
{
if( z!=0 )
{
glVertex3f( -limit, 0, z );
glVertex3f( limit, 0, z );
}
z+=gridSize;
}
if( x!=0 )
{
glVertex3f( x, 0, -limit );
glVertex3f( x, 0, limit );
}
x+=gridSize;
}
}
glEnd();
}
void GLWidget::drawGridYZ()
{
float limit = 10.0f;
float gridSize = 1.0f;
glColor4f( 0.4,0.4,0.4,0.5);
float y = -limit;
float z = -limit;
glLineWidth( 1.0 );
glBegin( GL_LINES );
{
while( y<=limit )
{
while( z<=limit )
{
if( z!=0 )
{
glVertex3f( 0, -limit, z );
glVertex3f( 0, limit, z );
}
z+=gridSize;
}
if( y!=0 )
{
glVertex3f( 0, y, -limit );
glVertex3f( 0, y, limit );
}
y+=gridSize;
}
}
glEnd();
}
bool GLWidget::showGrid( int idx, bool show )
{
bool old = mShowGrid[idx];
mShowGrid[idx] = show;
updateGL();
return old;
}
bool GLWidget::showCameraTarget( bool show )
{
bool old=mShowCameraTarget;
mShowCameraTarget = show;
updateGL();
return old;
}
bool GLWidget::showBoxes(bool show/*=true*/)
{
bool old=mDrawBoxes;
mDrawBoxes=show;
updateGL();
return old;
}
rk_geometry.h
#include <cmath>
namespace rkGeom
{
class CPoint;
class CVector;
inline bool equal(double x, double y, double epsilon = 0.000001) {
return fabs(x - y) <= epsilon;
}
// A class for 3-D Vectors.
//
// v.i, v.j, v.k Components of vector v
// Vector(i, j, k) Construct from components
// Vector(p) Construct from a point
// u + v, u += v Vector addition
// u - v, u -= v Vector subtraction
// -v <0, 0, 0> - v
// u.dot(v) Dot product of u and v
// u.cross(v) Cross product of u and v
// v * c, c * v, v *= c Multiplication of a vector and a scalar
// v / c, v /= c Division of a vector by a scalar
// v.magnitude() The length of v
// unit(v) The vector of length 1 in the direction of v
// normalize(v) Changes v to unit(v)
// cosine(u, v) The cosine of the angle from u to v
class CVector
{
public:
double i, j, k;
CVector(double i = 0, double j = 0, double k = 0): i(i), j(j), k(k) {}
CVector(CPoint p);
CVector operator +(CVector v) {return CVector(i + v.i, j + v.j, k + v.k);}
CVector& operator +=(CVector v) {i += v.i; j += v.j; k += v.k; return *this;}
CVector operator -(CVector v) {return CVector(i - v.i, j - v.j, k - v.k);}
CVector& operator -=(CVector v) {i -= v.i; j -= v.j; k -= v.k; return *this;}
CVector operator -() {return CVector(-i, -j, -k);}
double dot(CVector v) {return i * v.i + j * v.j + k * v.k;}
CVector cross(CVector);
CVector operator *(double c) {return CVector(i * c, j * c, k * c);}
friend CVector operator *(double c, CVector v) {return v * c;}
CVector& operator *=(CVector v) {i *= v.i; j *= v.j; k *= v.k; return *this;}
CVector operator /(double c) {return CVector(i / c, j / c, k / c);}
CVector& operator /=(double c) {i /= c; j /= c; k /= c; return *this;}
double magnitude() {return sqrt(this->dot(*this));}
friend CVector unit(CVector v) {return v / v.magnitude();}
friend void normalize(CVector& v) {v /= v.magnitude();}
friend double cosine(CVector u, CVector v) {return unit(u).dot(unit(v));}
};
// A class for 3-D Points.
//
// p.x, p.y, p.z Components (coordinates) of point p
// p + v, p += v Add a point to a vector
// p - q The vector from q to p
// p.distanceTo(q) The distance between p and q
// p.distanceTo(P) The distance between p and the plane P
class CPoint
{
public:
double x, y, z;
CPoint(double x = 0, double y = 0, double z = 0): x(x), y(y), z(z) {}
CPoint operator +(CVector v) {return CPoint(x + v.i, y + v.j, z + v.k);}
CPoint& operator +=(CVector v) {x += v.i; y += v.j; z += v.k; return *this;}
CPoint& operator -=(CVector v) {x -= v.i; y -= v.j; z -= v.k; return *this;}
CVector operator -(CPoint p) {return CVector(x - p.x, y - p.y, z - p.z);}
double distanceTo(CPoint p) {return (p - *this).magnitude();}
};
inline CVector::CVector(CPoint p): i(p.x), j(p.y), k(p.z) {
}
inline CVector CVector::cross(CVector v) {
return CVector(j * v.k - k * v.j, k * v.i - i * v.k, i * v.j - j * v.i);
}
}
主窗口.h
#include <QMainWindow>
#include "GLWidget.h"
#include <math.h>
#include <QComboBox>
namespace Ui {
class MainWindow;
}
class MainWindow :public QMainWindow
{
Q_OBJECT
public :
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots :
void showModel(int index);
private :
Ui::MainWindow *ui;
GLWidget *openglWidget1;
};
主窗口.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui -> setupUi(this);
openglWidget1 = new GLWidget();
openglWidget1->setRenderMode(0);
ui->verticalLayout->addWidget(openglWidget1);
connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(showModel(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::showModel(int index)
{
switch(index)
{
case 0:
{
openglWidget1->setRenderMode(0);
openglWidget1->updateGL();
}
break;
case 1:
{
openglWidget1->setRenderMode(1);
openglWidget1->setFrameImage(cv::imread("D:/Test switching/build/wireframe.jpg"));
openglWidget1->updateGL();
}
break;
}
}
ui_mainwindow.h
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout"/>
</item>
<item row="1" column="0">
<widget class="QComboBox" name="comboBox">
<item>
<property name="text">
<string>Cube</string>
</property>
</item>
<item>
<property name="text">
<string>Image</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
主文件
#include <qapplication.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "mainwindow.h"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
和CMakeLists
cmake_minimum_required(VERSION 2.6)
PROJECT(test)
FIND_PACKAGE(Qt4 REQUIRED)
INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})
FIND_PACKAGE(OpenCV REQUIRED)
SET(test_HEADERS GLWidget.h mainWindow.h)
SET(test_SOURCES GLWidget.cpp mainwindow.cpp main.cpp)
SET(test_FORMS mainwindow.ui)
QT4_WRAP_UI(test_FORMS_HEADERS ${test_FORMS})
QT4_WRAP_CPP(test_HEADERS_MOC ${test_HEADERS})
ADD_EXECUTABLE(test ${test_SOURCES} ${test_FORMS_HEADERS} ${test_HEADERS_MOC})
TARGET_LINK_LIBRARIES(test ${QT_LIBRARIES} ${OpenCV_LIBRARIES})