QML scaling extremely slow - qt

I'm currently working on a project where I need to scale the whole UI based on a global scale factor. I have about 2000 Items (and yes, I need that much). For now, those are just simple Rectangle, but the will get more complex later. I simulated the final behavior by adding5 rectangles inside each of the "main rectangles".
The problem is, if I change the scale factor, it takes about 3 seconds until the change is done. In this 3 seconds, the application freezes.
It tried different ways of using the scale:
Direct for all scalable properties:
Rectangle {
width: 50 * global.scale
height: 50 * global.scale
}
Using the scale property:
Rectangle {
width: 50
height: 50
scale: global.scale
}
However, both of them are equally slow. So, is there a way to zoom the whole ui with having to resize every element? Or anything else, that makes it faster?

The answere was quite simple: Using the debug build can be very slow, but as soon as I started a release build, it worked just fine.

Related

Caching of images/gradients?

I have a TableView with around 40 rows and 4 columns. All of the 160 cells have a Rectangle with a gradient. I use Qt5.13 with enabled Quick compiler. Yet, when I animate all of these 160 cells in relatively large time intervals (100ms), the UI will become unresponsive. This means that rendering the gradients takes too long. In fact, if I only render 40 of such cells, I can update in 100ms intervals with ease.
The rectangles represent progress bars. They have gradients from top to bottom. However, the value (length) of the progress bars changes the gradients, too. This is why for each value (length) point, the gradients have to be recreated and rerendered.
Clearly, this is slow. What I would like to do is have the gradients being cached for each value (length) point. They represent percentages, so I would only need to cache 101. I am quite certain that this improves the performance here.
However, how can I cache gradients (or any objects) myself in QML? The more general (or bonus) question is: how can I have a shared QML resource between multiple QML files?
You can try and load images instead of rendering if you have access to a large memory. Maybe you can also try scaling SVGs.

VNDetectFaceLandmarksRequest 50% slower when using regionOfInterest

I am doing real time face recognition on a video stream.
Right now, it's a bit slow, so I decided to use the regionOfInterest of my VNDetectFaceLandmarksRequest to reduce the size of the image where the algorithm has to do face recognition.
The underlying idea is that the face will be always more or less in the same position within two frame; so I use the previous faceObservation result with a transform.
In this case, drift is 0.05 (meaning that we allow the face to move at most 0.05% of the size of the frame)
My calculation is the following, and the bounding box seems correct:
CGRect(x: faceObservation.boundingBox.origin.x - self.drift, y: faceObservation.boundingBox.origin.y - self.drift, width: faceObservation.boundingBox.width + self.drift, height: faceObservation.boundingBox.height + self.drift * 2)
However, I noticed that the calculation is 50% slower when I set the regionOfInterest
This doesn't make sense to me.
Is there something I do wrong, or is my assumption incorrect ?

qscrollbar (not a qscrollarea) setValue not working

