在指定的时间在qglwidget上绘制一个rect 我在Ubuntu 16.04上用C++使用Qt 5.7。我试图实现一个继承qglwidget的类,它以给定的速率(3-10 Hz)将图像渲染到屏幕上
除此之外,我想在屏幕上的某个地方画一个小矩形,它的颜色从黑色变为白色,反之亦然。当图像出现时,它应该从白色切换到黑色,并在下一个图像出现之前的某个预定义时间切换回黑色。 现在我正在使用纹理加载图像(来自QImage对象),使用 这是我的paintGL()重载:在指定的时间在qglwidget上绘制一个rect 我在Ubuntu 16.04上用C++使用Qt 5.7。我试图实现一个继承qglwidget的类,它以给定的速率(3-10 Hz)将图像渲染到屏幕上,c++,qt,opengl,rendering,C++,Qt,Opengl,Rendering,除此之外,我想在屏幕上的某个地方画一个小矩形,它的颜色从黑色变为白色,反之亦然。当图像出现时,它应该从白色切换到黑色,并在下一个图像出现之前的某个预定义时间切换回黑色。 现在我正在使用纹理加载图像(来自QImage对象),使用 这是我的paintGL()重载: glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); drawTexture(QRect(0,0,1,1),texture,GL_TEXTUR
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
drawTexture(QRect(0,0,1,1),texture,GL_TEXTURE_2D);
swapBuffers();
glDisable(GL_TEXTURE_2D);
我想知道是否有可能在这个小部件上画图,让它同时呈现rect和image。我尝试过使用QPainter,但一直得到这样的结论:绘制矩形会使图像消失(矩形不应该出现在图像上,而是在小部件的某个角落,现在什么都没有绘制)
非常感谢您的帮助 这是一个最小的示例应用程序,它在paint handler中混合了OpenGL代码和
QPaint
:
#include <QtWidgets>
#include <QOpenGLFunctions_1_1>
// manually added types (normally provided by glib)
typedef unsigned guint;
typedef unsigned char guint8;
extern const struct Image {
guint width;
guint height;
guint bytes_per_pixel; /* 3:RGB, 4:RGBA */
guint8 pixel_data[1];
} fluffyCat;
class GLWidget: public QOpenGLWidget, protected QOpenGLFunctions_1_1 {
private:
float _step;
GLuint _idTex;
QTimer _qTimer;
public:
GLWidget(QWidget *parent = 0):
QOpenGLWidget(parent),
_step(0.0f), _idTex(0)
{
_qTimer.setInterval(100); // 100 ms -> 10 Hz
QObject::connect(&_qTimer, &QTimer::timeout,
this, &GLWidget::timeout);
}
protected:
virtual void initializeGL();
virtual void paintGL();
private:
void timeout();
};
void GLWidget::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(0.525, 0.733f, 0.851, 1.0);
glGenTextures(1, &_idTex);
glBindTexture(GL_TEXTURE_2D, _idTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, fluffyCat.width, fluffyCat.height, 0,
GL_RGB, GL_UNSIGNED_BYTE, fluffyCat.pixel_data);
glBindTexture(GL_TEXTURE_2D, 0);
_qTimer.start();
}
void GLWidget::paintGL()
{
// prepare OpenGL rendering
QPainter qPainter(this);
qPainter.beginNativePainting();
// do OpenGL rendering
glColor3f(1.0f, 1.0f, 1.0f);
bool tex2dOld = glIsEnabled(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
static GLfloat envColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor);
glBindTexture(GL_TEXTURE_2D, _idTex);
float x = sin(_step) * 0.5f, y = cos(_step) * 0.5f;
#if 0 // does not work (no tex-coords)
glRectf(x - 0.5f, y - 0.5f, x + 0.5f, y + 0.5f);
#else // (not) 0
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glTexCoord2i(0, 1);
glVertex2f(x - 0.5f, y - 0.5f);
glTexCoord2i(1, 1);
glVertex2f(x + 0.5f, y - 0.5f);
glTexCoord2i(1, 0);
glVertex2f(x + 0.5f, y + 0.5f);
glTexCoord2i(0, 0);
glVertex2f(x - 0.5f, y + 0.5f);
glEnd();
#endif // 0
glBindTexture(GL_TEXTURE_2D, 0);
//if (!tex2dOld) glDisable(GL_TEXTURE_2D);
// prepare Qt painting
qPainter.endNativePainting();
// do Qt painting (HUD)
QPen qPen;
qPen.setWidth(1);
qPen.setColor(QColor(Qt::black));
qPen.setStyle(Qt::SolidLine);
qPainter.resetMatrix();
qPainter.setPen(qPen);
qPainter.drawLine(0, 0, width(), height());
qPainter.drawLine(0, height(), width(), 0);
}
void GLWidget::timeout()
{
_step = fmod(_step + 0.1, 2 * 3.141);
update(); // force redraw
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QMainWindow win;
GLWidget view3d;
win.setCentralWidget(&view3d);
win.show();
return app.exec();
}
顺便说一下,我没有意识到OP要求的是QGLWidget
。该示例使用新的QOpenGLWidget
,这是自Qt5+以来推荐的
QTimer
用于制作非常简单的动画(表示已完成定期绘制)
顺便说一句,我偶然发现了一个错误(这不是第一次击中我…)
设置
GL\u TEXTURE\u MIN\u FILTER
和GL\u TEXTURE\u MAG\u FILTER
非常重要,因为这是两种罕见的OpenGL状态,如果保留默认值则无法工作。这是一个最小的示例应用程序,它在paint handler中混合了OpenGL代码和qPaint
:
#include <QtWidgets>
#include <QOpenGLFunctions_1_1>
// manually added types (normally provided by glib)
typedef unsigned guint;
typedef unsigned char guint8;
extern const struct Image {
guint width;
guint height;
guint bytes_per_pixel; /* 3:RGB, 4:RGBA */
guint8 pixel_data[1];
} fluffyCat;
class GLWidget: public QOpenGLWidget, protected QOpenGLFunctions_1_1 {
private:
float _step;
GLuint _idTex;
QTimer _qTimer;
public:
GLWidget(QWidget *parent = 0):
QOpenGLWidget(parent),
_step(0.0f), _idTex(0)
{
_qTimer.setInterval(100); // 100 ms -> 10 Hz
QObject::connect(&_qTimer, &QTimer::timeout,
this, &GLWidget::timeout);
}
protected:
virtual void initializeGL();
virtual void paintGL();
private:
void timeout();
};
void GLWidget::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(0.525, 0.733f, 0.851, 1.0);
glGenTextures(1, &_idTex);
glBindTexture(GL_TEXTURE_2D, _idTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, fluffyCat.width, fluffyCat.height, 0,
GL_RGB, GL_UNSIGNED_BYTE, fluffyCat.pixel_data);
glBindTexture(GL_TEXTURE_2D, 0);
_qTimer.start();
}
void GLWidget::paintGL()
{
// prepare OpenGL rendering
QPainter qPainter(this);
qPainter.beginNativePainting();
// do OpenGL rendering
glColor3f(1.0f, 1.0f, 1.0f);
bool tex2dOld = glIsEnabled(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
static GLfloat envColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor);
glBindTexture(GL_TEXTURE_2D, _idTex);
float x = sin(_step) * 0.5f, y = cos(_step) * 0.5f;
#if 0 // does not work (no tex-coords)
glRectf(x - 0.5f, y - 0.5f, x + 0.5f, y + 0.5f);
#else // (not) 0
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glTexCoord2i(0, 1);
glVertex2f(x - 0.5f, y - 0.5f);
glTexCoord2i(1, 1);
glVertex2f(x + 0.5f, y - 0.5f);
glTexCoord2i(1, 0);
glVertex2f(x + 0.5f, y + 0.5f);
glTexCoord2i(0, 0);
glVertex2f(x - 0.5f, y + 0.5f);
glEnd();
#endif // 0
glBindTexture(GL_TEXTURE_2D, 0);
//if (!tex2dOld) glDisable(GL_TEXTURE_2D);
// prepare Qt painting
qPainter.endNativePainting();
// do Qt painting (HUD)
QPen qPen;
qPen.setWidth(1);
qPen.setColor(QColor(Qt::black));
qPen.setStyle(Qt::SolidLine);
qPainter.resetMatrix();
qPainter.setPen(qPen);
qPainter.drawLine(0, 0, width(), height());
qPainter.drawLine(0, height(), width(), 0);
}
void GLWidget::timeout()
{
_step = fmod(_step + 0.1, 2 * 3.141);
update(); // force redraw
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QMainWindow win;
GLWidget view3d;
win.setCentralWidget(&view3d);
win.show();
return app.exec();
}
顺便说一下,我没有意识到OP要求的是QGLWidget
。该示例使用新的QOpenGLWidget
,这是自Qt5+以来推荐的
QTimer
用于制作非常简单的动画(表示已完成定期绘制)
顺便说一句,我偶然发现了一个错误(这不是第一次击中我…)
设置
GL\u TEXTURE\u MIN\u FILTER
和GL\u TEXTURE\u MAG\u FILTER
非常重要,因为这是两种罕见的OpenGL状态,如果保留默认值则无法工作。好吧,最后这对于添加一个小的rect-
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
QPainter qPainter(this);
QPainterPath path;
path.addRect(10, 10, 30,30);
QPen pen(Qt::black, 1);
qPainter.setPen(pen);
qPainter.fillPath(path, Qt::black);
qPainter.drawPath(path);
qPainter.end();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glShadeModel( GL_FLAT );
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_TEXTURE_2D);
glColor3f(0.5, 0.5, 0);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.5f, -0.5f); // vertex 1
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.5f, 0.5f); // vertex 2
glTexCoord2f(1.0f, 0.0f); glVertex2f(-0.5f, 0.5f); // vertex 3
glTexCoord2f(1.0f, 1.0f); glVertex2f(-0.5f, -0.5f); // vertex 4
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
好的,最后这对添加一个小的rect-
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
QPainter qPainter(this);
QPainterPath path;
path.addRect(10, 10, 30,30);
QPen pen(Qt::black, 1);
qPainter.setPen(pen);
qPainter.fillPath(path, Qt::black);
qPainter.drawPath(path);
qPainter.end();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glShadeModel( GL_FLAT );
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_TEXTURE_2D);
glColor3f(0.5, 0.5, 0);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.5f, -0.5f); // vertex 1
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.5f, 0.5f); // vertex 2
glTexCoord2f(1.0f, 0.0f); glVertex2f(-0.5f, 0.5f); // vertex 3
glTexCoord2f(1.0f, 1.0f); glVertex2f(-0.5f, -0.5f); // vertex 4
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
如果使用了
QPainter
,则假定它具有对OpenGL状态的独占访问权限。如果直接使用OpenGL API,则必须在调用QPainter
-API之前恢复某些状态。通过这种方式,我解决了在使用OpenGL渲染3d场景后使用qPaint
渲染HUD的问题因为这应该由QGLWidget
完成。(我必须查看我的源代码以提供更多细节。)您必须知道QOpenGLFunctions
方法的使用和调用GL函数(从任何非Qt库)是不同的。这是可能的,尤其是在文件中。例如。如果调用“非Qt”OpenGL函数,这可能会绕过Qt中的内部状态跟踪。您是否注意到我在回答末尾添加的关于GL_纹理_MIN_过滤器
和GL_纹理_MAG_过滤器
的提示?如果使用QPainter
,则假定对OpenGL状态具有独占访问权限。如果直接使用OpenGL API,则必须在调用QPainter
-API之前恢复某些状态。通过这种方式,我解决了在使用OpenGL渲染3d场景后使用qPaint
渲染HUD的问题因为这应该由QGLWidget
完成。(我必须查看我的源代码以提供更多细节。)您必须知道QOpenGLFunctions
方法的使用和调用GL函数(从任何非Qt库)是不同的。这是可能的,尤其是在文件中。例如。如果调用“非Qt”OpenGL函数,这可能会绕过Qt中的内部状态跟踪。您是否注意到关于GL_TEXTURE\u MIN_FILTER
和GL_TEXTURE\u MAG_FILTER
的提示,这是我在回答末尾添加的?当我刚刚创建Qpainter(使用Qpainter Qpainter(this)),它会覆盖我正在绘制的纹理,即使我没有打电话给其他绘画指导。你知道为什么吗?我还尝试了整个代码块,但它不起作用,只是画对角线。@JLev我明确要求QOpenGLFunctions\u 1\u 1
像您那样使用OpenGL 1.1。默认的QOpenGLFunctions
不再提供glColor3f()
和glRectf()
。(它在OpenGL 3+中被弃用)也许,您的OpenGL驱动程序不支持请求的OpenGL 1.1函数(尽管-这很难相信…@JLev我试图记住如果QOpenGLFunctions
xx无法绑定请求的OpenGL函数会发生什么。我在Qtqopengelfunctions
doc中找不到任何成功的检索函数。我想,在这种情况下,它简直崩溃了。(我曾经在一个colaborator的Windows计算机上的驱动程序更新失败时看到过这种情况,并在没有适当的OpenGL支持的情况下退回到通用驱动程序。关于Linux我不知道。)我尝试切换到QopenGlwidget,但无法初始化QOpenGLFunctions。我不需要它,你在哪里看到我在使用它?QOpenGLFunctions
是属于Qt的openglapi。Qt建议使用它,但这不是必须的。在我们(公司)的项目中,我们从QOpenGLFunctions
开始,但后来切换到自己的OpenGL C绑定,因为我们希望使用独立于Qt的GL渲染代码。它确实有效,但不需要额外的努力。正如我已经说过的,如果GL状态发生更改,Qt可能会在内部跟踪这些状态,如果在执行“非Qt”OpenGL渲染代码后这些状态没有恢复,Qt代码可能会崩溃。顺便说一句,你可以吗