default constructors in wxWidgets 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
ebyrob
Knows some wx things
Knows some wx things
Posts: 27
Joined: Wed Sep 28, 2016 8:27 pm

default constructors in wxWidgets

Post by ebyrob »

I'm writing a new application and, to refresh my memory, I started by creating Hello World from scratch again. I spent about an hour trying to figure out why after creating a custom wxFrame and calling ->Show() it just wouldn't appear on the screen.

It turns out this is completely invalid:

Code: Select all

MyFrame::MyFrame()
{
    this->SetParent(NULL);
    this->SetId(wxID_ANY);
    this->SetTitle("no chained constructor");

    this->InitializeUI();
}
And that a chained constructor MUST be used:

Code: Select all

MyFrame::MyFrame() : wxFrame(NULL, wxID_ANY, "")
{
    this->InitializeUI();
}
Now, I've encountered this before where certain wxWidgets functionality just won't work unless it is passed into the constructor.

I'm now just wondering, if it's impossible to use the default constructor at all, why do these default constructors exist?
(Or at least, why aren't they private?)

Sorry if this is too philosophical.

This was tested on 3.0.4, but I'm pretty sure the behavior in 3.1.0 is the same.
Operating System: Windows 1-, 64-bit / macOS 13.4.1, Apple M1
Compiler: Visual Studio 2019 / Xcode 14.3.1
wxWidgets version: 3.1.0 / 3.2.2
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: default constructors in wxWidgets

Post by ONEEYEMAN »

Hi,
Why are you starting with "Hello World" and not the official "minimal" sample?

But this is also more philosophical...

Thank you.
ebyrob
Knows some wx things
Knows some wx things
Posts: 27
Joined: Wed Sep 28, 2016 8:27 pm

Re: default constructors in wxWidgets

Post by ebyrob »

Well, I was re-writing from scratch. Trying to see if I could remember enough to do it on my own.

I'm at 47 lines of code now, with the full GUI structure implemented and ready to put in some features.
(minimal.cpp is 205 lines. Comments I know, but still I wanted to do my own thing etc..)

Normally I just hack to pieces a single wxWidgets project with over 50k lines of code. So I don't play with the basics of a small program much.
Last edited by ebyrob on Wed Nov 07, 2018 7:33 pm, edited 1 time in total.
Operating System: Windows 1-, 64-bit / macOS 13.4.1, Apple M1
Compiler: Visual Studio 2019 / Xcode 14.3.1
wxWidgets version: 3.1.0 / 3.2.2
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: default constructors in wxWidgets

Post by doublemax »

I'm now just wondering, if it's impossible to use the default constructor at all, why do these default constructors exist? (Or at least, why aren't they private?)
There are situations where two-step construction is useful (default ctor + calling wxWindow::Create() at a later time).
Sorry if this is too philosophical.
It's not. I'm sure there are technical reasons for it (although i can't give more than the one above :) )
Use the source, Luke!
ebyrob
Knows some wx things
Knows some wx things
Posts: 27
Joined: Wed Sep 28, 2016 8:27 pm

Re: default constructors in wxWidgets

Post by ebyrob »

There are situations where two-step construction is useful (default ctor + calling wxWindow::Create() at a later time).
It was just in this case (wxFrame) I couldn't find a possible use for something created with the default constructor. (Totally crippled / broken) I guess I better dive the source if I want to know more...

...I just tried commenting out wxFrame default constructor for MSW and re-built. Several sub-classes failed to compile.

One being: wxMDIParentFrameBase

I think there must be a trick I'm missing that may make it possible to actually salvage a default wxFrame. I notice wxFrame's default constructor doesn't call ->Create() for one thing. So, I'll have to investigate more if I get time. I think there are some tricks to doing late-configuration when using default constructors. (Maybe not recommended, but likely possible)
Operating System: Windows 1-, 64-bit / macOS 13.4.1, Apple M1
Compiler: Visual Studio 2019 / Xcode 14.3.1
wxWidgets version: 3.1.0 / 3.2.2
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: default constructors in wxWidgets

Post by doublemax »

I think there must be a trick I'm missing that may make it possible to actually salvage a default wxFrame.
Like i said, just calling Create (with proper parameters) should do the trick.

Please show some code of what you're trying to do.
Use the source, Luke!
xtc
In need of some credit
In need of some credit
Posts: 8
Joined: Sat Oct 20, 2018 5:40 pm

Re: default constructors in wxWidgets

Post by xtc »

I will take a stab at this.

The 2 steps object creation seems to be necessary in the situations where it is not convenient to make all data available via the constructor.
In cases like these, it is possible to partially create the object using the default constructors as these constructor do not initialize the bases.

With the object "partially" constructed, it is then possible to furnish further data via get/set accessors.

The "Create" function can then be invoked to complete the object creation.

May be I am totally wrong about this ... :lol:
catalin
Moderator
Moderator
Posts: 1618
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: default constructors in wxWidgets

Post by catalin »

wxWindow [derived] classes instantiated using the default constructor are just the containers without the native widget. Obviously the default constructor will not call Create() (which for non-top level windows would also be impossible because the parent is required). The default constructor + Create() combination makes "delayed creation" possible.

Example:

Code: Select all

wxStaticText* st = new wxStaticText();
st->SetBackgroundColour(*wxRED);
st->SetFont(MyVerySpecialFont);
st->Hide(); // because I want to show it only when the user makes a mistake
st->Create(this, -1, "Some default message"); // let's have some default status

[...]

if ( errorOccurred )
    st->SetLabel("custom error message");

st->Show();
FWIW, top level windows are not shown on the screen by default, but at least for consistency, the constructors copy the base class and all other windows. There could be cases when you don't want to Create() the actual window until you know it is needed, but you might want to set up some properties in advance.

Now, whether you find that useful or not that's more likely up to you, but a default constructor will definitely not create a "broken" instance. It's exactly as it's supposed to be, as in "it's a feature, not a bug".
ebyrob
Knows some wx things
Knows some wx things
Posts: 27
Joined: Wed Sep 28, 2016 8:27 pm

Re: default constructors in wxWidgets

Post by ebyrob »

Sorry for leaving this topic hanging. I have a note in the project I was working on like this:

Code: Select all

    wxString sTitle = "Some Title";

    this->SetParent(parent);
    this->SetId(wxID);
    this->SetTitle(sTitle);
    this->SetWindowStyle(536877056L | wxRESIZE_BORDER);

    // wxWidgets bug means this->GetTitle() won't work in ->Create()
    this->Create(this->GetParent(), this->GetId(), sTitle, wxDefaultPosition, wxDefaultSize, this->GetWindowStyle());
Note: I had to set title with a setter and also set title in the create method or else it didn't work. I'm not sure why, and I'm not saying this is a bug, but just that's what I wrote in my comment at the time.
Operating System: Windows 1-, 64-bit / macOS 13.4.1, Apple M1
Compiler: Visual Studio 2019 / Xcode 14.3.1
wxWidgets version: 3.1.0 / 3.2.2
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: default constructors in wxWidgets

Post by doublemax »

Code: Select all

this->SetParent(parent);
this->SetId(wxID);
this->SetTitle(sTitle);
this->SetWindowStyle(536877056L | wxRESIZE_BORDER);

// wxWidgets bug means this->GetTitle() won't work in ->Create()
this->Create(this->GetParent(), this->GetId(), sTitle, wxDefaultPosition, wxDefaultSize, this->GetWindowStyle())
That all doesn't make sense. Setting the individual properties before calling Create is unnecessary. You only need the Create call.
Use the source, Luke!
Post Reply