PDA

View Full Version : How to threading data in app?



tanthinh1510
26th March 2015, 02:48
Hi all!
I created simple app as picture below
11032
code in file main.qml

import QtQuick 2.3
import QtQuick.Controls 1.2

ApplicationWindow {
visible: true
width: 640
height: 480
Rectangle{
color: "red"
width: 100
height: 100
anchors.centerIn: parent
Timer{
interval: 30
running: true
repeat: true
onTriggered: {
_processdata.calculator()
}
}
}
}

I have one component is a rectangle. In rectangle have timer and 30ms it Triggered to call function _processdata.calculator() from class C++
It's works fine if I put less rectangle(1- 100 rectangle). But I put about 500 - 1000 rectangle in my app, It became slow and when I move app, it is shaking shock
Cause is all rectangle call function _processdata.calculator() time.
How to it works fine when I put 500 - 1000 rectangle in my app? Please help me!

anda_skoa
26th March 2015, 07:26
Why do you need to call the same function on the same object with multiple timers?
If you want to update whatever it is that the function is doing, just to it with a single timer.

Cheers,
_

tanthinh1510
26th March 2015, 08:01
Because a rectangle will call the function and send possition of it to get pixel color. The same function but return different results
Every 30ms. I need the return value of each rectangle.

anda_skoa
26th March 2015, 09:22
Because a rectangle will call the function and send possition of it to get pixel color. The same function but return different results

Then this was a very bad choice of example code.



Every 30ms. I need the return value of each rectangle.

And each rectangle needs its own update interval? Or are they updated at the same time?

Cheers,
_

tanthinh1510
26th March 2015, 09:32
And each rectangle needs its own update interval? Or are they updated at the same time?

Cheers,
_
They updated at the same time. But I try both cases and results is the sames. It became slow.

anda_skoa
26th March 2015, 10:15
They updated at the same time
So you only need one timer.

Ok, then lets ignore your now irrelevant example and concentrate on the actual use case:

- you have a number of rectangles.
- they can change position
- their color depends on that position
- you want to update color for all rectangles every 30 seconds, not on every posiiton change

Correct?

Cheers,
_

tanthinh1510
26th March 2015, 11:42
- you have a number of rectangles.
Cheers,
_
Number of rectangles is random. I can enter any number


- they can change position
Cheers,
_
yes, they can change position


- their color depends on that position
Cheers,
_
Yes, their color depends on that position


- you want to update color for all rectangles every 30 seconds, not on every posiiton change
Cheers,
_
Yes. because color screen always change, so I want to update color for all rectangles every 30 miliseconds(not 30 senconds)
I think cause is all rectangle call function at the same time. But I have not found a way to solve.

anda_skoa
26th March 2015, 12:08
One approach is to register all rectangles with a controller object.
It runs the timer and on timeout gets the positions from the registered objects and updates the color.

Another approach is to have a model that gets the number of rectangles as its input and generates as many reference objects.
Each such object has a read/write for the position and a read property for the color.

The retangles are then generated using a Repeater, bind their position and color to the given reference object.
The model then updates each reference object with a timer.

Cheers,
_

tanthinh1510
26th March 2015, 15:52
One approach is to register all rectangles with a controller object.
It runs the timer and on timeout gets the positions from the registered objects and updates the color.

Another approach is to have a model that gets the number of rectangles as its input and generates as many reference objects.
Each such object has a read/write for the position and a read property for the color.

The retangles are then generated using a Repeater, bind their position and color to the given reference object.
The model then updates each reference object with a timer.

Cheers,
_

Thanks you anda_skoa!
I will try approach of you and update result as soon.
Thanks again.

tanthinh1510
27th March 2015, 03:29
I try created list include information of rectangle (possition) to contain all rectangle.
Every 30 milisecond. I get possition from list to get pixelcolor. Result is it slow the same as the last.
Maybe 30 milisecond not enough to calculate all the rectangles in list.

anda_skoa
27th March 2015, 07:47
Well, you don't have to guess, you can measure the time spent in update function, see QElapsedTimer.

Cheers,
_

tanthinh1510
27th March 2015, 08:51
Well, you don't have to guess, you can measure the time spent in update function, see QElapsedTimer.

Cheers,
_

I follow the above method and use see QElapsedTimer to measure the time spent in update function.
I put 512 rectangle and result QElapsedTimer return is 151 milisecond.
Is there a way for me to shorten the processing time down?

