Opened 8 years ago
Closed 2 years ago
#12369 closed defect (fixed)
Display glitch for wxStaticBox in wxNotebook on Windows
Reported by: | joostn | Owned by: | |
---|---|---|---|
Priority: | normal | Milestone: | 3.2.0 |
Component: | wxMSW | Version: | stable-latest |
Keywords: | wxStaticBoxSizer wxNotebook display glitch | Cc: | joost@… |
Blocked By: | Blocking: | ||
Patch: | no |
Description
I have a wxNotebook, containing wxScrolledWindow, containing a wxStaticBox and wxStaticBoxSizer, containing multiple controls.
Since wx2.9 there is a display glitch when resizing the window or when switching to different notebook pages: wxChoice and wxButton controls randomly disappear and wxTextCtrls are shown without border.
This happens on Windows 7 64 bit, I haven't yet tried on other windows versions.
This minimal sample application shows the problem:
#include "wx/wx.h" #include <wx/notebook.h> class MyApp : public wxApp { public: bool OnInit(); }; class MyFrame : public wxFrame { public: MyFrame(); }; DECLARE_APP(MyApp) IMPLEMENT_APP(MyApp) bool MyApp::OnInit() { wxApp::OnInit(); MyFrame *frame = new MyFrame(); SetTopWindow(frame); frame->Show(); return true; } MyFrame::MyFrame() : wxFrame(NULL, wxID_ANY, wxString(wxT("Test")), wxDefaultPosition, wxSize(600,400)) { wxNotebook *notebook= new wxNotebook( this, wxID_ANY); wxScrolledWindow* scrolledWin = new wxScrolledWindow(notebook, wxID_ANY); scrolledWin->SetSizer(new wxBoxSizer(wxVERTICAL)); notebook->AddPage(scrolledWin, _("Page 1")); wxStaticBox* staticBox = new wxStaticBox(scrolledWin, wxID_ANY, _("Static Box")); wxStaticBoxSizer *staticBoxSizer = new wxStaticBoxSizer(staticBox, wxHORIZONTAL); scrolledWin->GetSizer()->Add(staticBoxSizer, 0, wxGROW|wxALL, 5); wxChoice* choice = new wxChoice(scrolledWin, wxID_ANY); staticBoxSizer->Add(choice); wxTextCtrl* textCtrl = new wxTextCtrl(scrolledWin, wxID_ANY); staticBoxSizer->Add(textCtrl); wxChoice* choice2 = new wxChoice(scrolledWin, wxID_ANY); staticBoxSizer->Add(choice2); }
The problem is visible in the attached screenshots:
Attachments (6)
Change History (20)
Changed 8 years ago by joostn
comment:1 Changed 8 years ago by joostn
- Cc joost@… added
comment:2 Changed 8 years ago by joostn
Problem occurs on XP 32bit as well, see screenshot. The themed gradient background of the notebook page is corrupted as well.
comment:3 Changed 8 years ago by joostn
- Version changed from 2.9.1 to 2.9-svn
Problem still exists in trunk (19-08-2010)
comment:4 Changed 8 years ago by joostn
By the way the problem can be worked around by creating the controls as children of the staticbox instead of siblings. This is the recommended way for 2.9 but e.g. DialogBlocks will only create them as siblings. I think the old way should still work.
comment:5 Changed 8 years ago by joostn
Here's a workaround for those migrating from 2.8. Call ReparentAllStaticBoxItemsInWindow for all frames containing wxStaticBoxes. This reparents all controls in the staticbox:
void TnhUtilities::ReparentAllStaticBoxItemsInWindow(wxWindow *window) { std::vector<wxWindow*> staticboxes; GetAllWindowChildrenOfClass(window, CLASSINFO(wxStaticBox), staticboxes); for(size_t i=0; i < staticboxes.size(); i++) { wxStaticBox *staticbox=(wxStaticBox*)staticboxes[i]; ReparentStaticBoxItems(staticbox); } } // private: void TnhUtilities::GetAllWindowChildrenOfClass(wxWindow *window, const wxClassInfo *classinfo, std::vector<wxWindow*> &items) { if(window->IsKindOf(classinfo)) { items.push_back(window); } const wxWindowList& children=window->GetChildren(); size_t numchildren=children.GetCount(); for(size_t i=0; i < numchildren; i++) { wxWindow *child=(wxWindow*)children[i]; if(!child->IsTopLevel()) { GetAllWindowChildrenOfClass(child, classinfo, items); } } } void TnhUtilities::ReparentStaticBoxItems(wxStaticBox *staticbox) { #ifdef __WXMSW__ wxSizer *sizer=staticbox->GetContainingSizer(); ReparentStaticBoxItems2(staticbox, sizer); #endif } void TnhUtilities::ReparentStaticBoxItems2(wxStaticBox *staticbox, wxSizer *sizer) { wxWindow *staticboxparent=staticbox->GetParent(); size_t numitems=sizer->GetItemCount(); for(size_t i=0; i < numitems; i++) { wxSizerItem *item=sizer->GetItem(i); if(item->IsWindow()) { wxWindow *window=item->GetWindow(); if(window->GetParent() == staticboxparent) { window->Reparent(staticbox); } } else if(item->IsSizer()) { wxSizer *childsizer=item->GetSizer(); ReparentStaticBoxItems2(staticbox, childsizer); } } }
comment:6 Changed 8 years ago by vadz
- Milestone set to 2.9.2
- Status changed from new to confirmed
I can indeed see this bug. It looks like we paint the (themed) background over the children...
comment:7 Changed 7 years ago by etxmato
Hello,
The workaround works great for wxStaticBoxSizers in wxNotebooks however I use a structure something like:
wxNotebook
-> wxPanel
-> wxStaticBoxSizer
-> wxPanel
-> wxChoiceBook
-> wxPanel
-> wxStaticBoxSizer
For some reason the workaround doesn't for the second StaticBox (i.e. a StaticBox within a ChoiceBook within a NoteBook), and fine for the first. Actually without the workaround the boxes are drawn 'ok' (some controls disapear in certain cases) and with the workaround the boxes are completely empty.
Any suggestions for adapting the workaround to handle this?
Or maybe fixing the problem manually in the wxWidgets code?
Cheers, Marcel.
comment:8 Changed 7 years ago by joostn
Yes I'm still noticing display glitches too, even when the controls are created as children of the static box (or reparented using the workaround). So the problem is not limited to the case where controls are created as siblings.
I don't have a solution but I'll try to prepare a test app later when I have time.
comment:9 Changed 7 years ago by vadz
- Milestone changed from 2.9.2 to 3.0
I still don't know how to fix this and won't have time for it before 2.9.2 so resetting the milestone. A simple way to reproduce the bug would still be very, very welcome.
comment:10 Changed 5 years ago by staticinline
I've confirmed that the original example posted still exhibits the described behavior on the latest svn73045 (Win7). However, it appears to work fine when making the controls children of the staticbox, as I believe remains the recommended approach.
Note that I too use DialogBlocks to generate XRC, and ticket:14431 now causes XRC to place controls as children of the staticbox, according to recommendations, so I no longer need the workaround with the ReparentAllStaticBoxItemsInWindow given above. For people using DialogBlocks to generate C++ instead, I understand DialogBlocks 4.40 also 'added "Parenting" property to wxStaticBoxSizer, to change code generation between creating box children as siblings, and creating them as true children.'
Moreover, ticket:13151 reporting related behavior appears resolved now.
Should this issue be closed? or is the original example still expected to work unchanged or raise an error?
comment:11 Changed 5 years ago by vadz
- Milestone changed from 3.0 to 3.2
Ideal would be to fix it even when using static box as sibling because there must be a lot of existing code doing this. But as I still have no idea about how to actually do it, it's not a priority for 3.0 any more, now that it works correctly with the recommended approach.
Thanks for testing!
comment:12 Changed 2 years ago by awi
I cannot reproduce this issue neither with 2.8.12 nor 3.0.2 nor 3.1 (see attached screenshots).
-
samples/minimal/minimal.cpp
diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp
a b bool MyApp::OnInit() 140 140 // main frame 141 141 // ---------------------------------------------------------------------------- 142 142 143 #include <wx/notebook.h> 144 143 145 // frame constructor 144 146 MyFrame::MyFrame(const wxString& title) 145 147 : wxFrame(NULL, wxID_ANY, title) … … MyFrame::MyFrame(const wxString& title) 171 173 CreateStatusBar(2); 172 174 SetStatusText("Welcome to wxWidgets!"); 173 175 #endif // wxUSE_STATUSBAR 176 177 wxNotebook *notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP); 178 179 wxScrolledWindow* scrolledWin = new wxScrolledWindow(notebook, wxID_ANY); 180 scrolledWin->SetSizer(new wxBoxSizer(wxVERTICAL)); 181 notebook->AddPage(scrolledWin, "Page 1"); 182 183 wxStaticBox* staticBox = new wxStaticBox(scrolledWin, wxID_ANY, "Static Box"); 184 wxStaticBoxSizer *staticBoxSizer = new wxStaticBoxSizer(staticBox, wxHORIZONTAL); 185 scrolledWin->GetSizer()->Add(staticBoxSizer, 0, wxGROW|wxALL, 5); 186 187 wxChoice* choice = new wxChoice(scrolledWin, wxID_ANY); 188 staticBoxSizer->Add(choice); 189 190 wxTextCtrl* textCtrl = new wxTextCtrl(scrolledWin, wxID_ANY); 191 staticBoxSizer->Add(textCtrl); 192 193 wxChoice* choice2 = new wxChoice(scrolledWin, wxID_ANY); 194 staticBoxSizer->Add(choice2); 174 195 } 175 196 176 197
comment:13 Changed 2 years ago by joostn
I haven't seen this problem occurring recently anymore, maybe it was a bug in Windows which got fixed?
As far as I'm concerned this ticket can be closed.
comment:14 Changed 2 years ago by vadz
- Resolution set to fixed
- Status changed from confirmed to closed
Let's close it then. Thanks as usual to @awi for testing!
Initial screenshot