The most popular library to create GUI in Python is Tkinter, which is a part of standard Python installation. Tkinter is a mature and stable tool, widely ported and relatively easy to learn. However, it is also quite old with many drawbacks, among them, it has a limited set of widgets. Although the simplistic model is easy to learn, Tkinter also becomes cumbersome with more complex interfaces. Above all, it does not support mobile and web application development.
Having a traditional desktop application developed in Tkinter, we want to adapt it to modern standards by implementing a web GUI. However, migration can be a time-consuming task. One of the approaches is to make it an evolutionary process, i.e. we allow situations where we will have both a desktop and a web application at the same time. This enables developers to gradually replace desktop windows with web controls what allows them to avoid working with two versions of an application (Tkinter and Flask). In such a case, both GUI modules will cooperate and communicate with each other. After the final Flask version is ready, we can remove unnecessary Tkinter code.
Below, I present a draft of such an approach. Both GUIs, represented by the functions tk_main and flask_main, have to be in separate threads. To reduce the number of threads, we can reuse the main thread and assign to it the Tkinter GUI. For the Flask GUI, we create a new thread (see e.g. here for information about Python threads). In the Tkinter part, represented by the TkApp class, we define a button that clicked opens a web browser with a Flask webpage. Simultaneously, we pass an argument to a Flask through a global variable, which is a bit cumbersome but I strived for simplicity in this example. After running the example, we can use at the same time both GUIs – a useful feature while migrating our application. In case something goes wrong with your new Flask window – you have still a Tkinter backup what makes the application always usable.
In the next step, we will migrate an exemplary Tkinter widget — listbox. Let’s start with a messy code which mixed up computation and data presentation.
This code is working but is written against the principles of software engineering. To be ready to migrate i.e. replace the Tkinter with HTML GUI, we must extract the code responsible for displaying data. The GUI functionality should take care only of data presentation and keep away from data processing.
After some cleanup, we divided the functionality of our code into functions prepare_data, process_data and show_data. These are simple functions which model usual task of some applications: they acquire data, process it and display the results. The functions exchange data using cursor or list structures. The changes add some complexity to the code, but also makes it easier to introduce changes or allow for more efficient testing. Now we are ready to add the Flask part which consists of the class FlaskMyForm and the function flask_index. The FlaskMyForm represents a form which groups HTML controls but in our simple case, it has only one migrated widget SelectField. The function flask_index takes care of feeding the SelectField with data and rendering it on a website.
So, we have migrated a single widget. We don’t need to make changes in the rest of the code responsible for data communication and processing. Using this approach – separation GUI components from business logic, we can migrate the whole GUI replacing component by component.