drawing wxBitmap: doesn't refresh before every time it draws

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
greekfellows
Earned a small fee
Earned a small fee
Posts: 20
Joined: Fri May 23, 2014 5:01 pm

drawing wxBitmap: doesn't refresh before every time it draws

Post by greekfellows » Mon Sep 08, 2014 4:29 pm

Code: Select all

void bmImage::paintEvent(wxPaintEvent &event) {
	wxPaintDC dc(this);
	render(dc);
}

void bmImage::paintNow() {
	wxClientDC dc(this);
	render(dc);
}

void bmImage::render(wxDC& dc) {
	bitmap = wxBitmap(aswxImage);
	dc.Clear();
	dc.SetUserScale(((bmImageFrame*)this->GetParent())->scale[0], ((bmImageFrame*)this->GetParent())->scale[1]);
	dc.DrawBitmap(bitmap, wxPoint(0, 0), false);
}
bmImage derives from wxPanel. I want the image to be drawn on a clean, refreshed background every time.
But before I scale the loaded image, it looks like this: (the image is clipped because of resized window)
捕获0.PNG
And after I scale the image then resize the window, it looks like this:
捕获1.PNG
How should I fix this so that it redraws the scaled image over clean background? Obviously there is a problem with drawing and clearing canvas here.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2560
Joined: Sun Jan 03, 2010 5:45 pm

Re: drawing wxBitmap: doesn't refresh before every time it d

Post by PB » Mon Sep 08, 2014 4:34 pm

If there are issues with parts of window not being properly painted after its resize, it can be a good idea to create the window in question with wxFULL_REPAINT_ON_RESIZE flag.

eranif
Moderator
Moderator
Posts: 607
Joined: Tue Nov 29, 2005 7:10 pm
Location: Israel

Re: drawing wxBitmap: doesn't refresh before every time it d

Post by eranif » Tue Sep 09, 2014 4:00 am

Some tips:
1. Make sure you also capture the. Erase background event. Inside it, clear the paint area by drAwing a rectangle with size of the panel
2. Use wxBufferedPaintDC in In OnPaint event handler and use it to draw
3. Capture the ON_SIZE event and simply call refresh

Eran
IDE: CodeLite + wxCrafter
OS: All
https://wxcrafter.codelite.org
https://codelite.org

greekfellows
Earned a small fee
Earned a small fee
Posts: 20
Joined: Fri May 23, 2014 5:01 pm

Re: drawing wxBitmap: doesn't refresh before every time it d

Post by greekfellows » Wed Sep 10, 2014 4:55 pm

Thanks for answers so far @eranif @PB!

I intercepted the wxEVT_SIZE event and called event.Skip() there so it refreshes every time it draws now, that's fine,
but now I have a flickering white screen (I used white to repaint a full-size rectangle)...

Code: Select all

void bmImage::paintEvent(wxPaintEvent &event) {
	wxBufferedPaintDC dc(this);
	render(dc);
}

void bmImage::paintNow() {
	wxClientDC dc(this);
	render(dc);
}

void bmImage::render(wxDC& dc) {
	bitmap = wxBitmap(aswxImage);
	dc.SetBackground(*wxWHITE_BRUSH);
	dc.Clear();
	wxPoint orgp = dc.GetLogicalOrigin();
	dc.SetLogicalOrigin(((bmImageFrame*)this->GetParent())->scroll[0], ((bmImageFrame*)this->GetParent())->scroll[1]);
	dc.SetUserScale(((bmImageFrame*)this->GetParent())->scale[0], ((bmImageFrame*)this->GetParent())->scale[1]);
	dc.DrawBitmap(bitmap, wxPoint(0, 0), false);
	dc.SetLogicalOrigin(orgp.x, orgp.y);
	dc.SetUserScale(1.0f, 1.0f);
	dc.SetPen(*wxWHITE_PEN);
	dc.DrawText(wxString("w: " + std::to_string(GetSize().GetWidth()) + ", h: " + std::to_string(GetSize().GetHeight()) + "\nx: " + std::to_string(((bmImageFrame*)this->GetParent())->scroll[0]) + ", y: " + std::to_string(((bmImageFrame*)this->GetParent())->scroll[1])), 100, 100);
}

User avatar
doublemax
Moderator
Moderator
Posts: 15170
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: drawing wxBitmap: doesn't refresh before every time it d

Post by doublemax » Wed Sep 10, 2014 6:19 pm

Do you have a wxEraseEvent handler? If yes, it should be completely empty. Do not clear the background, do not call event.Skip().

If you're using wx 3.x, you don't need an wxEraseEvent handler at all, just call wxWindow::SetBackgroundStyle(wxBG_STYLE_PAINT) on the window.
Use the source, Luke!

eranif
Moderator
Moderator
Posts: 607
Joined: Tue Nov 29, 2005 7:10 pm
Location: Israel

Re: drawing wxBitmap: doesn't refresh before every time it d

Post by eranif » Wed Sep 10, 2014 7:18 pm

1. Make sure you also capture the. Erase background event. Inside it, clear the paint area by drAwing a rectangle with size of the panel
Hmm, I gave a bad advise here...
You should capture the EVT_ERASE_BACKGROUND event, but do nothing in it - this will remove the flickering
Also, avoid using wxClientDC. If you need to force a paint now, simply call 'Refresh()' this will trigger a call to OnPaint/OnErase

So your function 'paintNow'' should look like this:

Code: Select all

void bmImage::paintNow() {
   Refresh(); // triggers a 'OnPaint' event
}
Eran
IDE: CodeLite + wxCrafter
OS: All
https://wxcrafter.codelite.org
https://codelite.org

greekfellows
Earned a small fee
Earned a small fee
Posts: 20
Joined: Fri May 23, 2014 5:01 pm

Re: drawing wxBitmap: doesn't refresh before every time it d

Post by greekfellows » Thu Sep 11, 2014 10:56 am

Thanks! @eranif @doublemax

Used Refresh() in paintNow() and called SetBackgroundStyle().
Now it doesn't flicker at all.

Post Reply