ProgressBar with Gtkmm in c++ - c++

Hello I know how to create a progressBar with Gtkmm. I know also with a button how when I click on the button the progressBar increase of 10% for instance. But I don't know how to implement a progressBar which increase automatically I mean like this :
for(int i = 0; i<=10; i++){
double percentage(progressBar.get_fraction() + 0.1);
progressBar.set_fraction(percentage);
getchar();
}
But I don't see when the progressBar increases... I just see when the progressBAr is full...
Thank you for your help !

When you want to use a progress bar (or spinner, etc.) that should actually change its appearance, you need to ensure that the main thread gets some time to update the UI accordingly.
If you have a loop in main thread that sets new values and blocks the thread in getchar(), this thread cannot update the UI to reflect the new state of any widget.
To see your updates you should move the loop calling getchar in some other thread and only do the gtk_* function call in the main thread. This can be achieved by enqueing an update-function via g_idle_add().
Then the UI can be updated while your thread is blocked.
If you replace getchar by some other action that takes some time, this other activity will also prevent the thread from updating the UI unless you move it in some other thread.
You might also think about other mechanisms to return control back to the main thread between updating the widget's state.

Related

SendMessage WM_COPYDATA between two processes [duplicate]

Basically exactly what the title says. I would like to update the text that a button contains every 1 second when the user presses that particular button. I have noted that when the program doesn't have focus it works alright and the text refreshes correctly but when I am hovering over the program or when I am trying to click on it's menu Windows inform me that the program is unresponsive and asks me if I want it terminated. When the loop finishes the program returns to its normal state. Also any action I might have done (like moving it around or closing it) while it was Sleep()-ing is executed after the loop. Here is a bit of code:
case ID_BUTTON_START:
// Code executed when pressing Start Button.
char startButtonText[30]; // Storing next loop text
for (int i=5; i>0; i--)
{
sprintf(startButtonText, "Starting in ... %d", i);
SendMessage(hwndButtonStart, WM_SETTEXT, 0, (LPARAM)(startButtonText));
Sleep(1000);
}
Is this normal? If not what's causing this?
The WndProc does not process messages asynchronously within an application which means all messages are expected to be handled quickly and a return value delivered immediately. You must not Sleep in the UI thread since it will block other UI events from being processed. Any heavy work or synchronous requests/jobs which are likely to take a long time should be performed in worker threads. There are at least three viable options:
Create a new (worker thread) for the task.
If the task is likely to be done often, use a thread pool instead.
Set and subscribe to timer events.
I think the call to Sleep() might be keeping you from returning from the WndProc, so your application is not processing the incomming events for 5 secs. I suggest you try to subscribe to 5 timer events in 1s, 2s,..., 5s. Like when the timer message is recieved the button text must change. I don't know a way how to do that off the top of my head.

How to make a thread in MFC for moving slider control with respect to audio file that is being played?

I was able to move SliderControl according to the position using CSliderCtrl::GetPos , being played by the program. (This is a part of my Music Player MFC project).
But I need to do this automatically without any notification/events ....
I thought of creating a thread that will move slider after clicking on play button.
You generally want to have exactly one thread updating the UI (and doing as little else as possible).
It would almost certainly work better to have a secondary thread playing the music. It can send a message to the UI thread, and the UI thread updates the slider control position when it receives that message.
It is always good to update the UI from the main thread instead of adding a new thread for updating UI. Better you can perform your background tasks by using a worker thread and update the UI by sending a message to the main thread when ever required.
In your case, you can have a worker thread to play the music and send a message to the main thread to update the slider position.
::SendMessage( AfxGetMainWnd()->m_hWnd, Message_Id, ( WPARAM )&String, 0 );
You can use the APIs CSliderCtrl::SetPos() to update the position.

How can I stop a long for loop when the widget (QDialog) running it is closed without multithreading?

