With version 4.2, I turned my attention to facilitating rework in PAGE. That is, how do you use PAGE to tweak the GUI without loosing the supporting code that you have written? At the same time I want to allow one to view the changes with the run command button in the Python console.

Here is the situation. You design a GUI and generate the Python code using PAGE, which creates skeleton functions. You then fleshed out the skeleton functions to support the GUI and then decided to modify the GUI. If then you again generate the Python code for the GUI, you do not want to loose the application code which you have written to realize the application. This is the rework problem: How to keep your hard fought code when reworking the GUI?

Starting with version 4.2, I have tried to separate as completely as possible the automatically generated GUI code from the added support code. My approach is to create the generated GUI code in one Python module and the supporting code including skeleton functions and Tk variables in a separate Python support module to be imported by the GUI module. That is, now PAGE generates two Python modules, one for the GUI and one for the supporting code complete with the necessary linkage.

PAGE implements this schema as follows. PAGE now works with three files:

  • “<name>.tcl” which is the design description of the GUI suitable for input to PAGE. It can either be created in PAGE, passed to PAGE as a parameter, or opened from the File submenu of the main menu.
  • “<name>.py” which is the main python module generated by PAGE which contains the automatically code to create the GUI on the screen. It is meant to be completely generated by PAGE. This will be referred to as the GUI module.
  • “<name>” which contains the code supporting the GUI module. PAGE creates a skeleton of this module that contains all of the necessary boiler plate code for linkage to the GUI module as well as the definitions of the Tkinter variables and skeleton versions of callback routines. I will be referring to this as the support module.

In the above, “<name>” is the application name (it was called the project name in the original Visual Tcl program) selected by the user when the system saves the ”.tcl” or extracted from the file name which may be supplied as a parameter when invoking PAGE.

It is expected that the user will generate a new version of the GUI module whenever he modifies the GUI but will need PAGE to modify the support module only when new Tkinter variables or callback functions are defined. The first will be much more frequent than the latter. Further, version 4.3 provides a mechanism for updating the support module by adding the new Tkinter variables and callback functions skeletons to an existing support module.

Generation of either Python module will attempt to save the tcl file and in so doing may ask if you really want to save it. If you do not answer “yes” the root file name may not be known and bad code could be generated.

Let me repeat: You should only generate the support module once for an application; otherwise any code which you manually added will be lost. Well, just in case you do that inadvertently, PAGE will save some previous versions as backups. If you add new or change widgets in the GUI or modify callback functions or Tkinter variables changes will have to be made to the support module.

When saving the support module PAGE will test to see if a support module with the same name exists and if it does, it will question the user as to whether he wishes to continue and if continue, whether to replace or update the module.

For an example of the separation of the GUI module from the support module, see the WCPE directory in the examples directory. This is a program that displays the program of WCPE which is one of my favorite classical music stations. In this example all of the functional code is located in and the GUI design is recorded in which is the main module. I found it very tricky to deal with time zones and did not want to loose any of that code and have to redo it or to deal with diffs; at the same time, I was constantly tweaking the GUI. I generated the import module once and proceeded fill out the “init” function and the callback functions in while tweaking the GUI, i.e., changing its location, color, the size of the display fields, fonts, etc..

It may be instructive in that it exemplifies an application comprised of two top level windows where one of the windows accesses Tkinter variables in the second window.

With chagrin, I apologize to the PAGE users for not having thought of this solution to rework long ago. Even though I have tested the idea with several examples, some of which are included in the section on examples, I worry that I have overlooked something big. So if you find any problems or oversights, please let me know.

Automatically Updating the Support Module

The is the new feature of PAGE introduced with version 4.3. The basic idea is that reworking the GUI design may introduce new callback functions or Tkinter variables which need to incorporated into the support module. PAGE can now add those entities to the support module. That is, new skeletal functions are added and new entries are added to the set_Tk_var function, if necessary the set_Tk_var function is added. All this while leaving the rest of the existing support module unchanged.

If Control-U was selected to generate the support module, then the user will be given the options of:

  • generating the support module anew,
  • using an existing support module, thereby utilizing the existing handwritten code; the old support module will be displayed.
  • updating an existing support module to preserve the existing code and adding new Tk Variables or skeleton callback functions.

To rephrase the above, when the user selects Gen_Python->Generate Support Module from the main menu or selects Control-U, PAGE will analyze an existing support module and compare the callback functions and Tkinter variables in it with those utilized in the reworked design. If new entities are required the user will be given the option of automatically adding them. Existing code is not removed or modified. It is up to the user to remove or otherwise deal with code no longer needed.

To mitigate case where the update process damages an existing support module, PAGE keeps several backups.


By reuse, I mean the using of widget definitions used and defined in previous PAGE projects. The two aspects of reuse are:

  • Using existing projects as templates.
  • Borrowing widget definitions from existing projects.


Very simple, just load the project you want to use as a template and do a “Save As...” from the main menu providing the name of the new project.

Borrowing Widgets from Existing Projects

With borrowing one retrieves and opens an existing project, which I will refer as the Lender GUI, at the same time as the current project is open and then copies elements from the existing GUI and pastes them onto the current GUI. For instance one might have a frame with and array of buttons in one GUI and would like to replicate it in another project.

PAGE will only build projects with one GUI, but with this new capability introduced in version 4.10, the user can open up the GUI from an existing project and use that GUI as a source of widget definitions using the existing cut, copy, and paste functions. This facility is invoked by selecting the Borrow command from the File menu.

The Lender GUI is read only in the sense that the save functions will ignore it, leaving it unchanged on disk. So don’t worry about changes you might make to the Lender GUI. By the same token you cannot make changes to the Lender GUI that you would like to save.

The Lender GUI is opened via File->Borrow menu entry. When it is opened, the toplevel background is set to Plum so that the user will recognize it as a Lender GUI. I chose Plum because I doubt that many users will choose Plum as a toplevel background color. It is possible even likely that the Lender GUI will overlap or obscure the current GUI under construction; in that case just move it to the side to expose the current GUI.

This feature required a minor change in the format of the project tcl file. That means that a project file created before version 4.10 will need to be opened and saved before it can be a lender. Remember to use “Save as” instead of “Save” which only saves if the main GUI has been changed.

A peculiar side effect of borrowing is that if the Lender GUI happens to have context (popup) menus, they will be incorporated in the main GUI. That is because every bit of documentation that I could find on context menus used root as the parent rather than a Toplevel window; so I did too. This may not be too bad because if you don’t bind to them they will never be invoked. Further, if you borrow a widget which is bound to a popup you will likely want to pull over the menu as well as the widget. If not wanted context widgets are easily deleted from the Widget Tree. Comments solicited.

With version 4.11, the Menu Bar from the Lender GUI may be copied and pasted into the current GUI. To do that

  • Select the Menu Bar entry in the Widget Tree with Button-3 and then the Copy entry of the popupmenu, select the toplevel window with Button-3.
  • Select the Copy entry in the popup window.
  • Select the Toplevel GUI window with Button-3.
  • Select the Paste entry in the popup window.
  • Press Button-1 anywhere in the Toplevel GUI window.

When finished with a lender GUI, one is tempted to close the windowby means of the little “x” in the corner. The better way is to select the toplevel widget and use “Delete” item in the widget menu obtained by Button-3.

Borrowing is a new function, so please report any problems encountered.