Unable to cause horizontalSlider to slide at regular time intervals - qt

I need to make a Music Player using Qt, in which the slider slides as the song progresses.
this->ui->horizontalSlider->setValue(10);
sleep(1);
this->ui->horizontalSlider->setValue(20);
I was trying things like above but could not cause it to display the changing values, as the program pauses for 1 second and only the second value(20) is displayed.
How can i achieve this?

Whatever library you use for audio playback should asynchronously notify you of progress in playing the file. You should react to such progress and update the slider. Using hardcoded delays will quickly desynchronize the slider from real audio playback, even if we forget the fact that you block the event loop.
In any modern application development framework there's generally no need ever to block a thread to sleep. If you write such code, it's the wrong approach in 99.99% of the cases.

Sleeping will block the program for 1 second. Meaning that anything going on (music playback, or any process running inside your app) will basically not work.
What will happen is that the program will set the value to 10, sleep one second (nothing will happen), set 20, and block the program for 1 second again. So basically, your program blocks all the time, and sets the slider's value every second.
The solution is to get the progress value, for example :
int total_time, current_time; //Durations in seconds
int progress; //Will hold the progress percentage
//Somehow you get the total song time and the current song timer
//...
progress = (current_time/total_time)*100
this->ui->horizontalSlider->setValue(progress);
Or :
/*When initializing the slider*/
int total_time; //Duration in seconds
//Somehow you get the the total song time...
//...
this->ui->horizontalSlider->setRange(0,total_time);
And in your routine
/* In the routine where you refresh the slider */
int current_time; //Duration in seconds
//Somehow you get the the current song timer...
//...
this->ui->horizontalSlider->setValue(current_time);

Related

Qt measuring rendering time during which application is frozen

I have a Qt application, where, among other things, there is a function render which goes through a list of objects and creates for each an according (subclassed) QGraphicsPathItem which it then puts as a child in a (subclassed) QGraphicsScene. (It is done in the code below through a visitor GGObjConstructor which gets initialized with the variable scene which is the scene where the items are to be added to).
XTimer timer;
timer.start();
gobjlist gobjlis = ogc._gobjectlis;
GGObjConstructor ggoc(scene, z_value, bkground_color);
for(auto obj: gobjlis) {
obj->exec( &ggoc );
}
timer.stop();
My class XTimer is used in an obvious way to measure the time for this proceeding.
Now the problem is: Only the time spent in the loop where all the items are prepared and inserted into the scene is measured by timer. For a typical example with ~165000 items this gives about 7.5 sec as timer-value at reaching timer.stop(). But the application is after these 7.5 sec still frozen, with the screen-window where the scene is to by displayed yet invisible and only after about 25 sec (hand-stopped) suddenly the display window appears with all the items to be displayed.
Now of course I would like to measure these "freeze time" (or time till the application becomes responsive again, or maybe time till display window appears). But I found no way to do this although I looked some time through stackoverflow or the net in general. The best hint I found was
stackoverflow question
The answer there seemed to imply, that it would be not really simple to achieve (overriding paintEvent method and such things).
Question: Is this true? Or is there a simple way to measure the time till the application becomes responsive again/the image is really displayed?
I had a similar problem with an application once, where I wanted to measure the time the app freezes to figure out with logging what was causing these freezes. What I came up was to measure how long the Eventloop of the mainthread was not responding, because this directly corresponds to a frozen app.
The basic idea is to not run a QApplication but inherit from QApplication and override the notify() function. Some apps do this anyway to catch exceptions which would otherwise break the eventloop. Here is some pseudo-code which should bring the idea across:
bool MyApplication::notify( QObject * receiver, QEvent * event )
{
// something like storing current time like:
// auto start = std::chrono::system_clock::now();
// auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(start - end );
// if( elapsed.count() > 1000 ){
// log something like: Mainthread responds again after <elapsed> seconds
// }
// Note that end must be a member variable
// end = start;
return QApplication::notify(receiver, event);
}
Note 1: If your app does not continuesly run through notify() you can for testing purposes introduce a dummy QTimer which triggers faster than the logging time threshold.
Note 2: if you use multiple threads, esp. QThreads it could be necessary to filter the receiver object and perform that code only if the reciever is in the mainthread.
With this code you can log every freeze of the main-thread (frozen GUI) and determine the length of the freeze. With proper logging you can figure out whats causing the freezes.
Keep in mind that this will only log after the freeze has resolved!
Addition:
It is more complicated and slow, but for debugging/investigation purposes you can store the last event and Object-Tree of the reciever and log that as well. Than you even know which was the last event which triggered the freeze and the recieving Object.