anda_skoa
27th March 2015, 09:13
There is no generic answer to performance, there are way to many reasons for slowness.

The first step is always to do a thorough analysis, profiling the code to see exactly where it spends the time.

Can you post the code of the update function?

Cheers,
_

tanthinh1510
27th March 2015, 09:53
Code I save rectangle infomation to list

void processData::get_light_info_control(int _channel, int _posX, int _posY, int _index)
{
controllercolor *lightcolor = new controllercolor;
lightcolor->channel = _channel;
lightcolor->index = _index;
lightcolor->posX = _posX;
lightcolor->posY = _posY;
listcontroller.append(lightcolor);
}
Here is code update function

void processData::process_channel()
{
foreach (controllercolor *lightcolor, listcontroller) {
getMyPixel(lightcolor->posX, lightcolor->posY, lightcolor->index, lightcolor->channel);
}

}
Here is code function getMyPixel

QColor processData::getMyPixel(int _x, int _y, int _index, int _channel)
{
HWND name = FindWindow(NULL,L"Lighting Player");
HDC dc = GetDC(name);
COLORREF color = GetPixel(dc, _x, _y );

int _red = GetRValue(color);
int _green = GetGValue(color);
int _blue = GetBValue(color);
int _white = qMin(_red,_green);
_white = qMin(_white,_blue);

int _dimmer = _red*0.35 + _green*0.5 + _blue*0.15;
QColor c1;
c1.setRgb(_red, _green, _blue);
ReleaseDC(name, dc);
colorR = c1.name().mid(1,2);
colorG = c1.name().mid(3,2);
colorB = c1.name().mid(5,2);

colorD = QString::number( _dimmer, 16 );
if(colorD.length() == 1) {
colorD.insert(0,"0");
}
colorW = QString::number( _white, 16 );
if(colorW.length() == 1) {
colorW.insert(0,"0");
}


if(_index == 0){
frame.replace(_channel*2 + 20,2,colorD);
}
else if(_index == 1){
frame.replace(_channel*2 + 20,6,colorR+colorG+colorB);
}
else if (_index == 2){
frame.replace(_channel*2 + 20,8,colorR+colorG+colorB+colorW);
}
send_data_channel();
return c1.name();
}


have anything idea?

anda_skoa
27th March 2015, 11:33
Finding the window, getting and releasing a DC and calling send_data_channel for every loop iteration looks really wasteful.

Cheers,
_

wysota
28th March 2015, 07:40
If color of an object depends on this object's position, can't you simply ask the object what color it has instead of using this hacky WinAPI approach?

tanthinh1510
1st April 2015, 07:55
Finding the window, getting and releasing a DC and calling send_data_channel for every loop iteration looks really wasteful.

Cheers,
_

I just do not call these functions, better results but still not solved the problem.
I test and realized that GetPixel(dc, _x, _y ) is time-consuming. So when I put 500 - 1000 rectangle, I had 500 -1000 object in list and take a long time to process.
however I only 30ms to process all.

Added after 4 minutes:


If color of an object depends on this object's position, can't you simply ask the object what color it has instead of using this hacky WinAPI approach?

I get color pixel screen from object's position. I used WinAPI approach to get it. Anything approach?

wysota
1st April 2015, 17:52
The object knows its own color, ask the object for its "color" property instead of asking the screen for a pixel color.

tanthinh1510
2nd April 2015, 02:23
The object knows its own color, ask the object for its "color" property instead of asking the screen for a pixel color.

I only used object get position to get pixel in screen. The object have "color" property is "transparent.
As this video below

https://www.youtube.com/watch?v=eigHPrxketg

wysota
2nd April 2015, 06:28
How is the gradient implemented?

tanthinh1510
2nd April 2015, 07:32
How is the gradient implemented?


