With signals and slots you don't have to litter your code as well. You can always call the setValue() method (if used from the main thread) or use QMetaObject::invokeMethod with QueuedConnection parameter (from worker threads).
This is just some test code:
Qt Code:
timerThread::timerThread() { connect( timer, SIGNAL(timeout()), this, SLOT(sendValue())); } status=state; theBar=s; } void timerThread::run() { timer->setInterval(1000); timer->start(); } */ } // this will be executed when the timer has finished void timerThread::sendValue() { if (*status <= 100) { timer->start(); } theBar->setValue(*status); }To copy to clipboard, switch view to plain text mode
I can't see how you think this will work without putting the timer in a thread.
As the timer and the filter process have to run simultaneously.
Now i get an error when i run it: it cant seem to find the slot 'sendValue()'
Qt Code:
To copy to clipboard, switch view to plain text mode
Any ideas?
Last edited by aloha; 15th April 2009 at 20:09.
I'm guessing you forgot to add the Q_OBJECT macro to the thread class but the real problem is accessing the widget from within a worker thread which is forbidden. Also remember the thread object lives in the thread that created the object and not in the thread that the object controls. Therefore slots from this object will be executed in context of the main thread which is probably blocked by some heavy calculation or else you wouldn't be spawning the worker thread at all.
I cant seem to find much information about Qevents.
I think i still need signal and slot communication in my timer because I've got to know when the timer time's out. Or can I also do that using slots, maybe?
Imagine that this works, then i still need to send a slot to the mainwindow. Which i had to pass on by pointer to the thread, so then i guess I'm still accessing a widget within a worker thread which is forbidden?
Looking at my previous post, can anybody tell me where just to place those QEvents, cause it seems harder than expected.
Thank you!
Yes, you can. See QObject::startTimer(), QObject::killTimer() and QObject::timerEvent().
Sending a signal doesn't involve accessing the receiver directly. Only making the connection does but it is thread safe.Imagine that this works, then i still need to send a slot to the mainwindow. Which i had to pass on by pointer to the thread, so then i guess I'm still accessing a widget within a worker thread which is forbidden?
See docs for QObject::customEvent() and follow the links.Looking at my previous post, can anybody tell me where just to place those QEvents, cause it seems harder than expected.
In my filter call I know have the following:
Qt Code:
state=new double(0); // initialize the member variable cout << *state << endl; // prints 0 updateProgressBar * me=new updateProgressBar(state, this); // this holds the timer and the events with a pointer to the state ds->Filter(min, max,s, state); // pass the same pointer to state to check on the progressTo copy to clipboard, switch view to plain text mode
the updateProgressBar code:
Qt Code:
{ startTimer(20); // update every 20 miliseconds } // this will be called when the timer times out { std::cout << "Timer ID:" << event->timerId() << std::endl; if (*status==100) { // finished? killTimer(event->timerId()); } std::cout << "sending " << *status << std::endl; // !!! }To copy to clipboard, switch view to plain text mode
And i receive the event in my parent frame:
This code works, but i've got one pointer problem.Qt Code:
cout << "received an event" << endl; int value=(*state); //cast to int m_ui->progressBar->setValue(value); //display on the screen }To copy to clipboard, switch view to plain text mode
After even one timer loop, i display the value of the pointer (see !!!) and then i send an event to the parent window so he knows he has to check on the value of the state/progress and display it. But even when no assignments have been made to value of the pointer is set to a strange value: like for example: 2.1305e-313
The value of that double is allocated on the heap, so i dont immediately see a reason why the value of that pointer isnt just 0 and not 2.1305e-313 or so...
ps: even when i place the timer in my mainwindow and delete the updateProgressBar class, the value gets changed :/
Last edited by aloha; 17th April 2009 at 13:19.
the filtering is done in my library, i'm running this operation through the command
ds->Filter(...);
how else can I know how much computation is already completed without passing a pointer?
The filteroperation is a function, not an object, so i cant have a public member function or so.
During the filter process i can update that status (pointer to double) and in my gui i have a timer who checks the value of that pointer every 0.2 seconds.
I need to have access to the same value from two sections of my application.
1) Write access for the filterfunction, to update the status of the progress
2) read access for the gui to read the value of the current progress
Don't think there is another decent/better way to accomplish this
That's what the setValue() method in the progress bar is for, isn't it?
Let's temporarily forget accessing a shared variable from within multiple threads is WRONG... Updating the variable (why is it created on heap anyway?) won't do you any good because you have to inform the environment that you have actually changed it. You try to get away from it by wasting computer cycles with the timer but it's a bad approach. You should say "hey, my progress value has changed to 3.14!" instead. You can do that either by emitting a signal or by posting an event that carries the value (the latter is probably better in your case as you can do that from an arbitrary point in your code).The filteroperation is a function, not an object, so i cant have a public member function or so.
During the filter process i can update that status (pointer to double) and in my gui i have a timer who checks the value of that pointer every 0.2 seconds.
I hate to be rude but the one you picked is far from being decent. What happens if you read the value from one thread while it is being overwritten by the other thead? You'll get a bogus value. In your case it's not that dangerous, you'll just get a wrong progress value for a while but in a general case this can blow up the world.Don't think there is another decent/better way to accomplish this
Ok , let's start again, i've got no threads. I've got a mainwindow that starts a filterfunction. Now i want to add a progressbar reporting the progress of the filteroperation.
The filterfunction is in another file. how can i have access to the state of the progress of the filterfunction? My suggestion was to pass an integer/double by reference/pointer that I update during the filter progress. For example, i filter 5 different things, so the value of that integer/double will be incremeted every time by 20 (0%, 20%, 40% .... 100%)
Now, to update the progressbar on the screen, i need a timer to check like every 0.2 seconds the value of that passed integer/double. That's why i need the QTimer.
And i use the QTimerEvent to know when the timer has timed out and when to update the value on the screen.
If you can tell me another way how to check on the status/progress of a procedure without passing an integer/double that holds the status, please do...
Bookmarks