How to clear existing content before redrawing QGraphicsItem? - c++

I have a drawing that is built inside a QGraphicsScene with several layers of QGraphicsItem derived objects.
I am repositioning the QGraphicsItem objects based on some parameters and have noticed that there are some "ghost" trails left unless I call graphicsArea->viewport()->update(). I am repositioning the QGraphicsItem objects quite frequently (i.e. when a slider is moved) and updating the viewport only works if I call it manually some time after drawing is finished (e.g. on a button click).
One possible solution that I found was to fill the background of each QGraphicsItem to be a neutral colour. This doesn't work when I have overlapping items though, as the underlying items can get overwritten.
Does anyone have any suggestions?
Thanks,
Alan

Related

Qt: the proper way to draw a widget over a parent widget efficiently

I have a parent widget P which is a graphic-scene widget that is drawing some picture(QImage) of large size, so its paint function is expensive to be called.
Now I would like to add a small widget C which updating on its own of 10Hz and I would like it to have the graphic-scene widget as its parent.
C does appeared on the left top corner of the P widget as expected.
However I found the 10Hz updating of C also trigger a 10Hz updating of the P and used a lot of CPU.
How could I prevent this? C does not need to be transparent any way.
Unfortunately you cannot prevent the child update of at a frequency of 10Hz to trigger the parent update at a frequency of 10Hz. What you can do is make rendering as efficient as it could be.
Thus you have to use pixmaps for drawing P. Each time you draw the QImage in the paint event you get the penalty from using QImage. Your paintevent should be
void QWidget::paintEvent(QPaintEvent * event)
{
if(somethingHasChanged())
updatePixmap();
drawSavedPixmap();
}
This still holds even if you have a saved QImage.

Disable drawing items on QGraphicsView

I have two QGraphicsView and one QGraphicsScene. One of views don't need to draw qraphicsitems. Is there any way to disable drawing of items on the view?
From the Qt5.2 documentation:
updatesEnabled : bool
This property holds whether updates are enabled.
An updates enabled widget receives paint events and has a system background; a disabled widget does not. This also implies that calling update() and repaint() has no effect if updates are disabled.
You'll probably have to show some code. There are quite a few ways to do this but it's really based on your implementation.
So one of the most simple ways to not draw items - set flag QGraphicsView::IndirectPaint for graphics view and overload drawItems methods in scene and view. Works for me.

Scaling graphics in Qt

I am writing a scheduling-type application using Qt/C++ and want to display weekly schedules in one part of the window, and have this rendering scale as the window size increases. The renders will be composed of rectangles with text in them, and as the display area increases the rectangles should scale nicely while the text should remain the same size.
I have experimented with QGraphicsScene and QGraphicsView and I can make rectangles and text scale; however, the rectangle scaling seems ugly (stretches the outline) and I don't want text to scale at all.
I suspect that I might want to resize the scene to the display area and re-draw the rectangles and text; however, I am not sure how to do this - QGraphicsScene doesn't seem to respond to resizeEvent. Is this even the right approach?
I'm not sure what the ugly rectangle scaling is about (a screenshot might help me understand better what you meant there), but if you don't want the text parts to scale, you can accomplish that by calling setFlag(ItemIgnoresTransformations, true) on your QTextGraphicItem objects.
As far as automatically rescaling the rectangles in response to a window resize, you might take a look at the documentation of the QGraphicsView::fitInView() method:
Scales the view matrix and scrolls the scroll bars to ensure that the
scene rectangle rect fits inside the viewport [...] It's common to
call fitInView() from inside a reimplementation of resizeEvent(), to
ensure that the whole scene, or parts of the scene, scales
automatically to fit the new size of the viewport as the view is
resized. Note though, that calling fitInView() from inside
resizeEvent() can lead to unwanted resize recursion, if the new
transformation toggles the automatic state of the scrollbars. You can
toggle the scrollbar policies to always on or always off to prevent
this (see horizontalScrollBarPolicy() and verticalScrollBarPolicy()).

Stringray Grid transparent background

In Stringray grid, there is the ability to use a transparent background which allows the background of the dialog to be shown through the grid.
In the documentation it states:
But be careful; you should disable scrolling or you have to redraw the grid each time it is scrolled (by overriding DoScroll).
I have a scrollable gird and override the DoScroll and make sure I call Redraw and also tried Invalidate, however the grid is still not completely erasing and redrawing.
I also tried using the old drawing method by setting m_bForceOldDrawing to TRUE.
How can I create a grid that has a transparent background that paint correctly after a scroll without leaving artifacts?
Yes you have to redraw the grid by overriding DoScroll because it is no longer using ScrollWindow to scroll contents because the background is transparent.
However you now have artifacts of the grid over your background.
This is because the background behind the grid is not getting redrawn.
Do you have clipchildren set for the parent?
Another potential problem is that the background is not being drawn because it doesn't realize it has been exposed.
Try calling the parent with the following.
Parent.Invalidate();
Parent.UpdateWindow();
before calling...
Invalidate();

Displaying a popup widget in QT over application border

Let's say that I have an application frame, and I want to show a popup QCalendarWidget over on the right side of the frame. Normally, QT will clip the edges of the QCalendarWidget, cutting it in half and not displaying the rest, as it would be over the right side border.
Is there a way to work around this limitation without resorting to implementing a QDialog?
I want the widget to be visible outside the bounds of it's container.
If you'd show your Calendar, let's say, after a button click, as QDateTimeEditor does, it's contents will not be clipped, cause it do not belong to frame. It will be just a widget, that shows in a dialog manner. And maybe you should even place it in QDialog, that is modal and provides some convenience methods, rather then simple QWidget.
Btw, why don't you want to use QDatetimeEditor?