I'm writing simple application for WP 8.1 using C++/cx. My problem starts when I'm trying to do something in some event. For example if I create simple button event "tapped" and I want to do something inside for example change the color of the button background, it doesn't execute in the correct time. I mean that for the code below it will first execute Somefunction() and then change the color of the button.Same happens for example when I try to show message box using message dialog and ShowAsync function.
but->Background = ref new SolidColorBrush(Windows::UI::Colors::Red);
Somefunciton();
You have the background change and the function call in the same function and that function gets executed on one thread blocking it. This thread happens to be the UI thread which gets blocked for the time of your function execution. So you set the button background but the actual change will be applied only when the UI thread could run the render function and it will be able to do it only after your function call ends.
So in terms of program execution the button background gets updated before the call to Somefunciton();. But visual changes are delayed until after the function call is completed so you might think that Somefunciton(); gets called before the background is set which is not the case.
Related
I have a button with function onClicked. There is a C++ class Middle with function search_connection connected via qmlRegisterType.
What I want to do is to change the text of searchButton while the C++ function is calculating the return value and also disable the button for that time.
What happens is nothing. The button is enabled for the whole time with text "Search". I believe that what actually happens is, that search_connection function is executed first and than all the rest happens so fast I can't notice the change from "Search" to "Searching..." and back again.
TextField {
id: startStop
}
TextField {
id: finishStop
}
Button {
id: searchButton
text: qsTr("Search")
onClicked: {
text = qsTr("Searching...")
enabled = false;
searchResult.text = middle.search_connection(startStop.text,finishStop.text)
enabled = true;
text = qsTr("Search")
}
}
Does anyone know how to make the Qt to call the function after it changes the text to "Searching..."?
Your UI will repaint certain areas with the next call of the event loop. This never happen in your case, because the slot (your function) is called directly and blocks the application until it is finished. There are a few ways to avoid that blocking:
Move your task to another thread (QThread) and wait until finish
Start your task with an timer (QML-Timer). You can redraw the button before starting the method, but your GUI will still block until the method has finished (the change of enabled will be useless).
Call processEvents() within your method multiple times (not recommended, can cause problems).
If the method needs some time, I would use a new thread. So your gui isn't blocking and your button wil still receive events (painting, mouse, ...).
Edit 1:
If your C++-Code is simple and can be translated to JavaScript-Code, you can also use WorkerScript. It's the QML-Version of QThread. But it has some limitations. You can only use JavaScript and you can't interact with the Worker while running.
Thanks to folibis for the suggestion.
I have an existing (legacy) SDI app, and I want to call some functions immediately after the UI is shown, i.e. when it would normally sit idle and wait for user input.
Normally I'd put the calls in CView::OnInitialUpdate, e.g.:
CMyView::OnInitialUpdate()
{
CView::OnInitialUpdate();
//...
LoadStartupData(); //<-- this is what I want to call
}
... but this gets executed before the UI is shown. For this I want to show some UI feedback while it runs (it takes a while and should probably be in its own thread, but that's a different problem); the function also shows a dialog at the end of it, so I do need the UI to be visible.
What's the "best practice" on how to do this?
Use PostMessage in your init code with a WM_APP+x message.
When the message pump runs your message is delivered to the window and you can do your lazy init.
Use a ON_MESSAGE(MY_WM_APP_INIT,OnMyInit) entry in the message map.
Other way would be to use CWinApp::OnIdle, but this isn't view specific.
Or use a "one time" Timer... start a timer handle it and kill it.
I've created all my controls through the dlg resource. I've added code to control the spin control and it works perfectly. However, if I want to directly change the value of the edit box by typing a value into it, the program crashes with no error message other than "exited with return value 13."
void CNuanceGuiPart2Dlg::OnEnChangeSignalDb(){
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialogEx::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
If I am to add any code into the above block that contains an UpdateData call or manipulates a CEdit/CSpinControl object, it gives me a debug assert at wincore2.cpp, Line 128.
EDIT:
So I figured out that the function is being called too soon when the code first runs. If I wrap the entire function that is being mapped from ON_EN_CHANGE with a if(gui_start), with gui_Start signaling when CDialog::OnInitDialog() has been executed, any updates to the GUI can run fine - I don't even get a debug runtime error. My question is: anyway I can do this without the gui_Start? Why is the ON_EN_CHANGE for this particular edit box being called so soon? Does it have to do with the spin control? Thanks in advance.
Generally, message boxes work like this:
if(ShowMessageBox("Title","Text",MB_YES_NO) == MB_YES)
{
//the user responded yes
}
However, I'm working on a game where I have made the gui system, and when a messagebox is shown, there is still animation happening in the background so I cannot simply block the thread, the animation would stop.
Right now, the way it works is to show the message box, an IMessageHandler* must be provided and it is called with the dialog result.
I'm wondering if I'm overlooking something. Is there a better way to do this that might resemble more how it is usually done. How might other games approach it?
Thanks
There are multiple options, e.g...
Create a View-Model class that the message box reads from (title, message, button text) and writes to (result prior to closing), pass the VM to your message box before displaying it, then read result from VM after close.
(A better technique would to use a command pattern or place an event on the message box instead of passing VM to message box, then within command/event handler update VM).
Use a command pattern or an event to pass result from message box (prior to close) directly to caller (or to view model).
Use a show dialog style call to message box (blocking), however, do that on a separate thread, then write results to a place where main thread can read from.
If I call SetDlgItemText() to update the value of a dialog text it seems to only be updated when the function returns. I'm using it to update a status message informing the user of the current progress mid function so I would like it to be updated immediately.
If this can not be done, is there something else I can do that would perform the same results?
Any help would be appreciated.
Thanks.
I think Processing function is not allowing to call the OnPaint message of the window to which you are setting the message. You can move the processing function to a thread so that main thread handles the UI messages.