PDA

View Full Version : Render QWidget within QGLWidget



crazymonkey
16th September 2010, 20:09
Hello All This is my first post on this forum. but i have a question (i dont know if it is a newbie question or not)

I have been using/learning Qt over the past week or so, I'm comfortable with Qt and OpenGL to the point where i know how to use standard OpenGL API commands within Qt.

Firstly I have done some searching and found http://doc.trolltech.com/qq/qq26-openglcanvas.html which is exactly what im trying to achieve, but when i try to compile and run the example code it doesn't work. these widgets also need to have their own event listeners etc...

does anybody know if this is the only way to do this? any help will be appreciated.

Thanks

Crazymonkey

JohannesMunk
16th September 2010, 20:13
Hi!

What doesn't work? Describe the problem! What event listeners?

Joh

crazymonkey
16th September 2010, 20:27
This qWarning pops up several times when i run the program.


if (painter->paintEngine()->type() != QPaintEngine::OpenGL) {
qWarning("OpenGLScene: drawBackground needs a QGLWidget to be set as viewport on the graphics view");
return;
}

JohannesMunk what I meant to say is that these Widgets which are embedded within my QGLWidget Scene must be able to handle their own event listeners as well


PS im running Qt 4.7.0 with Qt Creator 2.0

JohannesMunk
16th September 2010, 20:35
Well the warning says that your viewport setup didn't work.
Did you copy/leave this line in place?


view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
Yes for sure if you want the widgets to work in a certain way, you will have to code their eventhandlers.

What do you want to do? Where is the problem?

Joh

crazymonkey
16th September 2010, 20:46
Joh i never altered the above code in any way. it's just giving me those errors (those qWarnings)

What could the problem be? is it my PC?

I ultimately want to embed a normal QWidget within a QGLWidget. at the moment all i have is a QGLWidget which renders my scene. now i want to add those widgets ontop so i can get user input/output.

JohannesMunk
16th September 2010, 21:04
Ok. Step by step. You need to setup a QGraphicsView/Scene properly.


main.cpp:

#include <QtCore>
#include <QtGui>

#include "main.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

MainWindow w;
w.show();
return a.exec();
}

---------------------------
main.h:

#ifndef MAIN_H
#define MAIN_H

#include <QtCore>
#include <QtGui>
#include <QtOpenGL>

using namespace std;

class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget *parent = 0);
private:
QGraphicsScene *scene;
QGraphicsView *graphicsView;
};

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
scene = new QGraphicsScene();

QPushButton* btn = new QPushButton("Test");
scene->addWidget(btn);

graphicsView = new QGraphicsView(this);
graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
graphicsView->setScene(scene);
graphicsView->setGeometry(QRect(50, 50, 500, 300));
graphicsView->show();

this->setCentralWidget(graphicsView);

}

#endif // MAIN_HDon't forget to add

QT += opengl

to your pro file.

Does that work?

Joh

JohannesMunk
16th September 2010, 21:18
Now we render the background of the scene with our own OpenGL calls..



#ifndef MAIN_H
#define MAIN_H

#include <QtCore>
#include <QtGui>
#include <QtOpenGL>

using namespace std;

class OpenGLScene : public QGraphicsScene
{
public:
OpenGLScene() {

}
protected:
void drawBackground(QPainter *painter, const QRectF &);
};

void OpenGLScene::drawBackground(QPainter *painter, const QRectF &)
{
/*if (painter->paintEngine()->type() != QPaintEngine::OpenGL) {
qWarning("OpenGLScene: drawBackground needs a "
"QGLWidget to be set as viewport on the "
"graphics view");
return;
}*/
//
QColor m_backgroundColor = QColor("yellow");
glClearColor(m_backgroundColor.redF(),
m_backgroundColor.greenF(),
m_backgroundColor.blueF(), 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}


class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget *parent = 0);
private:
OpenGLScene *scene;
QGraphicsView *graphicsView;
};



MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
scene = new OpenGLScene();

QPushButton* btn = new QPushButton("Test");
scene->addWidget(btn);

graphicsView = new QGraphicsView(this);
graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
graphicsView->setScene(scene);
graphicsView->setGeometry(QRect(50, 50, 500, 300));
graphicsView->show();

this->setCentralWidget(graphicsView);

}

#endif // MAIN_H

Aah! Something is wrong with this check! Did produce the same warning here. But the OpenGL stuff obviously works!

Joh

JohannesMunk
16th September 2010, 21:21
That check should be nowadays:



if ((painter->paintEngine()->type() != QPaintEngine::OpenGL2) &&
(painter->paintEngine()->type() != QPaintEngine::OpenGL))
{
qWarning("OpenGLScene: drawBackground needs a "
"QGLWidget to be set as viewport on the "
"graphics view");
return;
}
HIH

Joh

crazymonkey
17th September 2010, 11:40
Thanks Joh ill try the above mentioned when i get back from work

speaking of which, i tried to run the qq26-openglcanvas program on an Ubuntu 10.04 PC with Qt 4.6.2 and this code runs fine. howcome?

BTW my home PC is Windows 7 using Qt 4.7.0

JohannesMunk
17th September 2010, 11:44
I guess your Ubuntu only supports/has drivers for OpenGL 1.0.
Happy coding

crazymonkey
18th September 2010, 12:47
Thanks Joh, youve helped alot!

quick question: where do i make my usual updateGL() , resizeGL() and paintGL() calls then?

JohannesMunk
18th September 2010, 12:55
You don't!

