Multi Windows, open/close it programatically. Is there a way?

#1

Hi guys,

Been looking to the new multi window feature in OF for a possible project. It’s pretty cool that now you can set multiple windows so easily.

I just wonder one thing, after closing the window is there a way to open it again programatically?

Thanks,
João

#2

Hey, that’s a complex question to answer, it depends on your specific needs.
Raven Kwok has recently done some experiments with windows using Processing.

Looking at the multiWindowOneAppExample, I just tried making them on the fly from the main ofApp and it seems to run stable.

ofApp.h

std::vector<shared_ptr<ofAppBaseWindow> > windows;
void drawRandomInWindow(ofEventArgs & args);

ofApp.cpp


	void ofApp::keyPressed(int key){
		ofGLFWWindowSettings settings;
		settings.width = 300;
		settings.height = 300;
		settings.setPosition(ofVec2f(0,0));
		settings.resizable = false;
		windows.push_back( ofCreateWindow(settings) );
		windows.back()->setVerticalSync(false);

		ofAddListener(windows.back()->events().draw, this,&ofApp::drawRandomInWindow);
	}

	void ofApp::drawRandomInWindow(ofEventArgs &args){
		ofPushStyle();
		ofSetColor(ofRandom(128,255));
		ofFill();
		ofDrawRectangle(ofRandomuf()*20.f, ofRandomuf()*20.f, ofRandomuf()*80.f, ofRandomuf()*80.f);
		ofPopStyle();
	}

	// add to ofApp::setup() to manipulate created windows
	for(auto it=windows.begin(); it!=windows.end(); it++){
		ofDefaultVec2 pos(150+cos(fmod(ofGetElapsedTimef(),TWO_PI)) * 100.f, 150+sin(fmod(ofGetElapsedTimef(),TWO_PI)) * 100.f);
		(*it)->setWindowPosition(pos.x, pos.y);
	}
1 Like
#3

Hi @Daan,

Awesome, thanks a lot for the insight :slight_smile:

#4

awesome indeed… thanks a lot…

is it also possible to do…
settings.shareContextWith = mainWindow;
with this method?
or how can i access/refer to windows created in main.cpp?

and how is it possible to identify different elements of the vector with the “auto it” method?

greetz

pls

#5

You have either to register the window instances from your ofApp (not in main.cpp), store them, then loop trough them to send commands.

In the example above, when you press a key, windows is populated with a new window instance.
The last piece of code in my example above shows how to loop trough them and call a member function on each (setWindowPosition).

Another way to communicate is to listen to window events.
ofAddListener(windows.back()->events().draw, this,&ofApp::drawRandomInWindow);

1 Like
#6

thanks a lot… sorry for my late reply… did not login for quite a long time…
so you are not doing any window related stuff in main.cpp?

#7

No worries :slight_smile:
Yes that’s right, no window stuff in main.cpp

1 Like
#8

Hi ! So im developing a software that also uses a render window to show the output.

It seems like the window that i´ve created programatically can´t render the FBOs that im using in my main window as shown in this image :

As you can see. The image that have the visual(wich is my main window) works just fine.
but the window that i´ve open programatically does not render the fbos allthought it renders the drawings that @Daan uses as an example.

this is my code :

The function that opens the window:

void ofApp::openRenderWindow() {
	ofGLFWWindowSettings settings;
	settings.setSize(600, 600);
	settings.setPosition(ofVec2f(20, 50));
	settings.resizable = false;
	//settings.shareContextWith = &ofApp;
	//settings.setGLVersion(4, 5);
	windows.push_back(ofCreateWindow(settings));
	//windows.back()->setVerticalSync(false);

	ofAddListener(windows.back()->events().draw, this, &ofApp::drawRandomInWindow);

}

The function that draws inside the other window :

void ofApp::drawRandomInWindow(ofEventArgs &args) {
	ofPushStyle();
	ofSetColor(ofRandom(128, 255));
	ofFill();
	ofDrawRectangle(ofRandomuf()*20.f, ofRandomuf()*20.f, ofRandomuf()*80.f, ofRandomuf()*80.f);
	ofPopStyle();

	boxes.draw();
}

How ever im able to draw my fbos with shaders in a second window if i make how @edapx teach me how to do it in this post : How to separate windows and use one as renderer

is this because i can´t set settings.shareContextWith if i try to do it inside the ofapp? So, im making the question that @sinsynplus make. Is it posible to set settings.shareContextWith inside my ofApp?

and if it is posible, is this the reason why my fbos with shaders are not being drawn in the second window?

