Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
205 views
in Technique[技术] by (71.8m points)

c++ - Paint a rect on qglwidget at specifit times

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

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

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

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

Would appreciate any help!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

and the source for the texture image:

/* 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.)

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

The Qt project file testQGLWidgetHUD.pro:

SOURCES = testQGLWidgetHUD.cc fluffyCat.cc

QT += widgets opengl

Snapshot of the testQGLWidgetHUD

By the way, I didn't realize the OP was asking for QGLWidget. The sample uses the new QOpenGLWidget which is recommended since Qt5+.

The QTimer is used for very simple kind of animation (to show that periodical painting is done).

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...