I'm just starting to learn OpenGL in Qt, and I've been following a demo clip from youtube, but my display is not same as the display in clip. It looks very small. Is there any way to make it bigger?
I tried to change to the coordinates of the triangle drawing code like:
glColor3f(1,1,0);
glScalef(1, 1, 0.0);
glBegin(GL_TRIANGLES);
glVertex3f(-10,-10,0);
glVertex3f(10,-10,0);
glVertex3f(0.0,10,0);
glEnd();
But, it didn't draw a triangle. My output became a square. See these screen shots for before and after my changes.
You need to set the viewport appropriately (namely the window client region dimensions). At the start of paintGL call glViewport(0, 0, width(), height());.
Also later on you probably want to set appropriate projection and modelview transformations.
Related
I am working on some software to display semitransparent images in a row.
It worked fine using glut functions for resizing etc. but then i decided to move to Qt for a GUI.
all glut functions are stripped and i use a QGLWidget to render my OpenGL stuff.
When i open the program, everything works as wanted but as soon as i resize the mainwindow (and thus the QGLWidget is being resized) the contents of my openGL widget disappear or appear cluttered.
Strangely though the widget is completely grey (my glclearcolor) when there is no cluttered render of my scene content.
This is how it should look like (after starting the program):
http://abload.de/img/okw0qh0.png
And this is how it looks like after resizing the mainwindow:
http://abload.de/img/errort1peu.png
(sometimes it is just grey)
my resizeGL function looks like this and gets called properly:
void prosta3dwidget::resizeGL(int width, int height)
{
if (height == 0) return; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height; //get aspect ratio
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, aspect, 0.5f, 100.0f);
glViewport(0, 0, width, height);
update(); //redraw content
glMatrixMode(GL_MODELVIEW);
}
Okay, noticing that this must have something to do with the depth buffer (gluPerspective manual notes that depth buffer precision is affected by zNear and zFar values: https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml )
i disabled the GL_DEPTH_TEST (uncommented glEnable(GL_DEPTH_TEST)) and everything seems to work as desired. yet i dont fully understand why.
problem solved, new mistery achieved.
I dont know if I am using the correct term here. However this is what I am trying to achieve and I would like some suggestions on how I could achieve that. I want to have a circle with border visible. Now here is the hard part and something I dont even know how to start with. I want to manipulate the circle in such a way that the borders of the circle are visible and its center is not (i.e Pretty much that it has a hole in it and would show what ever is placed under it)I would then like to have another image placed under the circle such that only the part of the image that is under the transparent part of the circle is shown the parts outside the transparent boundary of the circle become invisible. Any suggestions on how I could achieve this. It seems that googling isnt helping me.
I would suggest the alternative way for unmasking a circular area of an image. You can specify the clip region - the area where you need to perform painting. For example:
[..]
QPainter painter(this);
// Sample circular area.
QRegion r(QRect(100, 100, 200, 200), QRegion::Ellipse);
painter.setClipRegion(r);
[..]
painter.drawImage(0, 0, image);
[..]
This will draw only those parts of your image that are inside of the circle with radius 200. All the rest pixels will be hidden.
You can handle mouse move event to move this "circle" over the image like a loupe.
UPDATE
Below is the sample code that generates an image with circular mask and insert it into the label:
QPixmap target(500, 500); // the size may vary
QPixmap source("image.png");
QPainter painter(&target);
QRegion r(QRect(100, 100, 200, 200), QRegion::Ellipse);
painter.setClipRegion(r);
painter.drawPixmap(0, 0, source);
QLabel l;
l.setPixmap(target);
l.show();
You might want to have a look at the Composition Example.
In short you could draw the first image and then use one of the Composition Modes to draw the second image on top (or the other way around). Make sure to convert the images to ARGB32 before using them.
To make the inner Part of the Circle transparent you can adjust the Alpha Channel accordingly.
Here is a small Example using Composition mode:
QPainter p(&imageCircle);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
p.drawImage(image);
p.end()
Here you can find the Qt Documentation of QPainter.
In my QGraphicsView, I display a map. I need to display a horizontal ruler and a vertical ruler on the top edge and left edge respectfully.
The map needs to scrolled but the above rulers should be displayed at their fixed positions, but change their scale values.
I tried to implement this using drawForeground method. Due to the maps large size I only paint the visible area. So I need to update() every time scrolling is done. But this result sometimes flickers.
I feel it would be best to have separate layer like approach.
What is the best way to approach the problem?
The correct way to implement a ruler on the top and left is to derive from QGraphicsView, and then call in the constructor:
// add two rulers on top and left.
setViewportMargins(20, 20, 0, 0);
// add grid layout
QGridLayout* gridLayout = new QGridLayout();
gridLayout->setSpacing(0);
gridLayout->setMargin(0);
// create rulers
hRuler = new Ruler(Qt::Horizontal);
vRuler = new Ruler(Qt::Vertical);
// add items to grid layout
QWidget* corner = new QWidget();
corner->setBackgroundRole(QPalette::Window);
corner->setFixedSize(20, 20);
gridLayout->addWidget(corner, 0, 0);
gridLayout->addWidget(hRuler, 0, 1);
gridLayout->addWidget(vRuler, 1, 0);
gridLayout->addWidget(viewport(), 1, 1);
// finally set layout
setLayout(gridLayout);
This solution was initially presented here, and it works very well. The result looks like this.
I just changed ViewportUpdateMode of the graphics view to FullViewportUpdate to get away from flicker.
You can use SmartViewportUpdate for somewhat good results also.
The downside is, during animations, this takes more process power.
I am new to QT. i am working on the Graphics.
i am using QWidget for drawing graphics(For drawing graphics in QWidget paint event). i need to draw background and foreground graphics. Background is fixed graphics. foregrounds i am drawing lines.
Each 100 millisecond i need to draw 20points. This drawing time is 8 sec. Total i need to draw 1600 points (total points represents the contentious line).
i am using QTimer to invoke this drawing in each 100ms. first few drawing drawn very fast. in the middle of the drawing it's become slow.
the problem is i need to draw all the foreground and background in each 100ms.
Please help me to fix the problem. if any one have sample code please provide. Thanks in advance.
Is there any way to draw only partial area ie. only particular modified region of the graphics?
QPainter-drawing can be very slow without hardware support. Using QGraphicsView won't help if all lines are visible, since it internally uses QPainter anyway.
If you just have to draw 20 new points (or lines) per update and per update background gets cleared so you have to render everything again, there are few things you could try:
1) Disable background autofill. See: QWidget::autoFillBackground
Add something like this to your widget init:
setAutoFillBackground(false);
setAttribute(Qt::WA_OpaquePaintEvent, true);
setAttribute(Qt::WA_NoSystemBackground, true);
Now on the first update render background and first lines. For next updates just skip rendering background and render only new lines.
2) Use double buffering. For example, create QImage of the size of your widget.
.h
private:
QImage m_targetImage;
.cpp
// constructor
m_targetImage = QImage(width(), height(), QImage::Format_ARGB32);
// paint event
// draw to image
QPainter p;
p.begin(&m_targetImage);
static bool firstUpdate = true;
if (firstUpdate)
{
// draw background)
p.drawImage(...);
firstUpdate = false;
}
// draw latest lines
p.drawLines(....);
p.end();
// draw image in widget paint
QPainter painter;
painter.begin(this);
painter.drawImage(0, 0, m_targetImage);
painter.end();
3) Use QGLWidget if possible. Inherit your widget from QGLWidget instead of QWidget. This method doesn't work on all platforms and speed increase might not be enough. Also using OpenGL brings all kind of new problems.
I was just going through one code used to draw one chart. This code is written in the updateDisplayList function of the ItemRenderer of ColumnChart. I am not good at the graphics part of Flex. Can anybody please explain me what this code is doing? I can see the final output, but am not sure how is this achieved.
var rc:Rectangle = new Rectangle(0, 0, width , height);
var g:Graphics = graphics;
g.clear();
g.moveTo(rc.left,rc.top);
g.beginFill(fill);
g.lineTo(rc.right,rc.top);
g.lineTo(rc.right,rc.bottom);
g.lineTo(rc.left,rc.bottom);
g.lineTo(rc.left,rc.top);
g.endFill();
Regards, PK
That code is drawing a rectangle, albeit in a bit of a roundabout way.
The drawing api in flash uses a "draw head". I can't see any reason for using g instead of graphics other than to save some typing. g.clear() erases anything that has been drawn before.
g.moveTo(rc.left, rc.top) moves that into position, in this case the top left corner of the rectangle (0,0). g.beginFill(fill) starts a fill, nothing surprising there.
The g.lineTo(x, y) calls move the draw head around to the the four corners of the rectangle and finally g.endFill() completes the fill.
You can get the same result doing this:
graphics.clear();
graphics.beginFill(fill);
graphics.drawRect(0, 0, width , height);
// this last call is only needed if you're going to draw even more,
// if not you can omit that too
graphics.endFill();
It basically draws a rectangle.
//clear any existing drawings
g.clear();
Set the current drawing position to the top-left corner of the rectangle, which is 0, 0
g.moveTo(rc.left,rc.top);
//start filling with the color specified by `fill`
g.beginFill(fill);
Draw a line to top-right corner of the rectangle from the current location (which is top-left corner). The lineTo method updates the current location so that subsequent drawings start from the new point.
g.lineTo(rc.right,rc.top);
Draw the remaining sides of the rectangle:
g.lineTo(rc.right,rc.bottom);
g.lineTo(rc.left,rc.bottom);
g.lineTo(rc.left,rc.top);
//end the fill.
g.endFill();
Check out the livedocs page for Graphics class for more info.
All the visual components in Flex inherit directly/indirectly from the UIComponent class. The updateDisplayList method of UIComponent draws the object and/or sizes and positions its children. This is an advanced method that you might override when creating a subclass of UIComponent. When you override it in your child class, you should call super.updateDisplayList with the correct parameters to make sure that the base class components are properly updated.
Degrafa makes this kind of thing much easier.