I'm making in Qt an application for educational purposes.. The goal is that students can write any OpenGL code that they want, and see what the results are in a QGLWidget inherited class..
For that I'm trying to use QtScript in this way:
The OpenGL code students write should be executed in a reimplemented painGL() method...
But the problem is that from the script I would generate from their OpenGL code, I can't access OpenGL methods, or enums, or enything, as they are neither Q_INVOKABLE methods nor slots...
Any ideas about how can I do that??
Here is the code:
*.h:
#include <QtOpenGL/QGLWidget>
#include <GL/glu.h>
#include <QColor>
#include <QtScript>
class Graficador : public QGLWidget
{
Q_OBJECT
public:
Graficador(QWidget *parent = 0);
void dibujar(QString);
void ejecutar_script();
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
private:
void draw();
QScriptEngine motor;
QScriptValue valor;
QString orden_motor;
};
*.cpp:
Graficador::Graficador(QWidget *parent)
: QGLWidget(parent)
{
setFormat(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer));
}
void Graficador::initializeGL()
{
qglClearColor(Qt::black);
}
void Graficador::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-w / 2.0, w / 2.0, -h / 2.0, h / 2.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void Graficador::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw();
}
void Graficador::draw()
{
QScriptValue resultado;
resultado = motor.evaluate(orden_motor); //Here is where the script should be executed
}
void Graficador::dibujar(QString orden)
{
orden_motor = orden; //Here I load the script content, which is generated from what the students write
}
void Graficador::ejecutar_script()
{
valor = motor.newQObject(this);
motor.globalObject().setProperty("app",valor);
}
The QString "orden_motor" is the code, which I receive from a QPlainTextEdit, that is a child of the same QMainWindow that Graficador is.. When the student presses a QPushButton, "dibujar" and "ejecutar_script" are executed, as well as "updateGL", which are all members of the Graficador class...
So the script should be executed... But instead, when I read the results of QScriptValue "resultado", I get that none of the functions I don't declare as Q_INVOKED are recognized... And that includes all OpenGL methods, as well as OpenGL enums...
If anybody could throw me some light here, I would really appreciate it!!
The ideal case for me would be that the entire QGLWidget class could be accessible from the script... I know it's not the ideal thing to do, but I think it's the most suitable way to do this...
But again, any ideas are welcome!
Thanks!!
Related
So I have this program should uses a QGLWidget, I'm still relatively new to using OpenGL and QT so I started following this tutorial. However the background of my QGLWidget won't change no matter what I do (I'm using ubuntu not windows). Do I need to create a class for it inside the mainWindow.cpp or is what I've done enough for it to work?
This is what is shown when the program is executed. The QGLWidget on the right is completely black when it show be yellow with a red triangle
Here is the promoted widget of the QGLWidget which is linked to the drawingArea class
Finally here's the code from the drawing area. It compiles fine and I cant see anything wrong with the logic hence my confusion.
drawingarea.h
#ifndef DRAWINGAREA_H
#define DRAWINGAREA_H
#include <QGLWidget>
#include <QOpenGLWindow>
#include <QSurfaceFormat>
#include <QOpenGLFunctions>
#include <QtOpenGL>
#include <GL/glu.h>
class drawingArea : public QGLWidget
{
public:
drawingArea(QWidget *parent=0);
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
void paintEvent(QPaintEvent *event);
private:
QOpenGLContext *context;
QOpenGLFunctions *openGLFunctions;
};
#endif // DRAWINGAREA_H
drawingarea.cpp
#include "drawingarea.h"
drawingArea::drawingArea(QWidget *parent) : QGLWidget(parent)
{
}
void drawingArea::initializeGL()
{
glClearColor(1,1,0,1);
}
void drawingArea::resizeGL(int w, int h)
{
}
void drawingArea::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,0,0);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0);
glVertex3f(0.5,-0.5,0);
glVertex3f(0,0.5,0);
glEnd();
}
void drawingArea::paintEvent(QPaintEvent *event)
{
}
Im searching for an circular progress indication Widget for Qt5 like this:
http://anthonyterrien.com/knob/
Is there something similar or is it possible to do this in Qt?
I want to set the percentage manually, it shouldn't be a spinning circle or something like that
It is very easy to write. You need just special paintEvent() and slot to setProgress(). Of course if you want to add more beauty, then you need spend some time, but here is example:
Header:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPaintEvent>
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
signals:
public slots:
void setProgress(int val);
protected:
void paintEvent(QPaintEvent *);
private:
double progress;
};
#endif // WIDGET_H
cpp:
void Widget::setProgress(int val)
{
progress = (double)val/100;
//yes, it is not very good, the best approach is to
//create something similar to QProgressBar
this->update();
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
QPen pen;
pen.setWidth(7);
pen.setColor(Qt::red);
p.setPen(pen);
p.setRenderHint(QPainter::Antialiasing);
QRectF rectangle(10.0, 20.0, 80.0, 80.0);
//to understand these magic numbers, look drawArc method in Qt doc
int startAngle = -90 * 16;
int spanAngle = progress * 360 * 16;
p.drawArc(rectangle, startAngle, spanAngle);
p.drawText(rectangle,Qt::AlignCenter,QString::number(progress*100)+" %");
}
Usage:
Widget wd;
wd.show();
QSlider sl;
sl.show();
QObject::connect(&sl,SIGNAL(valueChanged(int)),&wd,SLOT(setProgress(int)));
Result:
I showed here main idea, but I think that my code can be improved, for example add methods setMinimum/Maximum and setValue, as in QProgressBar, but I hope you will add additional functionality manually if you need this.
In addition to the above: who needs a simple implementation of what Chernobyl has posted there is a ready class that demonstrates a circular loading.
So my goal is to (first) draw a triangle with openGL.
my questions:
1) How/when do both of my functions get called? I see that only one gets called. i.e. void MyGLWidget::paintGL. I am confused because as you can see I never call this function, it gets called automatically.I added a widget on my ui which I promoted to MyGLWidget. But when/why/how does it get (not) called?
my code:
myglwidget.cpp
#include "myglwidget.h"
#include <QtWidgets>
#include <QtOpenGL>
#include <GL/glu.h>
MyGLWidget::MyGLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
}
void MyGLWidget::initializeGL()
{
glClearColor(1,1,0,1);
qDebug("init"); //<-------never gets printed
}
void MyGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
qDebug("painting"); //<---- does get printed
glColor3f(1,0,0);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0);
glVertex3f(0.5,-0.5,0);
glVertex3f(0.0,0.5,0);
glEnd();
}
myglwidget.h
#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H
#include <QGLWidget>
class MyGLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit MyGLWidget(QWidget *parent = 0);
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
private:
};
#endif // MYGLWIDGET_H
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowTitle("OpenGL with Qt DAO");
w.show();
return a.exec();
}
I do not see a class called Widget made by you which is connected to the class MyGlWidget. Maybe I am wrong but shouldn't you have to make a instance of MyGlWidget (Call it's constructor instead of Widget?)
Both functions are called internally by the QGLWidget super class. See QT Docs
In the documentation you also see that these virtual functions are protected. In your code they are public. So you have to change that in order to make it work.
I'm quite new to Qt. I wanted to create a simple application where there's triangle generated using OpenGL and three push buttons changing that triangle colour.
Here's my code:
In MainWindow.h I declare slots:
public slots:
void redButton(Widget w);
void greenButton(Widget w);
void blueButton(Widget w);
They change colour using function in Widget class:
void MainWindow::redButton(Widget w)
{
w.setColor(red);
}
In widget.h I have:
class Widget : public QGLWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
QSize minimumSizeHint() const;
QSize sizeHint() const;
enum color
{
red,
green,
blue
};
enum color c;
void setColor(enum color color1);
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
};
And function setColor looks like this:
void Widget::setColor(enum color color1)
{
c = color1;
}
Unfortunately I get an error saying:
no matching function forr call to 'Widget::setColor(QPushButton*&)'
w.setColor(red);
//Same goes for blue and green
I don't know what I'm doing wrong.
Well, your function declaration
void Widget::setColor(enum color color1);
obviously doesn't match your calls for
void Widget::setColor(QPushButton*&);
Certainly none of those QPushButton instances, establishes a valid instance of enum color, thus you get those compiler errors.
Although there are similar questions to mine posted on stackoverflow, none of their solutions actually respond to my problem. I have 2 independent widgets that I would like to combine (insert one widget into the other as a child): one is a UI created only with Qt Creator (drag-and-drop), and the other one an animation done in Qt with OpenGL. I am trying to add the animation in the UI and here is the code:
glwidget.h (animation):
class GLWidget : public QGLWidget
{
public:
GLWidget(QWidget *parent);
~GLWidget();
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void drawCube(int i, GLfloat z, GLfloat ri, GLfloat jmp, GLfloat amp);
QGLFramebufferObject *fbo;
};
and glwidget.cpp:
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
makeCurrent();
fbo = new QGLFramebufferObject(512, 512);
timerId = startTimer(20);
}
GLWidget::~GLWidget()
{
glDeleteLists(pbufferList, 1);
delete fbo;
}
void GLWidget::initializeGL()
{....
As for the UI, I have the header file:
class ClaraTeCourseSimulator : public QMainWindow
{
Q_OBJECT
public:
explicit ClaraTeCourseSimulator(QWidget *parent = 0);
~ClaraTeCourseSimulator();
private:
Ui::ClaraTeCourseSimulator *ui;
GLWidget *defaultAnim;
protected:
void setupActions();
protected slots:
void addAnimWidget();
};
and the .cpp file:
ClaraTeCourseSimulator::ClaraTeCourseSimulator(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ClaraTeCourseSimulator)
{
ui->setupUi(this);
defaultAnim = new GLWidget(ui->centralWidget);
}
void ClaraTeCourseSimulator::setupActions()
{
connect(ui->actionCar_Modelling, SIGNAL(triggered(bool)), ui->centralWidget,
SLOT(addAnimWidget()));
}
void ClaraTeCourseSimulator::addAnimWidget()
{
ui->centralWidget->layout()->addWidget(defaultAnim);
}
ClaraTeCourseSimulator::~ClaraTeCourseSimulator()
{
delete ui;
}
But when I try to run it I get about 24 of these errors: undefined reference to `imp_ZN9QGLFormatD1Ev all pointing to the constructor and destructor in glwidget.cpp.
What am I doing wrong? How can I fix this problem?
Are you trying to change the central widget to the GL one? Because specifying the parent for the GL widget does not change them. If you'd like to change a widget to another (using the Designer), I recommend the "promote to" feature, with which you can change a widget's actual class in the designer. So add a QWidget on the UI, and than promote it to your class (GLWidget).
It seems like the problem is with the GLFormat constructor call in the GLWidget constructor.