Thanks in advance.

#9

fbos can’t be shated between windows but you can share a texture between them. So if you create an fbo in one window you can’t draw on it from the other but you can draw it’s texture in the other.

In order to allow that though you need to share the context by using:

settings.shareContextWith = mainWindow;

where mainWindow is the window you get when calling ofCreateWindow in main, since it’s a shared pointer you can store a copy in your application for example to use it later

#10

But how to have a pointer to the mainWindow if I creating the windows inside my ofApp an NOT in the main?

I mean, I should get a pointer to the same ofApp instance inside a ofApp instance function. Is there any way to set settings.shaderContextWith NOT in the main buy inside the offapp.cpp ?

#11

no, the pointer is not to the ofApp but to the window. in main when creating the window you can do:

auto window = ofCreateWindow();
auto app = new ofApp;
app.window = window;

where window is a member variable in ofApp like:

std::shared_ptr<ofGLFWAppWindow> window;
#12

Excelent ! Now is working !!!.

Thank you very much.

Do you now if there is a way to get the keypressed and mousepressed and mouse positions that i´ve made in the programatically created windows!? Like listen to keypressed and mousepressed but from the windows that are being generate.

And also. Is there any way to get a listener when that window is closed?
Because it seems like the my windows vector keeps having the pointers of the windows that i´ve closed.

also : I want to point that it work using :

std::shared_ptr<ofAppBaseWindow> mainWindow;

and not

std::shared_ptr<ofGLFWAppWindow> window;

ofGLFWAppWindow is not recognized as an object in my ofApp.h

#13

Ok.

So .

Im replying my self. I´ve managed to handle all the listeners.

Heres is my final code about managing windows :

In the ofApp.h :

//Everything to do about windows. Listeners and stuff 
		std::vector<shared_ptr<ofAppBaseWindow> > windows; 
		std::shared_ptr<ofAppBaseWindow> mainWindow;
		bool isRenderWindowOpen = false;
		bool isRenderWindowFullscreen = false;
		void window_drawRender(ofEventArgs &args);
		void window_mouseMove(ofMouseEventArgs & e);
		void window_keyPressed(ofKeyEventArgs& e);

and this is my offApp.cpp


void ofApp::keyPressed(int key) {
if (key == 'w') {
		openRenderWindow();
	}

}
void ofApp::openRenderWindow() {
	if (!isRenderWindowOpen) {

		isRenderWindowOpen = true;
	ofGLFWWindowSettings settings;
	settings.setSize(600, 600);
	settings.setPosition(ofVec2f(20, 50));
	settings.resizable = true;
	settings.shareContextWith = mainWindow;
	
	windows.push_back(ofCreateWindow(settings));
	//windows.back()->setVerticalSync(false);
	cout << "windows size" << windows.size() << endl; 

	ofAddListener(windows.back()->events().draw, this, &ofApp::window_drawRender);
	ofAddListener(windows.back()->events().exit, this, &ofApp::exit);
	ofAddListener(windows.back()->events().keyPressed, this, &ofApp::window_keyPressed);
	ofAddListener(windows.back()->events().mouseMoved, this, &ofApp::window_mouseMove);

	}
}


//LISTENERS DE LAS VENTANAS:
void ofApp::window_drawRender(ofEventArgs &args) {
	//boxes.draw_activerender();
       //HERE WRITE YOUR DRAWING CODE
}
void ofApp::exit(ofEventArgs & e){
	cout << "EXIT WINDOW " << endl;
	windows.clear();
	isRenderWindowFullscreen = false;
	isRenderWindowOpen = false;
}

void ofApp::window_mouseMove(ofMouseEventArgs& e) {
	cout << "MOUSE X " << e.x <<endl;
	cout << "MOUSE Y " << e.y << endl;
}

void ofApp::window_keyPressed(ofKeyEventArgs& e) {
	cout << "KEYCODE ON WINDOWS : " << e.keycode << endl;

	if (e.keycode == 70) {
		isRenderWindowFullscreen = !isRenderWindowFullscreen;
		windows.back()->setFullscreen(isRenderWindowFullscreen);
	}
}
#14

you can also simply call ofRunApp(newWindow, otherApp)where otherApp is a new class that implements ofBaseApp and OF will hook up all the events for you.

The pointers of course won’t magically disappear from the vector you need to listen to the exit event for the newly created window and remove it’s pointer from the vector when it’s about to exit

also take a look at the example multiWindowExample, everything in there works no matter if the window is created from main or anywhere else