multiple forms

Apr 19, 2014 at 2:24 PM
Hi Jinhao!
Tell me please if there is a way
to manage multiple forms at the same time.

When I tried I got a problem:
int main()
{
    using namespace nana::gui;
    std::thread t1([]()
    {
        form fm;
        fm.show();
        exec();
    });
    t1.join();
    std::thread t2([]()
    {
        form fm;
        fm.show();
        exec();
    });
    t2.join();
}
In the second thread form construction is locked for some reason.

Thanks.
Coordinator
Apr 19, 2014 at 5:46 PM
The code represents the t2 thread will be created after finish of t1 thread, if you want t1 and t2 to run in the same time, join t1 after create of t2.
int main()
{
    using namespace nana::gui;
    std::thread t1([]()
    {
        form fm;
        fm.show();
        exec();
    });

    std::thread t2([]()
    {
        form fm;
        fm.show();
        exec();
    });

    t1.join();
    t2.join();
}
In the most situations a program creates multiple forms just in one thread. E.g.
int main()
{
    using namespace nana::gui;
    form fm1;
    form fm2;
    fm1.show();
    fm2.show();

    exec(); //The function returns when all windows in current thread are closed.
}
Apr 19, 2014 at 6:08 PM
Thank you for the answer!
In my case program need multiple forms in different threads.
Could you tell me,please more about what nana::gui::exec is,when it returns,
and what are rules/restrictions with using it concurrently?
Coordinator
Apr 19, 2014 at 6:19 PM
    std::thread t1([]()
    {
        form fm;
        fm.show();
        exec();  //This call returns when fm is closed.
    });

    std::thread t2([]()
    {
        form fm1;
        form fm2;
        fm1.show();
        fm2.show();
        exec();   //This call returns when fm1 and fm2 are closed.
    });
If you want to close all form in current thread and let exec() return, you can call API::exit().
    std::thread t2([]()
    {
        form fm1;
        form fm2;
        fm1.show();
        fm2.show();
        fm1.make_event<events::click>(API::exit); //Click fm1 and then exec() returns.
        exec();
    });
Apr 19, 2014 at 6:30 PM
Thank you very much!
Apr 21, 2014 at 9:21 PM
Hi,Jinhao.
Could you tell me,please,is it all right that in following code form will never be created?:

int main()
{
    using namespace nana::gui;
    form parent;
    parent.make_event<events::click>([]()
    {
        std::thread t([]()
        {
            form child;
            child.show();
            exec();
        });
        t.detach();
        while(true)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(5000));
        }
    });
    parent.show();
    exec();
}
If while is commented everything works.

Thanks
Coordinator
Apr 22, 2014 at 3:18 AM
Yes, the while() statement is like blocking the GUI thread(main()), and then the thread t will aslo be blocked(by creating child). The reason is there is an internal lock to make the library thread-safe. the main thread acquires the internal lock before executing the click lambda, but the lambda will never return, so that when creating child, thread t will wait for the internal lock until main thread releases it.

Never suspend a GUI thread. Please try to think about another solution.
Apr 22, 2014 at 7:27 AM
Understand,thank you.
Apr 22, 2014 at 4:37 PM
I have yet one more question.
Tell me please if there is a function like exec(),
but for only one widget?
I mean exec polls events of all widgets in the thread,
but maybe it would be usable in some cases to poll events of only one window.

For example, we have a main window and that window can create a dialog to enter some information.
And we want to have a function that creates the dialog and returns the information.
Since to get information we should use event handler,we are forced to call exec(),
and since there is main window, exec will not return until mainwindow is destroyed
nor the function will.

If my point isn't clear I can write a code snippet to illustrate

P.S. As you can see I am novice and my english is poor,so forgive me please if something I write is wrong.

Thanks
Coordinator
Apr 22, 2014 at 5:26 PM
Yes, you need a modal window. There is an example.
int main()
{
    using namespace nana::gui;

    form fm;

    fm.make_event<events::click>([&fm]()
    {
        class change_form
            : public form
        {
            textbox txtbox_;    //<nana/gui/widgets/textbox.hpp>
            button btn_;        //<nana/gui/widgets/button.hpp>
            place   place_;     //<nana/gui/place.hpp>
        public:
            change_form(window wd)
                : form(wd, API::make_center(wd, 300, 100))
            {
                txtbox_.create(*this);
                btn_.create(*this);
                btn_.caption(L"Change the caption of main form");
                btn_.make_event<events::click>([wd, this]()
                {
                    API::window_caption(wd, txtbox_.caption());
                    close(); //close the change_form.
                });

                place_.bind(*this);
                place_.div("<margin=[10, 20] vertical<text><margin=[10,0,0,20%] button>>");
                place_.field("text") << txtbox_;
                place_.field("button") << btn_;
                place_.collocate();
            }
        };

        change_form cf(fm); //to be a modal window, the owner for the modal window(cf) should be specified.
        API::modal_window(cf); //displays cf as a modal window. modal_window() returns when change_form is closed.
    });
    fm.show();
    exec();
}
A change_form is created when fm is clicked, and it acquires a user input for changing the caption of fm.
Apr 22, 2014 at 5:33 PM
Yes that's a solution.Thank you!