I am working on a qwtPlot and have implemented custom scrollbars to illustrate the position of things on the plot when zooming in (in regards to the whole thing - so basically the percentage).
Now, everything works fine, apart from the moment, when I do any zooming or panning right at the beginning (or simply when I see the whole plot and then I want to zoom in).
This is a slot I am using to refresh the appearance of the scrollbar:
void ScrollHorizontal::refreshAfterChanges() {
setValue(myPlot->getLowerBound(QwtPlot::xBottom));
setPageStep(myPlot->get_X_delta());
setSingleStep(myPlot->get_X_delta()/10);
setMaximum(myPlot->dataFromSources->lastTimeValMicro()-pageStep());
update();
printV("HorizontalScroll::setValue",myPlot->getLowerBound(QwtPlot::xBottom));
printV("value", value());
printV("pageStep", pageStep());
in the constructor I set the maximum to 0 (just in case, but it doesn't change anything)
The last 3 lines print out some values useful for debugging. What I found out thanks to them is that the slot is executed correctly, but the setValue(int) function doesn't work as I would expect it to:
//printed values right after starting the program
HorizontalScroll::setValue=0
value=0
pageStep=7320
//printed values after using the zoomer once
HorizontalScroll::setValue=956.316
value=0
pageStep=2225
Then, when I move the plot a tiny bit, e.g. zoom it 1.1 times, the setValue works properly and value() return the same thing I set. But if I go to the 100% view (the starting point) I get the same problems again.
Just to illustrate it, here are some screenshots:
http://tinypic.com/view.php?pic=2znph7s&s=8#.UvNkDoZhauY
(100% view, right before zooming in)
http://tinypic.com/view.php?pic=ke7nn9&s=8#.UvNkYIZhauY
(badly set qscrollbar)
Ok - problem was caused by the line
setMaximum(myPlot->dataFromSources->lastTimeValMicro()-pageStep());
It was setting the maximum to 0 sometimes. why? I wanted the slider to take up the whole length of the scrollbar so that at the beginning when the plot was shown in 100% view, you couldn't scroll it and I could achieve that by setting the pagestep to my plot's maximum value and the maximum to 0.
But that caused the setValue(int)problem - you can't set a value bigger than the maximum.
So what finally worked for me is:
double valueToSet=myPlot->getLowerBound(QwtPlot::xBottom);
if(valueToSet>maximum())
setMaximum(valueToSet);
setValue(myPlot->getLowerBound(QwtPlot::xBottom));
setPageStep(myPlot->get_X_delta());
setSingleStep(myPlot->get_X_delta()/10);
setMaximum(myPlot->dataFromSources->lastTimeValMicro()-pageStep());
update();

Qt/PyQt - frequently drawing pixmap to widget, partly not drawing correctly

I'm working on a Qt based application (actually in PyQt but I don't think that's relevant here), part of which involves plotting a potentially continuous stream of data onto a graph in real time.
I've implemented this by creating a class derived from QWidget which buffers incoming data, and plots the graph every 30ms (by default). In __init__(), a QPixmap is created, and on every tick of a QTimer, (1) the graph is shifted to the left by the number of pixels that the new data will take up, (2) a rectangle painted in the space, (3) the points plotted, and (4) update() called on the widget, as follows (cut down):
# Amount of pixels to scroll
scroll=penw*len(points)
# The first point is not plotted now, so don't shift the graph for it
if (self.firstPoint()):
scroll-=1
p=QtGui.QPainter(pm)
# Brush setup would be here...
pm.scroll(0-scroll, 0, scroll, 0, pm.width()-scroll, pm.height())
p.drawRect(pm.width()-scroll, 0, scroll, pm.height())
# pen setup etc happens here...
offset=scroll
for point in points:
yValNew = self.graphHeight - (self.scalePoint(point))
# Skip first point
if (not(self.firstPoint())):
p.drawLine(pm.width()-offset-penw, self.yVal, pm.width()-offset, yValNew)
self.yVal = yValNew
offset-=penw
self.update()
Finally, the paintEvent simply draws the pixmap onto the widget:
p = QtGui.QPainter(self)
p.drawPixmap(0, 0, self.graphPixmap)
As far as I can see, this should work correctly, however, when data is received very fast (i.e. the entire graph is being plotted on each tick), and the widget is larger than a certain size (approx 700px), everything to the left of the 700px area lags considerably. This is perhaps best demonstrated in this video: http://dl.dropbox.com/u/1362366/keep/Graph_bug.swf.html (the video is a bit laggy due to the low frame rate, but the effect is visible)
Any ideas what could be causing this or things I could try?
Thanks.
I'm not 100% sure if this is the problem or not, but I thought I might make at least some contribution.
self.update() is an asynchronous call, which will cause a paint event at some point later when the main event loop is reached again. So it makes me wonder if your drawing is having problems because of the sync issue between when you are modifying your pixmap vs when its actually getting used in the paintEvent. Almost seems like what you would need for this exact code to work is a lock in your paintEvent, but thats pretty naughty sounding.
For a quick test, you might try forcing the event loop to flush right after your call to update:
self.update()
QtGui.QApplication.processEvents()
Not sure that will fix it, but its worth a try.
This actually might be a proper situation to be using repaint() and causing a direct paint event, since you are doing an "animation" using a controlled framerate: self.repaint()
I noticed a similar question to yours, by someone trying to graph a heart monitor in real time: http://qt-project.org/forums/viewthread/10677
Maybe you could try restructuring your code similar to that. Instead of splitting the painting into two stages, he is using a QLabel as the display widget, setting the pixmap into the QLabel, and painting the entire graph immediately instead of relying on calls to the widget.update()

CSS background-position: animating and performance

I've seen many examples for animating the background-position of elements to produce nice looking scrolling backgrounds.
These examples tend to also script in reset counters to put the background-position in its original location after a certain amount of pixels.
My question is: Is it feasible to never reset the background-position for a tiled background? This would naturally produce very large background-position values over time, but if there is no significant difference in browser performance, it might be ok. I've tested IE, Firefox, and Chrome over an 8 hour period, and there didn't appear to be any negative impact, although my boxes are relatively fast.
To answer the "why not reset?" question, it just comes down to simplicity. I am animating many background elements, each with different X/Y ratios, so not having to calculate when exactly it would be pixel perfect timing to switch back would make my life easier.
Anyone have thoughts on this?
This would naturally produce very large background-position values over time
Yes, that could eventually become a problem if your code is like
el.style.backgroundPosition= '0 '+n+'px';
When n reaches a high number (typically 1000000000000000000000), its toString will switch to exponential representation, which would end up trying to set:
el.style.backgroundPosition= '0 1e21px';
which is an obvious error. It's possible some layout engines might bail out earlier, perhaps at 1<<31 pixels. But even so, if you were animating something by (say) 32 pixels 60 times a second, it would still take twelve days to reach that stage.
not having to calculate when exactly it would be pixel perfect timing to switch back would make my life easier.
Typically you'd use the modulo operator % separately on each counter rather than resetting the whole thing.
var framen1= 30; // item 1 has 30 frames of animation
var framen2= 50; // item 2 has 50 frames of animation
...
var framei1= (framei1+1)%framen1; // 0 to 29 then reset
var framei2= (framei2+1)%framen2; // 0 to 49 then reset
Or, for time-based animations:
var frametime1= 100; // item 1 updates 10 times a second
var frametime2= 40; // item 2 updates 25 times a second
...
var dt= new Date()-t0; // get time since started animation
var framei1= Math.floor(dt/frametime1) % framen1;
var framei2= Math.floor(dt/framelength2) % numberofframes2;
document.getElementById('div1').style.backgroundPosition= '0 '+(framei1*24)+'px';
document.getElementById('div2').style.backgroundPosition= '0 '+(framei2*24)+'px';
...
I would think you would hit an overflow of some sort, but if you tested it over an 8 hour period, it is unlikely that it is possible to get the browser to overflow. It is just speculation.

Resources