Case when wxGLCanvas::Refresh() doesn't refresh the screen

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
philm
Experienced Solver
Experienced Solver
Posts: 88
Joined: Fri Dec 18, 2015 4:46 am

Case when wxGLCanvas::Refresh() doesn't refresh the screen

Post by philm »

Hello all,

I am not sure if I came across a bug in the library or a bug in my program. I am hoping that it is a bug in my program but I am having a hard time seeing what code is wrong. I willl describe this the best that I can but please let me know if you need additional information

I have a button on my main program that will allow the user to load in a data file. If the user loads in a data file, the program will rebuild the data structure and, once finished, redraw elements on the canvas. The code that does this is below:

Code: Select all

	void model::setParameters(gridPreferences &gridParam, geometryEditor2D &editorParam, std::vector<double> &otherParam)
	{
		_preferences = gridParam;
		_editor = editorParam;
		/*
		 * This is required and must be done after the program copies the editor data structure.
		 * If the data structure is rebuilt after it is loaded, then all of the addresses will
		 * become invalided. This is so because the editor data structure is now occupying a 
		 * different block of memory.
		 */ 
		_editor.rebuildDataStructure();
		_zoomX = otherParam.at(0);
		_zoomY = otherParam.at(1);
		_cameraX = otherParam.at(2);
		_cameraY = otherParam.at(3);
		this->Refresh();
	}
Note that model inherits from wxGLCanvas.

This function calls the load function which calls the setParameters function and is executed on a button press:

Code: Select all

void MainFrame::onOpenFile(wxCommandEvent &event)
{	
	wxFileDialog openFileDialog(this, "Open File", "", "", "", wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR);
	
	if(openFileDialog.ShowModal() != wxID_CANCEL)
	{
		if(_UIState != systemState::MODEL_DEFINING)
			createModelDefiningClient();
			
		wxString appendedTitle = "Omni-FEM - ";
		wxString fileName;
		std::string tempFileName = openFileDialog.GetFilename().ToStdString();
		for(int i = 0; i < (tempFileName.length() - 8); i++)
			fileName += wxString(tempFileName[i]);
		appendedTitle.append(fileName.ToStdString());
		this->SetTitle(appendedTitle);
		_saveFilePath = openFileDialog.GetPath();
		_problemDefinition.defintionClear();
		load(openFileDialog.GetPath().ToStdString());
		_model->Refresh(true);
	}
}
Now the load function is below:

Code: Select all

void MainFrame::load(string filePath)
{
	std::ifstream loadFile(filePath);
	
	if(loadFile.is_open())
	{
		//modelDefinition temp(this, wxPoint(6, 6), this->GetClientSize(), _problemDefinition, this->GetStatusBar());
		//modelDefinition tempDefintion = (*_model);
		boost::archive::text_iarchive ia(loadFile);
		gridPreferences tempPreferences;
		geometryEditor2D tempEditor;
		std::vector<double> tempSomething;
		
		ia >> _problemDefinition;
		ia >> tempPreferences;
		ia >> tempEditor;
		ia >> tempSomething;
		
		_model->setParameters(tempPreferences, tempEditor, tempSomething);
		
		_model->Refresh();
	}
}
Now, as we can see, I call the Refresh function 3 times on 1 button press. Through using the debugger, I only count 1 time that the program executes my draw function. (I may need to double check this)

When the draw function was called, it was able to "draw" the elements needed on the canvas. But, after the swap buffer function was executed, my canvas was still blank.

Until, I move my mouse over the canvas.(Each time the mouse moves, an event is generated which will cause the canvas to be refreshed) When this happens, everything is drawn normally.

I am wondering if there is anything in the above code that could interfere with the refresh function? Also, have there been additional bugs where the refresh function does not actually refresh the canvas?

Any help would be appreciated and please, let me know if additional information is needed!
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Case when wxGLCanvas::Refresh() doesn't refresh the screen

Post by doublemax »

Now, as we can see, I call the Refresh function 3 times on 1 button press. Through using the debugger, I only count 1 time that the program executes my draw function. (I may need to double check this)
That's normal. Refresh() just tells the OS to invalidate the window content, it doesn't perform a redraw. The redraw only happens when your code is done and the wxWidgets event loop starts processing events again. You can force an immediate redraw by calling Update() after Refresh().

But i don't know why the first redraw does not work. Is it possible there is still something not initialized correctly when the paint event is called for the first time after loading?
Use the source, Luke!
philm
Experienced Solver
Experienced Solver
Posts: 88
Joined: Fri Dec 18, 2015 4:46 am

Re: Case when wxGLCanvas::Refresh() doesn't refresh the screen

Post by philm »

doublemax wrote:
Now, as we can see, I call the Refresh function 3 times on 1 button press. Through using the debugger, I only count 1 time that the program executes my draw function. (I may need to double check this)
That's normal. Refresh() just tells the OS to invalidate the window content, it doesn't perform a redraw. The redraw only happens when your code is done and the wxWidgets event loop starts processing events again. You can force an immediate redraw by calling Update() after Refresh().

But i don't know why the first redraw does not work. Is it possible there is still something not initialized correctly when the paint event is called for the first time after loading?
Hello doubleMAx,

Thank you for your input. I placed the Update function right after the refresh(). I commented out all of the places that I am calling the update function except for 1 spot, this spot is in the setParameters function. I believe that I posted the code snippet above.

I have verified that the program does go into the paint event. However, even with the Update, the canvas remains blank until I move my mouse over the canvas.

The mouse event does call the update function so it is able to draw.

As for things not being initialized correctly. I am not sure. My guess would be yes because in the paint event, all geometries call their respective draw functions. There is no error.

Are there any data types I should look out for when running through the code to make sure everything is initialized properly?
philm
Experienced Solver
Experienced Solver
Posts: 88
Joined: Fri Dec 18, 2015 4:46 am

Re: Case when wxGLCanvas::Refresh() doesn't refresh the screen

Post by philm »

So looking through the code, there is not much difference between after onOpenFile function and the event procedure that is fired when the mouse is moved on the canvas.

In the load function, by the time load parameters is ran, the canvas is already loaded and ready to go, in terms of setting up variables.

I have noticed that a resize event gets fired multiple times. This is excepted since I am changing the size of the canvas on startup. BY the time that the resize event is fired, the size of the canvas is already set. Still though, nothing is drawn on the canvas. It still has it's default color.

At this point, if I am to move my mouse or resize the window of the entire program, the canvas is able to draw the items on the sreen.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Case when wxGLCanvas::Refresh() doesn't refresh the screen

Post by doublemax »

I can't tell you what it is, but there must be some difference between the two states, immediately after loading and when the first mouse event arrives.

What happens if you use keyboard commands to hide and show (or minimize and restore) the window immediately after loading (without ever moving the mouse). Does the redraw work or not. If not, the solution is definitely inside your mouse event handler.
Use the source, Luke!
Post Reply