failed in wxPaintDCImpl() in a Paint Event

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
NoeMurr
Knows some wx things
Knows some wx things
Posts: 32
Joined: Sat Mar 31, 2018 2:26 pm

failed in wxPaintDCImpl() in a Paint Event

Post by NoeMurr » Tue Mar 05, 2019 8:44 am

Hi all,

I'm creating a wxSplitterWindow that contains 2 custom widgets: the first is derived from wxPanel and the second is derived from wxGLCanvas...

If I add both the widgets at the splitter I obtain an error:

Code: Select all

assert "window->MacGetCGContextRef() != __null" failed in wxPaintDCImpl(): using wxPaintDC without being in a native paint event
But if I add only one of them and and split the splitter window with an empty wxPanel all works fine...

exaple, this does cause the error:

Code: Select all

[...]
auto *splitView = new wxSplitterWindow(
        splitView,
        wxID_ANY,
        wxDefaultPosition,
        wxDefaultSize,
        wxSP_LIVE_UPDATE | wxSP_3D
);
auto *viewer2D = new Viewer2D(splitView, wxID_ANY );
auto *viewer3D = new Viewer3D(splitView, wxID_ANY);

splitView->SplitHorizontally(viewer, scheme);

[...]
this examples works:

Code: Select all

[...]
auto *splitView = new wxSplitterWindow(
        splitView,
        wxID_ANY,
        wxDefaultPosition,
        wxDefaultSize,
        wxSP_LIVE_UPDATE | wxSP_3D
);
auto *viewer2D = new Viewer2D(splitView, wxID_ANY );
auto *viewer3D = new wxPanel(splitView, wxID_ANY);

splitView->SplitHorizontally(viewer, scheme);

[...]

Code: Select all

[...]
auto *splitView = new wxSplitterWindow(
        splitView,
        wxID_ANY,
        wxDefaultPosition,
        wxDefaultSize,
        wxSP_LIVE_UPDATE | wxSP_3D
);
auto *viewer2D = new wxPanel(splitView, wxID_ANY );
auto *viewer3D = new Viewer3D(splitView, wxID_ANY);

splitView->SplitHorizontally(viewer, scheme);

[...]
The wxPaintDC object is created only in methods Viewer2D::onPaintEvent and in Viewer3D::onPaintEvent that are bind to the wxPAINT_EVT of the their own class.

EDIT: If I use wxCliendDC in the paint event handlers all works fine, but I can't understand why

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

Re: failed in wxPaintDCImpl() in a Paint Event

Post by doublemax » Tue Mar 05, 2019 9:06 am

The wxPaintDC object is created only in methods Viewer2D::onPaintEvent and in Viewer3D::onPaintEvent that are bind to the wxPAINT_EVT of the their own class.
This is most likely not true. Please show the event handlers and how you bind/connect them.
Use the source, Luke!

NoeMurr
Knows some wx things
Knows some wx things
Posts: 32
Joined: Sat Mar 31, 2018 2:26 pm

Re: failed in wxPaintDCImpl() in a Paint Event

Post by NoeMurr » Tue Mar 05, 2019 9:16 am

This is the event handler for the viewer 3D.

Code: Select all

void Viewer3D::onPaint(wxPaintEvent &e) {
    wxPaintDC dc(this);
    renderNow(dc);
    Start(10);
}
this is the bind code in the constructor:

Code: Select all

wxGLCanvas::Bind(wxEVT_PAINT, &Viewer3D::onPaint, this);
wxGLCanvas::Bind(wxEVT_SIZE, &Viewer3D::onSize, this);
wxGLCanvas::Bind(wxEVT_MOTION, &Viewer3D::onMouseEvent, this);
wxGLCanvas::Bind(wxEVT_MOUSEWHEEL, &Viewer3D::onWheel, this);
There are other events that call renderNow but always with wxCliendDC, I've run a search for wxPaintDC in the .cpp file and I found only the line in the onPaint method so I'm really sure about this.

For the 2D

Code: Select all

void Viewer2D::onPaint(wxPaintEvent &evt) {
    wxPaintDC dc(drawingSurface);
    render(dc);
}
The bindings

Code: Select all

