问题描述
我在 ubuntu 16.04 上使用 Qt 5.7 和 C++.我正在尝试实现一个继承 qglwidget 的类,该类以给定的速率(3-10 Hz)将图像呈现到屏幕上.
I'm using Qt 5.7 with c++ on ubuntu 16.04. I'm trying to implement a class that inherits qglwidget, that renders images to the screen at a given rate (3-10 Hz).
除此之外,我想在屏幕上的某处绘制一个小矩形,将其颜色从黑色变为白色,反之亦然.当图像出现时它应该从白色切换到黑色,并在下一个图像出现之前的某个预定义时间切换回黑色.现在我正在使用纹理加载图像(来自 QImage 对象),使用
In addition to that I want to draw a small rect somewhere on the screen that changes its color from black to white and vice-versa. It should switch from white to black when the image appears, and switch back to black some predefined time before the next image comes. Right now I'm using a texture to load the images (from QImage objects), using
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
这是我的paintGL()重载:
and this is my paintGL() overload:
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);
我想知道是否可以在小部件上绘制并使其同时呈现矩形和图像.我试过使用 QPainter,但一直在绘制矩形使图像消失(矩形不应该在图像上,而是在小部件的某个角落,现在什么都没有绘制).
and I was wondering if it possible to draw on the widget and make it render both the rect and image at the same time. I've tried using QPainter but kept getting that drawing the rect made the image disappear(the rect shouldn't be on the image, but on some corner of the widget where nothing is drawn now).
非常感谢您的帮助!
推荐答案
这是一个最小的示例应用程序,它在绘制处理程序中混合了 OpenGL 代码和 QPainter
:
This is a minimal sample application which mixes OpenGL code and QPainter
in paint handler:
#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();
}
和纹理图像的来源:
/* GIMP RGB C-Source image dump (fluffyCat.cc) */
// manually added types (normally provided by glib)
typedef unsigned guint;
typedef unsigned char guint8;
struct Image {
guint width;
guint height;
guint bytes_per_pixel; /* 3:RGB, 4:RGBA */
guint8 pixel_data[16 * 16 * 3 + 1];
};
extern const Image fluffyCat;
const Image fluffyCat = {
16, 16, 3,
"x211s215232200gw`fx`at[cx^cw^fu\itZerWn|ap~cv204jnzedq^fr^kzfhv^Ra"
"GRbMWdR\jXer^qw_311256226271253235275264252315277260304255"
"231u~i213225207l{fly`jx\^nRlz_z206nlx`t~i221211s372276243375"
"336275376352340356312301235216212judgwcl~f212226u}206h212"
"224q231237z232236{216225v225230200306274244376360327376"
"361331376360341326275272253240244{203p202220xp~e{204^222"
"230n212217g240242{234236z214222r270271247360353340376370"
"336376363334375357336310254262232223234\gRfrX204220z212"
"225g225232j254255177252250{225226u304302265374365351376"
"375366376367341376361320374346324306241242237232235n{fj"
"xckyfu~fUX@VZCfnT231231207374374371377372354376376374376376"
"372376362332375340301341300264260253262jvdbq\XkVJTDNTCCG8O"
"TE322321313377377375376376373376377376376376375376374362"
"376360342344311306250244254R_PL^HXkT<@2OP@`dP217220177374374"
"370377377374376375371377377376376374360377367336376350"
"316342303274246236245jtbXdQTdNQYGU\KchV317315302377376372377"
"376367376373360377376367376366337376355312374331271323"
"263251216214214\hTP^HL\FR[LMXI^dW355352342376375366377374"
"360376374361376374361376356321374331264374330266330270"
"260200||Y`SLVE>K9BJ<CN?VYP347330322376366345376363330376367"
"337377372350374342314326243210375350314352317304shc^`TV`"
"RVbT>B4IS?PTD244232216374355320376354311376351306376362332"
"374344321267206u375362337326274272\POMNBT]LNZH:<*<A*TV>OI;242"
"222207340304243375335262372336272376361334320241212374"
"352322266233237c\WFH;MR>\`F~xP220214[pqE211202\g]=230214`313"
"266207344303240362336274323257201333304240305252204254"
"232p216206\206203U232224b234244b246257m220232`224227h~202"
"W206213]204210W227227i|177RvzNlsGrtJwtLz}N{204RlxF",
};
(抱歉,图片质量太低.高分辨率图片对于本网站来说太大了.)
(Sorry, for the low image quality. Hi-res picture whould have been too large for this site.)
这两个文件必须编译并链接在一起.(我没有使用标题,而是在另一个文件的开头(重新)在 fluffyCat.cc 中声明了变量.)
The two files have to compiled and to to be linked together. (Instead of using a header, I simply (re-)declared the variable in fluffyCat.cc at the beginning of the other file.)
Qt 项目文件testQGLWidgetHUD.pro
:
SOURCES = testQGLWidgetHUD.cc fluffyCat.cc
QT += widgets opengl
顺便说一下,我没有意识到 OP 要求 QGLWidget
.该示例使用了自 Qt5+ 以来推荐的新 QOpenGLWidget
.
By the way, I didn't realize the OP was asking for QGLWidget
. The sample uses the new QOpenGLWidget
which is recommended since Qt5+.
QTimer
用于非常简单的动画类型(以显示周期性绘画已完成).
The QTimer
is used for very simple kind of animation (to show that periodical painting is done).
顺便说一句.我偶然发现了一个错误(这不是第一次打击我......)设置 GL_TEXTURE_MIN_FILTER
和 GL_TEXTURE_MAG_FILTER
很重要,因为这是两个罕见的 OpenGL 状态,如果保留默认值,它们将不起作用.
Btw. I stumbled upon a mistake (which hit me not the first time...)
It is important to set GL_TEXTURE_MIN_FILTER
and GL_TEXTURE_MAG_FILTER
because these are two of the rare OpenGL states which do not work if left with default values.
这篇关于在特定时间在 qglwidget 上绘制一个矩形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!