Mysterious EXC_BAD_ACCESS on dispatch_async *serial queue*

I have a location-based app that gets location every 1 second, and saves a batch of the locations at a time to the CoreData DB so as not to make the locations array too large. However, for some reason it crashes with EXC_BAD_ACCESS even though I use dispatch_async on a SERIAL QUEUE:
Created a global serial custom queue like this:
var MyCustomQueue : dispatch_queue_t =
dispatch_queue_create("uniqueID.for.custom.queue", DISPATCH_QUEUE_SERIAL);
in the didUpdateToLocation protocol function, I have this bit of code that saves the latest batch of CLLocation items onto the disk, if the batch size is greater than a preset number:
if(myLocations.count == MAX_LOCATIONS_BUFFER)
{
dispatch_async(MyCustomQueue)
{
for myLocation in self.myLocations
{
// the next line is where it crashes with EXC_BAD_ACCESS
newLocation = NSEntityDescription.insertNewObjectForEntityForName(locationEntityName, inManagedObjectContext: context as NSManagedObjectContext) ;
newLocation.setValue(..)
// all the code to set the attributes
}
appDelegate.saveContext();
dispatch_async(dispatch_get_main_queue()) {
// once the latest batch is saved, empty the in-memory array
self.myLocations = [];
}
}
}
The mystery is, isn't a SERIAL QUEUE supposed to execute all the items on it in order, even though you use dispatch_async (which simply makes the execution concurrent with the MAIN thread, that doesn't touch the SQLite data)?
Notes:
The crash happens at random times...sometimes it'll crash after 0.5 miles, other times after 2 miles, etc.
If I just take out any of the dispatch_async code (just make everything executed in order on the main thread), there is no issue.
You can take a look at this link. Your issue is probably because there is no MOC at the time you are trying to insert item into it.
Core Data : inserting Objects crashed in global queue [ARC - iPhone simulator 6.1]

An empty window pops up and steals focus each time an int is assigned using qrand() in Qt

I'm having a strange problem in a game I'm building in Qt where each time I generate I call qrand() (or rand(), I tried both), a separate tiny window pops up and steals focus from my game. I want to 'roll' a pair of dice every 2 seconds so I'm generating a number between 1 and 12. I'm using a QTimer object in a GameBoard custom widget constructor to call the public slot updateDice() that resets a private variable to a random number.
void GameBord::updateDice(){
dice_int = qrand()%12 +1;
repaint();
QCoreApplication::processEvents();
return;
}
and in my repaint()
...
dice_roll->clear();
dice_roll->setText(QString::number(dice_int));
...
where dice_roll is the label that displays what number the roll was for the player.
With the debugger I found that every time dice_int is assigned the window pops up. The weirdest part to me is that I have other random numbers generated and they don't cause this problem.
I know you can setAttribute so that the window comes up without activating, but I don't know where the window is coming from.
And if there is no solution to this problem, is there a way to set Focus on a widget so that it never changes? I tried Qt::StrongFocus but that doesn't help.
I'd be happy to post more code if you want it, and thanks in advance.

Adobe AIR issue