// setting event bindings
    drawingSurface->Bind(
        wxEVT_PAINT, &Viewer2D::onPaint,
        this
    );
    toolbar->Bind(
        wxEVT_TOOL,
        &Viewer2D::onToolButtonClicked,
        this,
        zoomPlusID,
        centerID
    );
    drawingSurface->Bind(
        wxEVT_MOTION,
        &Viewer2D::onMouseMove,
        this
    );
drawingSurface is a wxPanel.
Same as before the render method is called in other events like onToolButtonClicked but the wxPaintDC is created only in the method onPaint

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

Re: failed in wxPaintDCImpl() in a Paint Event

Post by doublemax » Tue Mar 05, 2019 10:50 am

Code: Select all

drawingSurface->Bind(
        wxEVT_PAINT, &Viewer2D::onPaint,
        this
    );
This looks suspicious. I assume "this" inside the paint event handler should be "drawingSurface" and not the "this" from the context of this call. Try passing "drawingSurface" instead of "this". What type is "drawingSurface"?
Use the source, Luke!

NoeMurr
Knows some wx things
Knows some wx things
Posts: 32
Joined: Sat Mar 31, 2018 2:26 pm

Re: failed in wxPaintDCImpl() in a Paint Event

Post by NoeMurr » Tue Mar 05, 2019 11:59 am

drawingSurface is a wxPanel *.

If I change this with drawingSurface

Code: Select all

drawingSurface->Bind(
        wxEVT_PAINT, &Viewer2D::onPaint,
        /*this*/ drawingSurface
);
it does not compile because the compiler cannot initialize a variable of type Viewer2D* with a wxPanel*.

The widgets Viewer2D is derived from wxPanel and it contains 3 widgets: a toolbar, a wxPane (the drawingSurface) and a status bar.
Here I'm binding my onPaint to the Event wxEVT_PAINT of the drawingSurface because I want to draw my custom content inside the panel when it is paint.

So the event is fired by drawingSurface, but the handler the viewer3D object.

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

Re: failed in wxPaintDCImpl() in a Paint Event

Post by doublemax » Tue Mar 05, 2019 3:00 pm

So the event is fired by drawingSurface, but the handler the viewer3D object.
Ok. In that case leave the Bind call as it was before, but inside the paint event handler, use wxPaintDC dc(drawingSurface); instead of wxPaintDC dc(this);
Use the source, Luke!

NoeMurr
Knows some wx things
Knows some wx things
Posts: 32
Joined: Sat Mar 31, 2018 2:26 pm

Re: failed in wxPaintDCImpl() in a Paint Event

Post by NoeMurr » Tue Mar 05, 2019 3:30 pm

It's already like that... you can see it in the first post. It is the code of Viewer2D::onPaint

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

Re: failed in wxPaintDCImpl() in a Paint Event

Post by doublemax » Tue Mar 05, 2019 4:36 pm

Sorry, i overlooked that. But there must be a mismatch somewhere. Try commenting out all paint event handlers and bring them back one by one. Hopefully you can narrow down who's the culprit.
Use the source, Luke!

NoeMurr
Knows some wx things
Knows some wx things
Posts: 32
Joined: Sat Mar 31, 2018 2:26 pm

Re: failed in wxPaintDCImpl() in a Paint Event

Post by NoeMurr » Tue Mar 05, 2019 6:40 pm

I've already checked it. The exception is thrown or in the Viewer2D::onPaint or in Viewer3D::onPaint (it depends on which is painted first) in the creation of the wxPaintDC that I've shown.

It is really curious that the exception is thrown only when I use both my widgets together in the same wxSplitterWindow.
If I use only one of them, don't metter which of them, and in the empty "slot" of the wxSplitterWindow I put a simple wxPanel it all works fine.

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

Re: failed in wxPaintDCImpl() in a Paint Event

Post by doublemax » Tue Mar 05, 2019 6:46 pm

Is it really related to the splitter? What if you just put both views side-by-side in a horizontal boxsizer?

Can you test your code on another platform?

In any case, i'm out of ideas. I'd need a sample that shows the issue in order to dig deeper into it.
Use the source, Luke!

Post Reply