wxBoxSizer not refreshing

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
vanarieleyen
Knows some wx things
Knows some wx things
Posts: 47
Joined: Thu Aug 29, 2019 3:55 am
Location: China, Shenzhen

wxBoxSizer not refreshing

Post by vanarieleyen »

I am most likely doing something wrong but I can't figure out what :?

I have a wxBoxSizer that I dynamically fill with some buttons.
The buttons are displayed without any problem.

Next I perform some action in the program (fired by a click event) that is supposed to remove these buttons and place different buttons instead.
After this action nothing happens or changes....

However, when I change the size of the main window the new buttons suddenly appear (together with the original buttons).

I searched the docs and found that I need to call the Layout() method of wxBoxSizer to force a refresh. So I added this but again no changes..

The following code is the skeleton with non relevant code removed:

Code: Select all

previewFrame::previewFrame(wxWindow* parent,wxWindowID id) {
	wxBoxSizer *mainSizer = new wxBoxSizer(wxHORIZONTAL);	

	wxBoxSizer *vertSizer = new wxBoxSizer(wxVERTICAL);
	mainSizer->Add(vertSizer, 1,  wxALL | wxEXPAND,  1);

	wxBoxSizer *renderers = new wxBoxSizer(wxHORIZONTAL);
	for (int i = 0; i < 5]; i++) {
		renderers->Add(button[i], 0, wxEXPAND, 1);		// button[] is an array with bitmap-buttons
	}
	
	wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
	sizer->Add(renderers, 0, wxALIGN_LEFT, 0);

	vertsizer->Add(sizer, 0, wxALIGN_BOTTOM, 0);	
	               
	this->SetSizer(mainSizer);
}

// called by another button (code not shown)
void myButton::OnClick(wxCommandEvent& event) {
	boxsizer->Clear();

	for (int i = 5; i < 10;  i++) {
		boxsizer->Add(button[i], 0, wxEXPAND, 0);
	}
	boxsizer->Layout();
}

The buttons are bitmap buttons. When the onclick event replaces the buttons in the renderers sizer the buttons are indeed replaced but the window is not updated. When I shrink the window the new buttons appear on a new row with the old buttons underneath. It looks like the bitmaps are not removed in the sizer and the bitmaps of the new buttons are placed above the row with the old buttons.

What am I doing wrong?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxBoxSizer not refreshing

Post by doublemax »

You need to call boxsizer->Clear(true); if you want the buttons to be deleted. Otherwise they're only removed from the sizer.

Call Layout() on the frame or the sizer highest up in the sizer hierarchy.
Use the source, Luke!
vanarieleyen
Knows some wx things
Knows some wx things
Posts: 47
Joined: Thu Aug 29, 2019 3:55 am
Location: China, Shenzhen

Re: wxBoxSizer not refreshing

Post by vanarieleyen »

Does that mean that the buttons are also deleted and need to be created again?

I thought that clear(false) only removed the appearance of the childs but apparantly not.
vanarieleyen
Knows some wx things
Knows some wx things
Posts: 47
Joined: Thu Aug 29, 2019 3:55 am
Location: China, Shenzhen

Re: wxBoxSizer not refreshing

Post by vanarieleyen »

The docs mention:
Detaches all children from the sizer.

If delete_windows is true then child windows will also be deleted.
Actually I don't want the child windows (the buttons) to be deleted I only want them to be removed from the sizer, so I assumed that 'delete_windows = false) would do that.

The reason that I want to keep the buttons is because there are also events connected. Of course I can re-create the buttons and attach the events again but that would lead to a lot of extra code...
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxBoxSizer not refreshing

Post by doublemax »

Clear just removes them from the sizer. If the buttons are not deleted, they will still be visible "somewhere" on their parent. Of course you could Hide() them, but that seems dirty.
Use the source, Luke!
vanarieleyen
Knows some wx things
Knows some wx things
Posts: 47
Joined: Thu Aug 29, 2019 3:55 am
Location: China, Shenzhen

Re: wxBoxSizer not refreshing

Post by vanarieleyen »

I now hide the buttons as you suggested and that works.

However, I think this is a flaw in the design and should be mentioned in the docs. But Ok, I can live with it, it only needs a little changes to my code.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxBoxSizer not refreshing

Post by doublemax »

vanarieleyen wrote: Tue Oct 29, 2019 9:11 amHowever, I think this is a flaw in the design and should be mentioned in the docs.
Why? A sizer is just a layout element. It can only delete its contents or not. If not, it's someone else's responsibility to layout them. I don't see how you can expect the items to disappear if they're not destroyed.
Use the source, Luke!
vanarieleyen
Knows some wx things
Knows some wx things
Posts: 47
Joined: Thu Aug 29, 2019 3:55 am
Location: China, Shenzhen

Re: wxBoxSizer not refreshing

Post by vanarieleyen »

Yes, you're right - I misunderstood this.

But that leads me to another question.
I have placed the sizers directly on the wxFrame without a panel. The sizer is only responsible for the positioning of the widgets, so the widgets are placed directly on the wxFrame.
How can I clean the contents of the wxFrame? I have tried Refresh(), Update() and cleaning the client space by using a wxClientDC but nothing seems to work.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxBoxSizer not refreshing

Post by doublemax »

vanarieleyen wrote: Wed Oct 30, 2019 3:04 am How can I clean the contents of the wxFrame?
I'm not sure what you mean. Do you have redraw errors? Refresh() should redraw everything. If that's not it, please explain what the problem is.

Using a wxPanel is still preferable, but i don't know if it will fix this particular problem.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7479
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxBoxSizer not refreshing

Post by ONEEYEMAN »

Hi,
wxPanel will give you TAB support for free.
Without it you will have to handle TAB-bing yourself.

Thank you.
vanarieleyen
Knows some wx things
Knows some wx things
Posts: 47
Joined: Thu Aug 29, 2019 3:55 am
Location: China, Shenzhen

Re: wxBoxSizer not refreshing

Post by vanarieleyen »

Excuse me for my late response (I had a computer problem and needed to reinstall my OS)

The wxBoxSizer is used on a wxFrame. There are bitmap-buttons placed using this sizer and these appear correctly in the frame.

On a certain moment these buttons are removed from the sizer using boxsizer->Clear(false) and I place different buttons in the sizer.

However the images of the old buttons stay in the frame and the new buttons are also placed in the frame.

When I force a refresh by manually changing the size of the frame the old images of the buttons are removed and everything is OK.

But when I call Refresh() of the frame nothing happens.
Kvaz1r
Super wx Problem Solver
Super wx Problem Solver
Posts: 357
Joined: Tue Jun 07, 2016 1:07 pm

Re: wxBoxSizer not refreshing

Post by Kvaz1r »

Can you provide minimal reproducible code?
Try to add

Code: Select all

Update();
after

Code: Select all

Refresh(); 
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7479
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxBoxSizer not refreshing

Post by ONEEYEMAN »

Hi,
Also a screenshot would be helpful?

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxBoxSizer not refreshing

Post by doublemax »

When I force a refresh by manually changing the size of the frame the old images of the buttons are removed and everything is OK.
In that case, calling Layout() on the topmost sizer in the hierarchy should fix it. If that doesn't work try calling SendSizeEvent() on the toplevel window.

https://docs.wxwidgets.org/trunk/classw ... 5fa82ba4c2
Use the source, Luke!
Post Reply