I have an Adobe AIR application with a chart component displaying some online data.
The chart component has to display a bunch of parameters about 10 of them.
The application has a timer to display current system time.
The chart component is invoked from the timer(using a bindable object) as shown below. A separate bindable object is used to prevent delay in timer.
private function onTimerEvent(event:TimerEvent):void
{
//Update time in screen
oCurrDate = new Date();
curTime = oDateformatter.format(oCurrDate).toString();
oCurrDate = null;
//oUpdate- Bindable object to inform chart about update
//Call chart every 250 ms
oUpdate.bUpdate = !oUpdate.bUpdate;
}
Iam using a calllater function in chart's update event as shown below. updateParameter() will update the dataprovider of each of the parameter and draws it.
public function onUpdateEvent(evt:PropertyChangeEvent):void
{
//aPlotIndex set to 0 for first parameter
aPlotIndex.push(0);
this.callLater(updateParameter, aPlotIndex);
}
The problem is the timer and chart updation stops after running 20 to 21 days. After 20 or 21 days, the update happens only on mouse move. When I moved mouse the time displayed & data in chart are updated.
I profiled the application and found that there is no memory leakage issues. I am logging all the errors but I didn't get any error in the log also. Everything seems weird.
Is it because of using the calllater function.
Is it that the timer is still running but frame update not happening.
I am using Flex SDK3.3 and Flex AIR version 2.0.4.13090.
Please guide me to resolve this issue.
Please read the documentation for Timer.
The total number of times the timer is set to run. If the repeat count is set to 0, the timer continues indefinitely, up to a maximum of 24.86 days, or until the stop() method is invoked or the program stops. If the repeat count is nonzero, the timer runs the specified number of times. If repeatCount is set to a total that is the same or less then currentCount the timer stops and will not fire again.
The maximum is due to the max of an int, which is what the timer uses to store its current count. int has a max value of 2,147,483,647. 2147483647 / 24.86 days / 1440 minutes / 60 seconds /1000 milliseconds is equal to 1 (give or take, differences with the way the docs' number is rounded), which aligns with the fact that the internal clock stores its count per millisecond the Timer has run.
So you cannot set an option to fix this. Instead, you can work around it, assuming nothing actually relies on your timer's value. Each time the timer runs, call
timer.reset();
timer.start();
That will reset the timer to 0 and start it back up again, meaning you will never hit that 24.86 day limit, unless your delay is longer than that (which it cannot possibly be)
Additionally, I'd like to point out that the Flex and AIR versions you are running are severely out of date. Both are nearly 5 years old at this point. AIR may not even run properly on newer versions of Windows and OS X because of it (and won't run on mobile at all). Not a big deal if everything works, but always good to know (many posters on SO do not realize how out of date their Flex and AIR SDKs are)
Timer.repeatCount
int.MAX_VALUE

Forcing Flex to update the screen?

