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 »

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: 4204
Joined: Sun Jan 03, 2010 5:45 pm

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

Post by PB »

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: 610
Joined: Tue Nov 29, 2005 7:10 pm
Location: Israel

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

Post by eranif »

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 »

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: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

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

Post by doublemax »

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: 610
Joined: Tue Nov 29, 2005 7:10 pm
Location: Israel

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

Post by eranif »

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 »

Thanks! @eranif @doublemax

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