paintGL => drawBackground
or if you want individual items, subclass QGraphicsItem implement boundingRect and paintEvent (using either QPainter stuff or native OpenGL calls with QPainter.beginNativePainting() .. )

http://www.qtcentre.org/threads/34148-Qt-and-OpenGl-(I-m-lost)?p=158675#post158675 (http://www.qtcentre.org/threads/34148-Qt-and-OpenGl-%28I-m-lost%29?p=158675#post158675)

resizeGL => taken care of the view, otherwise subclass QGraphicsView, implement resizeEvent.
updateGL => not necessary.

Joh

crazymonkey
18th September 2010, 13:02
and if i want to use listeners to zoom in/out of my openGL scene is it done in the same way as i would normally do it?

JohannesMunk
18th September 2010, 13:20
Yes. You can then update the view either manually (view->update()), when something changes - or periodically with a Timer (fixed framerate), depends.

Or you split your scene and implement different QGraphicsItems. Call their update() function to trigger a redraw of them.

Joh

crazymonkey
19th September 2010, 10:24
Sorry and what about initializeGL() ??

im very noob sorry for all these questions! :D

JohannesMunk
19th September 2010, 11:58
InitializeGL. Bit tricky that one.

Your example http://doc.trolltech.com/qq/qq26-openglcanvas.html doesn't use any opengl initialization. Does it on every repaint.

drawBackground is called every 20ms due to (view.setViewportUpdateMode(QGraphicsView::FullVie wportUpdate); in main.cpp and QTimer::singleShot(20, this, SLOT(update())); at the end of drawBackground)

If that's too expensive for you, because you need to setup big displaylists or something like that, you could:

1) Do one of these: http://stackoverflow.com/questions/1112167/calling-qts-qgraphicsviewsetviewport-with-a-custom-qglwidget

2) Have a look at the boxes demo: http://doc.trolltech.com/latest/demos-boxes.html

3) "Dirty", but efficient Hack:



class OpenGLScene : ..
{
private:
bool initialized;
}

OpenGLScene::OpenGLScene(..)
{
initialized = false;
}

void OpenGLScene::drawBackground(QPainter *painter, const QRectF &)
{
if (initialized == false)
{
// your initialization goes here..
initialized = true;
}
}Joh

crazymonkey
19th September 2010, 18:23
hello Joh im having difficulty in adding new widgets

i think this is more of a Qt specific question but what command can i use to set the position of my widgets on my scene?

i have added widgets made via Qt designer perfectly fine. but now i want to make them movable with mouse dragging.

also my widget doesn't have a title like in the example shown http://doc.trolltech.com/qq/qq26-openglcanvas.html

how do i make them movable via mouse dragging and how do i show a title (eg "Instructions")

JohannesMunk
20th September 2010, 13:57
Hi!

You could have looked it up in the example you referred to!



QWidget* w = new QWidget();
w->setGeometry(0,0,150,150);
w->setWindowTitle("Title");
QGraphicsProxyWidget* proxy = scene->addWidget(w);
proxy->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
proxy->setPos(10,10);

Cheers!

Joh

crazymonkey
20th September 2010, 18:39
sorry i meant how do make it draggable across the scene?

JohannesMunk
20th September 2010, 18:51
you can take it and drag it around this way. what else do you want?

crazymonkey
20th September 2010, 19:45
Just to put things into perspective im trying to load a heightmap in OpenGL which i know how to do.

When i try to make a reasonably simple widget like eg

http://i51.tinypic.com/30tjlmh.jpg

the above image shows how far i am (the white square is the "space" where my heightmap will go dont worry about it)

I cant edit the line edit or i cant move the box around, i have been tinkering with this for quite a while now. im not sure whynot, ive tried 3 different examples im doing the exact same thing as the other examples. i cant seem to click/select anything within my widgets

JohannesMunk
20th September 2010, 19:52
Have you overwritten the scenes event (mouse keyb) handlers? Then don't forget to call the inherited ones!

Have you enabled the item flag focusable?

Thx for sharing the screenshot. Puts things into perspective :->

Joh

crazymonkey
20th September 2010, 20:19
ive only implemented listeners for my openGLScene. for moving up down left and right through my scene (even they dont work properly yet but ill get there)

crazymonkey
20th September 2010, 22:43
Feel like such an idiot. my problem was that i didnt pass the mouseMoveEvent/mousePressEvent to QGraphicsScene base class

JohannesMunk
20th September 2010, 22:51
That's what I said! call the inherited ones!

Good night,

Johannes

crazymonkey
21st September 2010, 21:54
Im running into problems when i change the layout of my Widget in Qt designer, i clean project files, rebuild all and when i run the program it doesnt show the changes made to my widget. is there any reason for this? :O kinda stuck here?

JohannesMunk
21st September 2010, 22:00
Maybe you are editing a different file with the designer than the one that is used in the project?

Create a new directory, copy your source files to it. Create an empty new project. Add your files to it. Make sure the project file is correct / compare with the old one. Go to bed :->

BTW: This is a totally new question.. and has nothing to do with this thread.

Joh

crazymonkey
22nd September 2010, 10:58
ahh nvm i had it running the debug build instead of the release build. Ah learning new things the hard way :D

crazymonkey
26th September 2010, 13:49
Hey Joh

When i try to render my scene in wireframe using

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

It also "draws" my widget wireframe and it looks horrible

any way in which i can circumvent this problem?

edit: nvm

JohannesMunk
26th September 2010, 13:54
yes: reset that at the end of your drawing.

OpenGL is a state machine. You always should revert things back to the way they were.

Joh