The Kivy Frontier: Multiple Independent Windows
Yes you can!
I’m running and testing on OSX10.11.4. This is all written in Python 3.4.2. Kivy version is 1.9.1.
I am in no way associated with Kivy. I picked it because it is the most up-to-date, modern GUI library available for Python. It can look good easily. Keyword, easily.
It’s important to keep in mind that Kivy is a cross-platform, cross-device GUI framework. It’s geared more towards touch devices than it is desktop. I haven’t played with it on mobile so I can’t speak to that.
Given that it’s built with a mobile, or at least touch input, mentality there are some obstacles for building non-mobile applications.
1. It does not support multiple windows running at the same time.
For instance, as you can take a tab of your browser bar and you have a new independent window, you cannot do that with standard Kivy. You’ll have to employ a workaround. That workaround brings us to obstacle number two.
2. Once you do figure out how to open up multiple windows the glaring issue of how to pass data between them becomes a show stopper.
Trying to work with subprocess.PIPE or hosting a local web server gets very ugly, very fast. I would not recommend going down this route. I’m not a hardcore Python person so it may be easier than I’m making it out to be¹.
The best way, in my opinion, is to set up a lightweight backend. Parse would have been the perfect solution for this because it was so simple but given the Parse-Server situation I opted for Firebase instead². You could go down any backend route to get the same result.
It’s interesting that the easiest way to communicate between two programs on the same machine is to push the data into the cloud and then retrieve it back. Perfect? Absolutely not. Effective? The internet was Title 2’ed, I’m willing to risk the slim chance of not having internet access. Especially when only transferring strings and ints.
Disclaimer: This is all very much a work in progress. I want to write it as I go so I don’t forget the little details later on. I’ll keep this updated as the project progresses.
This is how you run multiple windows:
Put the second application python file that you want to run in the same directory as your main.py. When you want to open it:
global secondApp
secondApp = subprocess.Popen('python3 secondAppFileName.py', shell=True)
When you want to close the second program:
global secondApp
secondApp.kill()
This is how you push it to another monitor on open:
So very hacky. But it works. I need the second app to be full screen on a second monitor. It seems that the second application will take on whatever display it’s in as it’s master and resize to it as long as you initialize it in that screen space. I have not yet tested this out for different monitor configurations or for different platforms.
from kivy.config import Config
Config.set('graphics', 'resizable', '0')
Config.set('graphics', 'position', 'custom')
Config.set('graphics', 'top', '-900')
Config.set('graphics', 'left', '0')
Config.set('graphics', 'fullscreen', 'auto')
If you have monitors in different arrangements you’ll have to account for that. I have yet to figure out the best way to do that accounting. Any suggestions would be greatly appreciated. Constructing a function that identifies whether the second monitor is to the left, right, top, or bottom, would be a wonderful help when releasing this type of program to the public.
¹Aside from the Kivy styling, this is my first application in pure Python.
²I’ve only scratched the surface of Firebase Database but so far it is refreshingly simple. In total, a PUT-GET roundtrip is only 4 total lines of cod not including error handling, using the data, etc.. It’s actually easier to setup than old Parse.com and way easier than Parse Server.
I would very much recommend not using the Python Firebase wrappers that are available. After a couple of hours of trial with the wrappers I abandoned ship and wrote my own RESTful methods. The wrappers are full of bugs and haven’t been updated since 2014.