問(wèn)題描述
我在 ubuntu 16.04 上使用 Qt 5.7 和 C++.我正在嘗試實(shí)現(xiàn)一個(gè)繼承 qglwidget 的類,該類以給定的速率(3-10 Hz)將圖像呈現(xiàn)到屏幕上.
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).
除此之外,我想在屏幕上的某處繪制一個(gè)小矩形,將其顏色從黑色變?yōu)榘咨粗嗳?當(dāng)圖像出現(xiàn)時(shí)它應(yīng)該從白色切換到黑色,并在下一個(gè)圖像出現(xiàn)之前的某個(gè)預(yù)定義時(shí)間切換回黑色.現(xiàn)在我正在使用紋理加載圖像(來(lái)自 QImage 對(duì)象),使用
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);
我想知道是否可以在小部件上繪制并使其同時(shí)呈現(xiàn)矩形和圖像.我試過(guò)使用 QPainter,但一直在繪制矩形使圖像消失(矩形不應(yīng)該在圖像上,而是在小部件的某個(gè)角落,現(xiàn)在什么都沒(méi)有繪制).
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).
非常感謝您的幫助!
推薦答案
這是一個(gè)最小的示例應(yīng)用程序,它在繪制處理程序中混合了 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();
}
和紋理圖像的來(lái)源:
/* 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",
};
(抱歉,圖片質(zhì)量太低.高分辨率圖片對(duì)于本網(wǎng)站來(lái)說(shuō)太大了.)
(Sorry, for the low image quality. Hi-res picture whould have been too large for this site.)
這兩個(gè)文件必須編譯并鏈接在一起.(我沒(méi)有使用標(biāo)題,而是在另一個(gè)文件的開(kāi)頭(重新)在 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 項(xiàng)目文件testQGLWidgetHUD.pro
:
SOURCES = testQGLWidgetHUD.cc fluffyCat.cc
QT += widgets opengl
順便說(shuō)一下,我沒(méi)有意識(shí)到 OP 要求 QGLWidget
.該示例使用了自 Qt5+ 以來(lái)推薦的新 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
用于非常簡(jiǎn)單的動(dòng)畫(huà)類型(以顯示周期性繪畫(huà)已完成).
The QTimer
is used for very simple kind of animation (to show that periodical painting is done).
順便說(shuō)一句.我偶然發(fā)現(xiàn)了一個(gè)錯(cuò)誤(這不是第一次打擊我......)設(shè)置 GL_TEXTURE_MIN_FILTER
和 GL_TEXTURE_MAG_FILTER
很重要,因?yàn)檫@是兩個(gè)罕見(jiàn)的 OpenGL 狀態(tài),如果保留默認(rèn)值,它們將不起作用.
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.
這篇關(guān)于在特定時(shí)間在 qglwidget 上繪制一個(gè)矩形的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!