resizing QGLWidget to fit with each sprite size I have - c++

I'm creating 2D Map editor using opengl to draw simple 32x32 sprites but it seems that I cannot resize my QGLWidget to a large size (i.e size * sprite size -> 1024 * 32), using 1024 only seems to work fine (using glwidget->setMinimumSize(...)). I've been googling for a while now about this, the only interesting thing I found is subclassing QAbstractScrollArea and setting my QGLWidget as it's viewport (That's what QGraphicsView does), I also seen all Qt opengl examples but i couldn't find anything that could help (except Image Viewer example which is not exactly what I want), I also tried the following:
horizontalScrollBar()->setMaximum(width * 32);
verticalScrollBar()->setMaximum(height * 32);
with the widget resizable set to true/false on the scrollarea but still nothing.
Any ideas how would I do that? I can show more code if you ask me to.
Using Qt v4.7.3.

I have two ideas:
If it's possible, drop the idea of using a QGLWidget and place the sprites directly in a graphics scene (QGraphicsPixmapItem). Possibly not what you want, but the graphics scene is made to handle a lot of items, so most things you need (trigger mouse events on items for example) are already implemented.
Or just place the QGLWidget in a graphics scene using a QGraphicsWidget. This should automatically tell the scene its size, which then tells the view the size of the scene. The scroll bars appear automatically if the scene doesn't fit into the view.
Update:
As described in this link, you can use OpenGL in any graphics view:
view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);

Related

Is it possible to set the QOpenGLWidget internal resolution independently from the widget size?

I'm using QOpenGLWidget widget in a QGraphicsView/Scene, this widget should be able to display images that can be huge, in QOpenGLWidget this slows down the application immensely since the OpenGL window is at the size of the widget which is at the size of the huge image even though the visible displayed window is always small, equal or less than the size of the screen.
In other words, is there a way to make the widget rendering resolution the same size as the "physical" widget size on screen instead of always rendering at the potentially huge image size?
PS: I know I can scale the widget myself, but this will force me to change the size and location of every other widget in the QGraphicsView, I'd like to avoid this if possible. Grabbing the frambuffer to a QImage then scaling that up might be an option, but it is also somewhat slow, I'd like to avoid that too if possible.

QOpenGLWindow z-order issues

I am working on updating an application for a client.
They use Qt and currently use a QGLWidget to display a full-screen view of 1 of 4 possible cameras selected by clicking the appropriate radio button. They then use OpenGL to draw on the image being displayed. This works great, but they want to update the UI to include a quad-split view of all 4 cameras.
My first thought on how to accomplish this was to keep the one QGLWidget for the full-screen display, and have 4 small QGLWidgets for the quad-split. From the documentation I found that you can't overlap QGLWidgets or QOpenGLWidgets because they don't handle z-order appropriately, but that this can be accomplished by using QOpenGLWindows and QWidget::createWindowContainer.
So, I coded up an application that uses a QOpenGLWidget (trying to bring them up to date) for the full-screen view, and 4 smaller QOpenGLWindows using QWidget::createWindowContainer, but this isn't working either.
The widgets built from QOpenGLWindows are always on top even if I use lower() to try to get them behind the full screen QOpenGLWidget. I've also tried using hide() on the widgets built from QOpenGLWindows, however, this has had no effect.
Do this at a lower level. Keep the one QGLWidget -- in fact don't touch your Qt objects. Instead, change the lower-level rendering so that it makes 4 calls to glViewport.
After each call to glViewport, update the modelview and projection and matrices according to the camera of interest, then draw the 3D scene.
This is simple and performant, because the driver only needs to deal with a single OpenGL context. You might have some extra work to adjust mouse input, but I think it'll be worthwhile.

RectangularGlow with Qt 4.7 without QML

I'm working on some Qt GUI application with shiny glossy design.
I have a list view customized with my QItemDeleagte subclass. I draw items in paint virtual method. Selected items need to be drawn with glow effect on the border. Normal items must be without glow effect
That's RectangularGlow QML Type which is exactly what I need my view items border to look like. Unfortunately the app was written in Qt 4.7 and there is no way to port the app and all its dependencies to Qt 5.
QGraphicsDropShadowEffect is not sutable since shadow gradient has one direction and an offset. QLinearGradient doesn't help too or I don't know how to use it.
I consider drawing some kind of border image.
Is there any proper and elegant way to implement this using gradients or graphics effects?
EDIT:
As cmannett85 pointed out QGraphicsDropShadowEffect seems to be ok. However graphics effect may be installed on a whole paintdevice and for view item i cant just draw only selected item border rectangle with glow effect and leave other elements in a normal state. Instead all drawing on a list view affected
EDIT2:
I found a solution in an answer for another question. So I think this question may be closed

