wxProgressDialog refusing to hide and die Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Mzg
Earned a small fee
Earned a small fee
Posts: 15
Joined: Mon Jul 02, 2012 11:31 am

wxProgressDialog refusing to hide and die

Post by Mzg »

In my project I try to use a wxProgressDialog, but it's not going too well. I'm new to wxWidgets, by the way. Platform is 64 bit Arch Linux with GTK.

What I want to achieve is to have a progress dialog that I create when my main window is created, and store in the background, showing it when I need it, then hide again. Obviously it should destroy on application exit.

Here's parts of my code (the whole project is currently several thousand lines of code and copyrighted, so can't post it all, hope this is enough to spot an error):

Code: Select all

class MainWnd : public wxFrame
{
  public:
    wxProgressDialog* progDlg;  
    // Other code
};
In the constructor of MainWnd:

Code: Select all

MainWnd::MainWnd(const wxString& title)
    : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(350, 200))
{    
    // Add this window's user interface
    wxPanel* panel = new wxPanel(this);
    wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
    panel->SetSizer(topSizer);

    wxButton* run_button = new wxButton(panel, wxID_INFO, wxT("Run test"));
    wxButton* quit_button = new wxButton(panel, wxID_EXIT, wxT("Quit"));

    buttonSizer->Add(run_button, 0, wxALIGN_CENTRE | wxALL, 20 );
    buttonSizer->Add(quit_button, 0, wxALIGN_CENTRE | wxALL, 20 );
    topSizer->Add(buttonSizer, 1, wxALIGN_CENTER);
    
    // Add dialogs
    progDlg = new wxProgressDialog("Send data", "Sender...", 100, this, 0);    // !!!!!!NOTE THIS LINE!!!!!
    
    // Connect to event handlers
    Bind(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainWnd::OnBtnPressRun), this, wxID_INFO);
    Bind(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainWnd::OnBtnPressQuit), this, wxID_EXIT);
    Bind(wxEVT_TIMER, wxTimerEventHandler(MainWnd::OnTimer), this);
    Bind(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(MainWnd::OnClose), this);
    
    // Size and place window
    topSizer->SetSizeHints(this);
    Centre();
}
In the main window's close event handler:

Code: Select all

// What to do on close
void MainWnd::OnClose(wxCloseEvent& event)
{    
    m_timer->Stop(); // Timer that runs a function every 50ms. This function might access GUI, 
                       // so I stop the timer before destroying anything. Program is single-threaded.
    // Other stuff here, not GUI related     
    this->Destroy();     
}
I have not overridden wxApp::OnExit.

So, what happens with this code is:
1. My progress dialog is displayed immediately
2. My progress dialog is not destroyed when I close the main window

What I've tried to do to fix the above problems:
1. Call progDlg->Show(false) after constructing it - didn't help
2. Play around with the parent argument as well as the wxPD_APP_MODAL style flag - didn't help
3. Destroy progDlg manually (using progDlg->Destroy() in the MainWnd::OnClose function) - with or without using the main window as parent. This partially worked, in the sense that the progress dialog disappeared, but the application process did not terminate.

