1

I am building a relatively large application based on Tkinter. Whenever I make a code change, I have to reload the application manually, and then use the GUI to go back to the desired state.

For instance, if I had open an image in the app before changing the code, and I want to open it again, I have first to open the GUI, select the image from the drop-down list and so on... This is a waste of time. Is there a way to automatically reload the application/GUI after a code change in the last state it was?

  • This may not be possible in the general case, but occasionally [runtime - how to "reimport" module to python then code be changed after import - Stack Overflow](https://stackoverflow.com/questions/4111640/how-to-reimport-module-to-python-then-code-be-changed-after-import) is possible – user202729 Sep 02 '21 at 14:01
  • Hi, thanks for the reply. I am bit scared of using reload since I don't know how it behaves when you have stateful objects. Moreover, on the web, people says it introduces hidden pitfalls. – Tommaso Bendinelli Sep 02 '21 at 14:03

1 Answers1

1

This question has been asked a number of times

Proper way to reload a python module from the console

You can use reload(module) for this, but beware of nasty side effects. For example, existing code will be based on the original code, it will not magically get new attributes or baseclasses added.

Another great resource on this would be https://code.activestate.com/recipes/580707-reload-tkinter-application-like-a-browser/

After you've described you're problem a bit further in the comments, I was able to reconstruct the issue better on my end.

Here's my basic implementation for a solution to your issue:

from tkinter import *
import json

application_state = {"background": "white"}  
background_colors = ["white", "red", "blue", "yellow", "green"]


def main():
   root = Tk()
   root.title("Test")
   root.geometry("400x400")
   reload_state(root)

   for color in background_colors:
      def change_background_wrapper(color=color, root=root):
         change_background(color, root)

      Button(root, text=color,command=change_background_wrapper).pack()

   root.mainloop()


def change_background(color, window):
   print("new color: " + color)
   window.configure(bg=color)
   application_state["background"] = color
   update_config()


def reload_state(window):
   config_file = open("config.json")
   conf = json.load(config_file)
   window.configure(bg=conf["background"])


def update_config():
   with open("config.json", "w") as conf:
      conf.write(json.dumps(application_state))


if __name__ == "__main__":
   main()

In this instance, we're able to update the background color of the GUI and it will persist on each rerun of the script, until it gets manually changed again. You can apply this concept to pretty much any sort of state you have inside your application, I think this should get you started!

Bialomazur
  • 1,122
  • 2
  • 7
  • 18
  • Hi, Thanks for the reply. I am not interested changing the app during runtime. I want to restart it without manually having to recreate the previous state. – Tommaso Bendinelli Sep 02 '21 at 14:05
  • @TommasoBendinelli Okay now I get what you're trying to do, let me tell you that it is possible - **but** you will probably have to implement something on your own in order to achieve this. I think the easiest & fastest approach would be to create a **config file** for the **GUI**. I would contain information on it's current state like **selected file path, active buttons, title,...** basically every interactive element that can change or has some sort of state inside your GUI would have to be saved & updated inside this file and on each rerun of your script *I'll continue in a second comment* – Bialomazur Sep 02 '21 at 14:10
  • @Tomasso Bendinelli you'll have to read the config file inside your script and rerender all information it contained. The format can be as simple as a **.json file** and you would keep a **dictionary** in your code with all configurations & update it on each interactive change of the GUI, dump it with **json.dumps** and overwrite the config file with the information. To read it out again on each start you would use **json.loads**. I hope you get the idea. – Bialomazur Sep 02 '21 at 14:14
  • Yeah this makes sense. I would have loved to have something that already does it for you – Tommaso Bendinelli Sep 02 '21 at 14:21
  • @TommasoBendinelli I took my time to write a little example script for your use case. I'll include the code in my answer – Bialomazur Sep 02 '21 at 16:23