void StartGeneration() { // Disable buttons buttonBar.generate.Enable(false); buttonBar.next.Enable(false); buttonBar.previous.Enable(false); // Switch page displayLayouts[buttonBar.pageIndex].Show(false); generationProgress.Show(true); // Setup main progress bar generationProgress.progressMain.Set(0, 3); // Start thread generationThread.Run(THISBACK(Generate)); //Thread::Start(THISBACK(Generate)); return; }
TestLayout::TestLayout() { CtrlLayout(*this); button1 << THISBACK(OnCLickButton); } void TestLayout::OnCLickButton() { WhenThreadStart(); } TestLayout2::TestLayout2() { CtrlLayout(*this); progress.Set(0, 1); } TestWindow::TestWindow() { SetRect(0, 0, Zx(400), Zy(200)); Add(testLayout); Add(testLayout2); testLayout.Show(true); testLayout2.Show(false); testLayout.button1.WhenAction = THISBACK(StartProgress); // button1's WhenAction callback was not defined. } void TestWindow::StartProgress() { testLayout.Show(false); testLayout2.Show(true); testLayout2.progress.Set(0, 10); Thread().Run(THISBACK(Progress)); } void TestWindow::Progress() { // This thread code could be written in a much better way, but I'm simply giving you the idea :). for(int i = 0; i < 10; i++) { if(Thread::IsShutdownThreads()) break; Sleep(1000); PostCallback([=]{ // Never directly call GUI elements. If wou want to do fancy GUI stuff with // threads, use PostCallback. testLayout2.progress++; }); } PostCallback([=]{ // Let us roll-back; testLayout2.Hide(); testLayout.Show(); }); } TestWindow::~TestWindow() { // Make sure that running threads terminate. if(Thread::GetCount()) Thread::ShutdownThreads(); }
As I suspected, you are calling GUI elements/methods from a worker thread directly. You need to use PostCallback, and make sure the thread terminates.
I changed the code to your code but still no layout change. So the main problem persists.
Any idea why?
Can you post a package here?
TestWindow::TestWindow() { SetRect(0, 0, Zx(400), Zy(200)); Add(testLayout); Add(testLayout2); testLayout.Show(true); testLayout2.Show(false); testLayout.button1.WhenAction = THISBACK(StartProgress); }
TestWindow::TestWindow() { SetRect(0, 0, Zx(400), Zy(200)); Add(testLayout); Add(testLayout2); testLayout.Show(true); testLayout2.Show(false); testLayout.button1 << [=] { testLayout.Show(false); testLayout2.Show(true); testLayout2.progress.Set(0, 100); Thread::Start([=] { for(int i = 0; i < 100; i++) { if(Thread::IsShutdownThreads()) break; Sleep(100); GuiLock __; testLayout2.progress++; } GuiLock __; testLayout.Show(true); testLayout2.Show(false); }); }; }
There is only a small typo: You have assigned StartProgress to TestLayout instead of button1:
void MainWindow::Generate() { // Generate GuiLock __; progress.progressMainLabel.SetText(t_("(0/3) Generating first...")); if(!GenerateFirst()) { AbortGeneration(1); return; } progress.progressMain++; progress.progressMainLabel.SetText(t_("(1/3) Generating second...")); if(!Second()) { AbortGeneration(2); return; } progress.progressMain++; progress.progressMainLabel.SetText(t_("(2/3) Generating third...")); if(!GenerateThird()) { AbortGeneration(3); return; } progress.progressMain++; progress.progressMainLabel.SetText(t_("(3/3) Done")); }
How exactly does GuiLock work? Because when I tried to implement it in my application it doesn't work. Is there a documentation?
EDIT:
This is part of the code I use:
void MainWindow::Generate() { // Generate GuiLock __; progress.progressMainLabel.SetText(t_("(0/3) Generating first...")); if(!GenerateFirst()) { AbortGeneration(1); return; } progress.progressMain++; progress.progressMainLabel.SetText(t_("(1/3) Generating second...")); if(!Second()) { AbortGeneration(2); return; } progress.progressMain++; progress.progressMainLabel.SetText(t_("(2/3) Generating third...")); if(!GenerateThird()) { AbortGeneration(3); return; } progress.progressMain++; progress.progressMainLabel.SetText(t_("(3/3) Done")); }
Instead of showinf every step it just generates all three and at the end updates the gui. So what do I have to change that every step it is updated?
And how can I unlock it inside the function?
struct GuiLock { GuiLock() { EnterGuiMutex(); } ~GuiLock() { LeaveGuiMutex(); } };
You can call EnterGuiMutex() / LeaveGuiMutex() directly too...
BTW, note that "__" is my way of saying "name does not matter".