I have a quite lengthy foreach loop in a QDialog. It basically looks like this:
foreach (xxx, xxx) {
... doSomeStuff ...
QApplication::processEvents();
if (m_cancelMapLoading) {
break;
}
}
m_cancelMapLoading is set to true by clicking a "Cancel" button. The QApplication::processEvents(); makes this possible.
This works quite fine, but if the dialog is closed as long as that foreach loop still runs, it continues running. I tried to set m_cancelMapLoading to true in each function closing the dialog, but this does not help.
I also tried to test not only for m_cancelMapLoading being true, but also for isVisible(). This actually stops the dialog, but it re-opens it at once without the GUI elements in it.
Unfortunately, QtConcurrent::run etc. can't be used for the function, because the data structures that are manipulated by the foreach loop are not thread safe.
Is there a convenient way to solve this?
You can use a QTimer and Qt's parent-child structure to your advantage here. QTimer with a timeout value of zero has a special meaning in Qt
As a special case, a QTimer with a timeout of 0 will time out as soon
as all the events in the window system's event queue have been
processed. This can be used to do heavy work while providing a snappy
user interface:
So you could do something like
void Dialog::beginDoingStuff()
{
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(processData());
m_timer->start(0);
}
void Dialog::processData()
{
// Perform one cycle of your process here
}
This will perform the processData() function in the same thread as the rest of the dialog, and when the dialog is destroyed by being closed, the timer will be deleted (because it's parent is the dialog), meaning the processing will stop.
A good and quite easy way to unload your GUI from heavy processing is assigning it to another thread or QtConcurrent.
You could then either poll a "should-I-terminate-yet?" variable or terminate the thread manually when it is no longer needed.
I highly recommend a parallel processing since offers better control rather than doing a "DoEvents"-like queue emptying.
We actually managed to solve the problem by connecting the dialog's finished signal to the click slot of the cancel button. This actually stops the loop in all circumstances.
We also introduced starting the function by a QTimer (for a nicer implementation not blocking the function where it's started), but this does not stop the loop (perhaps because we don't destroy the dialog when it's closed).
Thanks for all help :-)

Sleep() in Win32 makes program unresponsive

Basically exactly what the title says. I would like to update the text that a button contains every 1 second when the user presses that particular button. I have noted that when the program doesn't have focus it works alright and the text refreshes correctly but when I am hovering over the program or when I am trying to click on it's menu Windows inform me that the program is unresponsive and asks me if I want it terminated. When the loop finishes the program returns to its normal state. Also any action I might have done (like moving it around or closing it) while it was Sleep()-ing is executed after the loop. Here is a bit of code:
case ID_BUTTON_START:
// Code executed when pressing Start Button.
char startButtonText[30]; // Storing next loop text
for (int i=5; i>0; i--)
{
sprintf(startButtonText, "Starting in ... %d", i);
SendMessage(hwndButtonStart, WM_SETTEXT, 0, (LPARAM)(startButtonText));
Sleep(1000);
}
Is this normal? If not what's causing this?
The WndProc does not process messages asynchronously within an application which means all messages are expected to be handled quickly and a return value delivered immediately. You must not Sleep in the UI thread since it will block other UI events from being processed. Any heavy work or synchronous requests/jobs which are likely to take a long time should be performed in worker threads. There are at least three viable options:
Create a new (worker thread) for the task.
If the task is likely to be done often, use a thread pool instead.
Set and subscribe to timer events.
I think the call to Sleep() might be keeping you from returning from the WndProc, so your application is not processing the incomming events for 5 secs. I suggest you try to subscribe to 5 timer events in 1s, 2s,..., 5s. Like when the timer message is recieved the button text must change. I don't know a way how to do that off the top of my head.

Problem in displaying the message and the progress at the same time,threading in MFC?

I am working on threading in MFC..I am not sure how to use threading.. I cant attain what i excepted!What I actually tried, is to read the directory and display the file names and at the same time,the progress control should show the progress..I created a dynamic static to display the file names and progress bar control to show the progress...What happens here is,its first displaying all the file names one by one and then after that its showing the progress...so,am bit confused..can anybody explain me how to do that or refer me some articles...if u want i can post the code
This appears to be creating 10 threads for each file
for(int i =0;i<10;i++)
{
THREADINFOSTRUCT *_param = new THREADINFOSTRUCT;
_param->_this = this;
AfxBeginThread(MyThread,_param,THREAD_PRIORITY_ABOVE_NORMAL);
....
}
All 10 threads are simultaneously trying to set a single progress bar. (that's bad)
ts->_this->m_ProgressCtrl.SetRange (0, 500);
while (ts->_this->m_ProgressCtrl.GetPos () < 500)
{
Sleep(250);
ts->_this->m_ProgressCtrl.StepIt ();
}
We don't see the code for creation of the progress bar. But it presumably belongs the the main thread. So when these 10 threads try and SetRange or GetPos or StepIt, they are actually sending messages to the main thread to tell it to do those things.
Meanwhile the main thread is in the do {} }while(FindNextFileW(handle,&findData)); loop, and isn't pumping messages. So those threads all wait until the loop is finished and the main thread goes back to its message pump.
Then each of your threads wakes up and returns from calling SetRange, etc. But one at a time, since only message at a time can be processed by the main thread.
For this to work, you need to move the FindNextFile loop into a thread, and you need to let the main thread go back to the pump so that the UI can be updated while things progress.
You also need to stop trying to set the progress bar directly from any of your non-main threads. Instead use PostMessage to post messages back to the main thread and let it set the progress bar. That way your threads don't end up blocking and waiting for the main thread to talk to the progress bar on their behalf.