Making Qt Widgets Stretch and Scale w/ Main Window

I'm wondering if there is a way to make Qt widgets within a QMainWindow widget stretch and scale as the size of the main window is stretched and shrunk. Basically, I'd like the entire window and it's contents to have the same appearance except for size:
At the only way I can think to accomplish this is to get the size of the main window, do the math for every single widget, and reset their sizes any time the main window size is changed, but I'm thinking there's an easier way.
I like this video tutorial on youtube. I'll help you create a layout using QLayout classes. If you use QtCreator/Designer, you can also take a look at the auto-generated ui_MainWindow.XXX file that will clue you in on how it uses some of the UI classes.
As always, QtCreator/Designer has a bunch of hints and tips so you should be able to dig up from the documentation that's embedded in the application.

Lazy rendering of Qt on OpenGL

i came about this problem and knew it could be done better.
The problem:
When overlaying a QGLWidget (Qt OpenGL contextview) with Qt widgets, Qt redraws those widgets after every Qt frame.
Qt isn’t built to redraw entire windows with >60fps constantly, so that’s enormously slow.
My idea:
Make Qt use something other to draw upon: a transparent texture. Make OpenGL use this texture whenever it redraws and draw it on top of everything else. Make Qt redirect all interaction with the OpenGL context view to the widgets drawn onto the texture.
The advantage would be that Qt only has to redraw whenever it has to (e.g. a widget is hovered or clicked, or the text cursor in a text field blinks), and can do partial redraws which are faster.
My Question:
How to approach this? how can I tell Qt to draw to a texture? how can i redirect interaction with a widget to another one (e.g. if i move the mouse above the region in the context view where a checkbox sits in the drawn-to-texture widget, Qt should register this event to the checkbox and repaint to reflect itshovered state)
I separate my 2D and 3D rendering out for my CAD-like app for the very same reasons you have, although in my case my the 2D stuff are not widgets - but it shouldn't make a difference. This is how would approach the problem:
When your widget changes render it onto a QGLFramebufferObject, do this by using the FBO as the QPaintDevice for a QPainter in your QGLWidget::paintEvent(..) and calling myWidget->render( myQPainter, ...). Repeat this for however many widgets you have, but only onto the same FBO - don't create an FBO for each one... Remember to clear it first, like a 'normal' framebuffer.
When your current OpenGL background changes, render it onto another QGLFramebufferObject using standard OpenGL calls, in the same way.
Create a pass through vertex shader (the 'camera' will just be a unit cube), and a very simple fragment shader that can layer the two textures on top of each other.
At the end of the QGLWidget::paintEvent(..), activate your shader program, bind your framebuffers as textures for it (myFBO->texture() gets the handle), and render a unit quad. Because your camera is a unit square, and the viewport size defined the FBO size, it will fill the viewport pixel perfect.
However, that's the easy part... The hard part is the widget interaction. Because you are essentially rendering a 'proxy', you going to have to relay the interaction between the 'real' and 'proxy' widget, whilst keeping the 'real' widget invisible. Here's how would I start:
Some operating systems are a bit weird about rendering widgets without ever showing them, so you may have to show and then hide the widget after instantiation - because of the clever painting queue in Qt, it's unlikely to actually make it to the screen.
Catch all mouse events in the viewport, work out which 'proxy' widget the cursor is over (if any), and then offset it to get the relative position for the 'real' hidden widget - this value will depend on what parent object the 'real' widget has, if any. Then pass the event onto the 'real' widget before redrawing the widget framebuffer.
I should state that I also had to create a 'flagging' system to handle redraws nicely. You don't want every widget event to trigger a widget FBO redraw, because there could many simultaneous events (don't just think about the mouse) - but you would only want one redraw. So I created a system where if anything in the application could change anything in the viewport visually, then it would flag the viewport as 'dirty'. Then setup a QTimer for however many fps you are aiming for (in my situation the scene could get very heavy, so I also timed how long a frame took and then used that value +10% as the timer delay for the next check, this way the system isn't bombarded when rendering gets laggy). And then check the dirty status: if it's dirty, redraw; otherwise don't. I found life got easier with two dirty flags, one for the 3D stuff and one for the 2D - but if you need to maintain a constant draw rate for the OpenGL drawing there's probably no need for two.
I imagine what I did wasn't the easiest way to do it, but it provides plenty of scope for tuning and profiling - which makes life easier in the long run. All the answers are definitely not in this post, but hopefully it will get you on the way to a strategy.