#15214 closed defect (fixed)

wxPanel needs Refresh() after calling Layout()

Reported by: elirips Owned by: vadz
Priority: normal Milestone:
Component: wxMSW Version: stable-latest
Keywords: wxPanel Cc:
Blocked By: Blocking:
Patch: no

Description

After calling Layout() on a wxPanel you may need to call Refresh() on the panel too to make its controls be drawn correct:

I have a wxPanel inside a wxBoxSizer inside a wxFrame.
Inside the wxPanel there is a horizontal wxBoxSizer.
Inside the sizer is a wxButton, a wxStaticText and then 5 wxCheckBoxes.
Now I set the Label of the wxStaticText to a text that is longer (takes more horizontal space) than the initial text. Then I call Layout() so that there is enough space for the wxStaticText. The wxButton and the wxCheckBoxes get moved to the right (as the wxStaticText needs more text).
Now the last two wxCheckBoxes are not painted correctly: You still see part of the "old" picture. If you move the mouse over them, or minimize/maximize the frame they get redrawn and appear correct.
They also appear correct if you call Refresh() after calling Layout(). From what I know it should not be necessarily to call Refresh() after calling Layout().

I have attached a minimal example to reproduce the problem and a screenshot of how things look like on my Windows 7 Professional 64 bit. I tested this with wx 2.9.4 in a DLL Debug and Release build and with the 2.9.5 daily snapshot from today in Debug DLL build, builded with Visual Studio 2010.

This also happens if you use wxRadioButtons or wxTextCtrls instead of wxCheckBoxes.

Attachments (4)

LayoutProblem.h download (494 bytes) - added by elirips 14 months ago.
LayoutProblem.cpp download (2.1 KB) - added by elirips 14 months ago.
before_click.png download (36.4 KB) - added by elirips 14 months ago.
after_layout_without_refresh.png download (35.5 KB) - added by elirips 14 months ago.

Download all attachments as: .zip

Change History (9)

Changed 14 months ago by elirips

Changed 14 months ago by elirips

Changed 14 months ago by elirips

Changed 14 months ago by elirips

comment:1 follow-up: Changed 14 months ago by vadz

This is definitely a bug but I have no idea what to do about it. We're just moving the windows around using ::DeferWindowPos() and it's not supposed to result in display corruption...

If this only happens when changing the text of the label, we could add a call to GetParent()->Refresh() in wxStaticText::SetLabel() itself. But I think the same problem should happen when resizing any other control to be of more than its old size, doesn't it?

comment:2 in reply to: ↑ 1 Changed 14 months ago by elirips

Replying to vadz:

This is definitely a bug but I have no idea what to do about it. We're just moving the windows around using ::DeferWindowPos() and it's not supposed to result in display corruption... If this only happens when changing the text of the label, we could add a call to GetParent()->Refresh() in wxStaticText::SetLabel() itself. But I think the same problem should happen when resizing any other control to be of more than its old size, doesn't it?

Yes, it does also happen if you set a longer text onto the wxButton instead of the wxStaticText: In LayoutProblem.cpp:

void LayoutProblem::OnButton1(wxCommandEvent& event)
{
    // m_pLbl1->SetLabel("A very very long text we set here");
    m_pBtn1->SetLabel(L"A very very long text we set here");

    m_pPanel->Layout();
    
    // Here is an extra refresh needed:
    // m_pPanel->Refresh();
}

This results in the same: The wxCheckBoxes on the very right look corrupted. After a Refresh its okay.

comment:3 Changed 14 months ago by vadz

  • Owner set to vadz
  • Status changed from new to accepted

Actually I take my words back: we do not use ::DeferWindowPos() in Layout(), we only use it when redoing layout because of a change in the window size. So we just need to call ::BeginDeferWindowPos() in this case too and everything will work. I'll try to do it soon but if anybody can beat me to it with a patch, it would be helpful.

comment:4 Changed 14 months ago by vadz

Just a note: forget what I wrote above about a patch, I'm going to just fix this myself as it's really simple.

comment:5 Changed 14 months ago by VZ

  • Resolution set to fixed
  • Status changed from accepted to closed

(In [74067]) Use deferred window positioning in wxWindow::Layout() in wxMSW.

Ensure that {Begin,End}RepositioningChildren() are called before/after
changing the positions of multiple children, whether we're using sizers or
constraints.

This fixes display corruption which could happen under Windows 7 and a child
resized first became bigger, pushing off the children resized later.

Closes #15214.

Note: See TracTickets for help on using tickets.