Levi
Levi

Reputation: 151

Wt C++ make window unclickable after button click

Edit: solution below

Using Wt (version 3) C++ framework: When clicking on a WPushButton which calls a function:

button->clicked(boost::bind(&Service::burn, this));

How can one freeze the screen(or all the buttons) in such a way, that nothing can be clicked while the function runs (runs quite a long time). Currently, when the function Service::burn() runs, I can click other buttons which get queued up and executed after the function Service::burn() has finished.

Note that all buttons/screen needs to be restored after freeze. Also there's a function:

Solution:

Wt::WPushButton* spec_button;

void testclass::test_only()
{
    spec_button = new Wt::WPushButton("slow func");

    auto some_long_func = [&](){
        cout << "#######start \n";
        std::this_thread::sleep_for(std::chrono::seconds(1));
        cout << "#######end \n";
        spec_button->setDisabled(false);
    };
    content()->addWidget(spec_button);
    spec_button->clicked().connect(spec_button, &WPushButton::disable);
    spec_button->clicked().connect(boost::bind<void>(some_long_func));
}

Upvotes: 1

Views: 485

Answers (3)

jbrouwer
jbrouwer

Reputation: 69

The Wt application have a main container with my own class like :

WtMain::WtMain               ( void )
       :Wt::WContainerWidget (      ) {
        setId ( "wkmain-apps"       ) ;
       }

this class is create on a pointer C_Main. When i will freeze the all application run this :

C_Main->doJavaScript ( "$('#wkmain-apps').css({'opacity': 0.5,'z-index': 5,'pointer-events': 'none' });" ) ;

and when your function finish is work do :

C_Main->doJavaScript ( "$('#wkmain-apps').css({'opacity': 1,'z-index': 'auto','pointer-events': 'all' });" ) ;

to un-freeze the screen.

Upvotes: 0

user52875
user52875

Reputation: 3058

Wt doesn't send widget tree modifications to the browser until the event handling is completed, which means that the effect pf button disable will not become visible until after some_long_func completes.

One way around this is to call wApp->processEvents() after disabling the button and before calling some_long_func. This will cause an intermediate update of the widget tree to be sent to the browser immediately. The button clicked() handler can thus look like this (as one function to ensure the order of execution of the signal handers):

{
  spec_button->disable();
  wApp->processEvents();
  some_long_func();
}

Upvotes: 0

hank
hank

Reputation: 9853

This should work:

button->clicked(button, &WPushButton::disable);
button->clicked(boost::bind(&Service::burn, this));

So, you disable the UI using the first handler and then launch your heavy long process using the second one.

If you put those two handlers into a single call, it won't work, because the UI changes won't be propagated to a browser until that call is finished.

Upvotes: 1

Related Questions