Problems calling Refresh() from a different class Topic is solved

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
forrestcupp
Earned some good credits
Earned some good credits
Posts: 102
Joined: Thu Dec 28, 2006 5:12 pm
Location: Indiana, US

Problems calling Refresh() from a different class

Post by forrestcupp » Fri Oct 14, 2011 12:37 am

Let's say my main frame is called MyFrame and I have another class called wxAnimatePng. One of the parameters in the wxAnimatePng constructor takes the wxPanel that gets drawn to in MyFrame::OnPaint and it puts it in a wxWindow pointer that is a member of the wxAnimatePng class. That wxWindow is called parent, and it is a pointer to the wxPanel in MyFrame.

So, I have a wxTimer in wxAnimatePng that gets updated every 10ms and figures out whether it's time to go to the next frame in the animation. At the end of the timer event handler, I put a parent->Refresh() so that the panel in MyFrame gets refreshed. This is necessary for the next frame of the animation to get updated and drawn.

This works perfectly while the app is running, but as soon as I close the window, it always throws this error:
Unhandled exception at 0x778715ee in testanimate.exe: 0xC0000005: Access violation reading location 0xfeef0006.
When I comment out the line with parent->Refresh(), it doesn't update the animation, but it also doesn't throw that error when the window is closed.

Here is my timer code:

Code: Select all

void wxAnimatePng::OnTimer(wxTimerEvent &event)
{
	currentTime += 10;
	if(currentTime > frameTime[currentFrame])
	{
		currentTime = 0;
		currentFrame++;
		if(currentFrame > frame.size()-1)
		{
			if(frame.size() > 1)
				currentFrame = 1;
			else
				currentFrame = 0;
		}
	}
	parent->Refresh();
}
frame is an std::vector of wxImages. frameTime is an std::vector of shorts that stores the number of milliseconds each frame lasts.

Any ideas?

Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Re: Problems calling Refresh() from a different class

Post by Auria » Fri Oct 14, 2011 12:47 am

make sure the "parent" pointer is OK, this looks like a symptom of an invalid pointer
"Keyboard not detected. Press F1 to continue"
-- Windows

forrestcupp
Earned some good credits
Earned some good credits
Posts: 102
Joined: Thu Dec 28, 2006 5:12 pm
Location: Indiana, US

Re: Problems calling Refresh() from a different class

Post by forrestcupp » Fri Oct 14, 2011 10:55 am

It does seem like that from the error, but the problem is that it works while the program is running. I can run the program for an hour and it will sit there running through the animation frames perfectly. Then when I finally close the window, that's when I get the error, and it's stopped at IMPLEMENT_APP.

Here is the relevant code for passing the panel to the wxAnimatePng constructor from the MyFrame constructor. Maybe you can see something that I don't.

From the MyFrame constructor (MyFrame is actually called testanimateFrame):

Code: Select all

	panel = new wxPanel(this, -1);
	panel->SetDoubleBuffered(true);
	panel->Connect(-1, wxEVT_PAINT,
		wxPaintEventHandler(testanimateFrame::OnPaint), NULL, this);
	
	wxImage::AddHandler(new wxPNGHandler);
	imgTemp.LoadFile(wxT("res/chRightStand.png"), wxBITMAP_TYPE_PNG);
	apChef = new wxAnimatePng(imgTemp, wxPoint(250,100), panel);
wxAnimatePng takes a wxImage for the frame when the animation is stopped, a wxPoint for its position, and a wxWindow* to draw the animation on. There is a Show(wxDC *dc) function that is called from MyFrame::OnPaint and that DC draws to whatever "parent" wxWindow you pass to the wxAnimatePng object. I've already tried putting my MyFrame panel on the stack instead of making it a pointer, and it crashed immediately instead of at the end.

Here is the applicable code from the wxAnimatePng constructor:

Code: Select all

wxAnimatePng::wxAnimatePng(wxImage StoppedImage, wxPoint Position, wxWindow *Parent) :
	wxFrame()
{
	parent = Parent;

	this->Connect(-1,wxEVT_TIMER,
		wxTimerEventHandler(wxAnimatePng::OnTimer));
	timer = new wxTimer(this, -1);
}
I call parent->Refresh() at the end of the timer event handler. I had to inherit from wxFrame to be able to connect to the timer event handler. Remember that everything works error free when parent->Refresh() is commented out, except that the frames don't get redrawn, which is the whole point. I can't really see how the pointer could be bad, but I don't really have any idea what else it would be.

Thanks for your help.

forrestcupp
Earned some good credits
Earned some good credits
Posts: 102
Joined: Thu Dec 28, 2006 5:12 pm
Location: Indiana, US

Re: Problems calling Refresh() from a different class

Post by forrestcupp » Fri Oct 14, 2011 11:14 am

I just figured out my whole problem and it was a very stupid mistake. I didn't have a proper destructor in wxAnimatePng to delete the timer pointer that was created. Once I put that in there, everything works perfectly.

What a stupid mistake! Thanks for your help.

Post Reply