Any ideas? :(
Coding on 64 bit Arch Linux with GTK.
Using wxWidgets version 2.9.4
New to the game.
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: wxProgressDialog refusing to hide and die

Post by DavidHart »

Hi,
3. Destroy progDlg manually (using progDlg->Destroy() in the MainWnd::OnClose function)
That should have worked. A wx app exits when the last top-level window is destroyed; 'top-level' being things with 'Frame' or 'Dialog' in their name, plus wxWizard and wxSplashScreen and (I think) wxTaskBarIcon.

If your app fails to exit when you Destroy() both of the top-level windows you've mentioned, check that there aren't any others that you haven't; the common mistake is to Close() a wxDialog but not Destroy() it (when you Close() a frame it self-destructs; a dialog just Hide()s). Other errors are to override one of the wx internals and forget either to call the base-class or Skip() the relevant event; and accidentally creating a frame twice, e.g. by both calling the base-class and also loading from XRC.

Regards,

David
Mzg
Earned a small fee
Earned a small fee
Posts: 15
Joined: Mon Jul 02, 2012 11:31 am

Re: wxProgressDialog refusing to hide and die

Post by Mzg »

Thank you for replying. Bit frustrated.

I can not imagine what kind of other dialog or frame that could stay open, there are none at that stage in the program. Also, when I uncomment the creation of the progress dialog my application exits just fine. I've also checked that the main window constructor is only called once. And I have checked that my Destroy() calls return true.
Coding on 64 bit Arch Linux with GTK.
Using wxWidgets version 2.9.4
New to the game.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxProgressDialog refusing to hide and die

Post by doublemax »

Maybe you should just create the wxProgressDialog on the stack when you need it. I'm pretty sure that's how it's intended to be used.
Use the source, Luke!
Mzg
Earned a small fee
Earned a small fee
Posts: 15
Joined: Mon Jul 02, 2012 11:31 am

Re: wxProgressDialog refusing to hide and die

Post by Mzg »

Would love to, but I have to be able to access it from an event handler that does communications work. So it must be a public member of the MainWnd class and should be available at all times (more or less). I'll try to create in on the stack in the constructor and see if I can make that work. I assume it will then destroy itself when it goes out of scope (so in the MainWnd destructor).
Coding on 64 bit Arch Linux with GTK.
Using wxWidgets version 2.9.4
New to the game.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxProgressDialog refusing to hide and die

Post by doublemax »

I'll try to create in on the stack in the constructor and see if I can make that work. I assume it will then destroy itself when it goes out of scope (so in the MainWnd destructor).
No. It will get out of scope and be destroyed at the end of the ctor.

I don't know the bigger picture of your application, but if you create the wxPD on the stack on demand, you can make its pointer known to whoever needs to know about it.

Code: Select all

wxProgressDialog pd(...);
m_some_frame_pointer->SetPDPointer( &pd );
// do your work
m_some_frame_pointer->SetPDPointer( NULL );
Use the source, Luke!
Mzg
Earned a small fee
Earned a small fee
Posts: 15
Joined: Mon Jul 02, 2012 11:31 am

Re: wxProgressDialog refusing to hide and die

Post by Mzg »

Aaaand it's working! :mrgreen:

Creating the progress dialog on stack in the constructor did not make any difference, or so it seemed from my testing. What did work, however, was creating it on stack when I needed it (as suggested by doublemax) and passing the address of the created dialog for storage in the main window class (in a public pointer), so that I could pick it up from my event handler. I will need to create a small safety net around this to make sure I don't access invalid pointers, but the idea seems to be working fine.

Thank you!

I'm puzzled why the method I tried first did not work, though.

EDIT: Didn't see your post until now, but well, that's exactly what I did, and it worked great ;)

What I did with the creation on stack was create a public variable that I initialized in the ctor's initializer list. Surely the scope of that dialog would be the lifetime of the object? Regardless, it did not work...
Coding on 64 bit Arch Linux with GTK.
Using wxWidgets version 2.9.4
New to the game.
alankdkd
In need of some credit
In need of some credit
Posts: 5
Joined: Mon Feb 04, 2019 6:33 pm

Re: wxProgressDialog refusing to hide and die

Post by alankdkd »

I've got this problem too. I need to make the progress dialog go away and show a message. It should be simple.

Destroy() before my wxMessageBox causes a memory error, but works ok after. So I'm trying to hide the progress dialog until after the message box. I've tried Lower(), Hide(), and Close(), and nothing makes the progress dialog go away.

What finally worked was newing it on the heap, and using delete, not Destroy, to make it go away.

Jeez, it's been SEVEN YEARS and this problem still hasn't been fixed!
Post Reply