gradient: Gradient {
id: id0
GradientStop {
position: 0.0
id: id1
SequentialAnimation on color {
id: update1
loops: Animation.Infinite
ColorAnimation { from: "red"; to: "magenta"; duration: 1000}
ColorAnimation { from: "magenta"; to: "blue"; duration: 1000}
ColorAnimation { from: "blue"; to: "cyan"; duration: 1000}
ColorAnimation { from: "cyan"; to: "lime"; duration: 1000}
ColorAnimation { from: "lime"; to: "yellow"; duration: 1000}
ColorAnimation { from: "yellow"; to: "red"; duration: 1000}
}
}
GradientStop {
position: 1
id: id2
SequentialAnimation on color {
id: update2
loops: Animation.Infinite
ColorAnimation { from: "yellow"; to: "red"; duration: 1000}
ColorAnimation { from: "red"; to: "magenta"; duration: 1000}
ColorAnimation { from: "magenta"; to: "blue"; duration: 1000}
ColorAnimation { from: "blue"; to: "cyan"; duration: 1000}
ColorAnimation { from: "cyan"; to: "lime"; duration: 1000}
ColorAnimation { from: "lime"; to: "yellow"; duration: 1000}
}

}

This is one example. I have get color pixel of screen another effect.

wysota
2nd April 2015, 08:25
It seems quite easy to calculate the color from such definition. You know the starting color, the ending color and the percentage of the gradient you are currently in.

tanthinh1510
2nd April 2015, 09:11
It seems quite easy to calculate the color from such definition. You know the starting color, the ending color and the percentage of the gradient you are currently in.

Yes! I can calculate gradient the color from the starting color and ending color. But random effect, I can't calculate color.
As this video

https://www.youtube.com/watch?v=vL7p-IsObj4
So I want get color of screen

Added after 15 minutes:

My problem is when I put <150 object to get color pixel of screen, it work ok. But when I put 500 - 1000 object, it's shaking shock
I need get color all object in 30 millisecond or less but 30 milisecond not enough to calculate all the object in list.
So I think threading data.

wysota
2nd April 2015, 10:30
Then do as I told you in the beginning -- render the scene to an FBO, convert that to a QImage and use QImage::pixel() to get the color.

tanthinh1510
2nd April 2015, 11:27
Then do as I told you in the beginning -- render the scene to an FBO, convert that to a QImage and use QImage::pixel() to get the color.
it can get a large number of pixels in a small period of time?

I have to get color by function

HWND name = FindWindow(NULL,L"Lighting Player");
HDC dc = GetDC(name);
COLORREF color = GetPixel(dc, _x, _y );
But it but 30 millisecond not enough to calculate large object
I don't know what is "render the scene to an FBO"? Can you explain more?

wysota
2nd April 2015, 13:09
it can get a large number of pixels in a small period of time?

I bet it can.

tanthinh1510
3rd April 2015, 09:55
Then do as I told you in the beginning -- render the scene to an FBO, convert that to a QImage and use QImage::pixel() to get the color.

Can you for me example "render the scene to an FBO"?

wysota
3rd April 2015, 10:01
QQuickWindow::setRenderTarget() (make sure you understand the warning in the docs) and optionally you can see if QQuickWindow::grabWindow() is fast enough for you.

tanthinh1510
3rd April 2015, 16:18
QQuickWindow::setRenderTarget() (make sure you understand the warning in the docs) and optionally you can see if QQuickWindow::grabWindow() is fast enough for you.

I used QQuickWindow::grabWindow() and my code

void getScreen::getpixel(int _x, int _y)
{
QQuickWindow screen;
QImage imageScreen = screen.grabWindow();
COLORREF color = imageScreen.pixel(_x,_y);
int _red = GetRValue(color);
int _green = GetGValue(color);
int _blue = GetBValue(color);
QColor c1;
c1.setRgb(_red, _green, _blue);
qDebug() << c1.name();
}
result is
QQuickWindow::grabWindow: scene graph already in use
QImage::pixel: coordinate (39,72) out of range
I don't know warning
Warning: This function can only be called from the GUI thread

wysota
3rd April 2015, 21:07
Where are you calling this function? What is COLORREF? How in God's name am I supposed to make anything out of the code you post?

tanthinh1510
4th April 2015, 04:07
Where are you calling this function?
I call when I click in rectangle

Rectangle {
width: 360
height: 360
MouseArea {
anchors.fill: parent
onClicked: {
_getScreen.getpixel(mouse.x,mouse.y)
}
}
}

tanthinh1510
4th April 2015, 08:58
Thanks wysota!
I used QQuickWindow::grabWindow() and it work ok. However when I minimize app, it do not work. How to it work when minimize app?

wysota
4th April 2015, 12:21
Render the scene to an FBO :)

tanthinh1510
6th April 2015, 07:45
Render the scene to an FBO :)

I'm trying used it but I can't find document or example about it. Maybe a don't understand about it.

wysota
6th April 2015, 12:35
Did you try using setRenderTarget as advised?