This may be a bit of a beginners question, but I can't for the life of me figure it out.
I'm using flex to develop a GUI for a large project, specifically a status bar along the bottom. Within my StatusBar class is a ProgressBar, which other classes doing work can tell to update(change bar completion and label) as they progress. The problem I'm encountering is that flex won't update whats shown on the screen until it's too late, for example
ProgressBar initialized, 0% done
some class sets the ProgressBar to be 12% done
some class does some work
some class sets the ProgressBar to be 56% done
Whats happening is the 12% done is never displaying, it just hangs at 0% during the work, then skips right to 56% done. I've tried to understand the lifecycle of a flex component (invalidation and validation), and I think I understand it and am applying it correctly, but it's not working at all. I need to tell flex to redraw my StatusBar (or at least the ProgressBar within) after some class sets it to be 12% done, but before some class starts doing its work. How do I do this?
As mentioned in other answers, the flash player is single threaded, if you don't break up your work into discrete chunks that can be executed in separate "frames", you're going to see jumps and stutters in the ui, which is effectively what you're seeing.
If you really must see that 12% message, then it's not enough to invalidate the display list, as the display list isn't getting a chance to update until after the 56% work has completed, you must explicitly interrupt the natural event cycle with a call to validateNow() after your message has been set.
This however is not the best way to do things if performance is of concern. You might get by with judicial usage of callLater() to schedule each chunk of work in turn, as this will allow the player to potentially complete a frame cycle (and update the display list) before attempting the next step in your process.
Glenn,
That is not at all how the threading in Flex works whatsoever. Like many UIs it has a message pump on the main UI thread (they do it in frames). When you call callLater() it places the passed in function pointer at the end of the message pump queue (on the next frame) and returns immediately. The function then gets called when the message pump has finished processing all of the messages prior (like mouse clicks).
The issue is that as the property change causes UI events to be triggered, they then place their own messages on the pump which now comes after your method call that you placed there from callLater().
Flex does have multiple threads but they are there for Adobe's own reasons and therefore are not user accessible. I don't know if there is a way to guarantee that a UI update will occur at a specific point, but an option is to call callLater a number of times until the operation occurs. Start off with a small number and increase until the number of iterations produces the result you want. Example:
// Change this to a number that works... it will probably be over 1, depending on what you're doing.
private const TOTAL_CALL_COUNT:int = 5;
private var _timesCalled:int = 0;
//----------------------------------------------------------------
private function set Progress( progress:int ):void
{
progressBar.value = progress;
DoNextFunction();
}
//----------------------------------------------------------------
private function DoNextFunction():void
{
if( _timesCalled >= TOTAL_CALL_COUNT )
{
_timesCalled = 0;
Function();
}
else
{
_timesCalled++;
callLater( DoNextFunction );
}
}
Try calling invalidateDisplayList() after each changes to your progress bar. Something like :
Class StatusBar
{
public function set progress(value:uint):void
{
progressBar.value = value;
progressBar.invalidateDisplayList();
}
}
Flex has an invalidation cycle that avoid screen redrawing everytime a property changes. As an example, if a property's value changes 3 times in a single frame, it will render only with the last value set. You can force a component to be redrawn by calling invidateDisplayList() which means updateDisplayList will be immediatly executed instead of waiting the next frame.
Actionscript in Flash player, like Javascript in the browser, is pseudo-multithreaded. That is, they're single threaded, but they have multiple execution stacks. This means you can't "sleep" in a particular thread, but you can spawn a new execution stack that gets deferred until a later time. The flex way of doing this is the "callLater" function. You can also use the setTimeout/setInterval functions. Or you can use a timer object built into the flash player. Or even "ENTER_FRAME" event listener. All of these will essentially allow you to do what you need, if I'm correct about the cause of your problems.
It sounds like you have one "thread" doing most of your work, never stopping to allow other execution stacks (threads*) to run.
The problem could be what PeZ is saying, but if that doesn't help, you might want to try some deferred calls for worker classes. So your process might look like this now:
Progress initialized.
Do some work.
Update progress bar to 12. (invalidate display list)
setTimeout(doMoreWork, 100);
Update progress bar to 52.
(if your worker is a UIcomponent, you can use uicomp.callLater(...), otherwise, you need to use setTimeout/timers/enter_frame for pure AS3 classes).
Sometimes its necessary set to zero before assign another value.
progressBar.setProgress(0, progressBar.maximum);
progressBar.setProgress(newValue, progressBar.maximum);
I'm using Flash Builder 4.6 and I also have a problem for the display of my progress bar. I open a new window where I start a new multiloader class (39 Mo of content). The new window is opened in background and the main window display a progress bar until the multiloader class has finished his work. However the opening window is blocking the animation of my main window. I know it's not the multiloader class cause I saw it running correctly.
But I will try to find some new ways of doing it.
The main purpose of my post is the complexity adobe has build around flash.
When you seek ressources for your own application or answers for your questions, it's a real pain to find the good ressource. There is a total mix up (at adobe side and at user side) between AS3, Flex, Flash CS, Flash Builder, AiR, ... If you try to develop in AS3, you will find that some examples won't work for you because it is not implemented in your SDK. You have more and more forums giving you the "best practice" or ironic answers based on experiences on different developping platform.
By example, just here above, I see progressBar.value = value; With my experience, I can say that in Flash Builder 4.6, this property is read-only. But It might be a custom class made by the user but who can tell.

Resources