!!! warning "Pre-2.0 layout"
This page describes the pre-2.0 flat main.py layout. As of 2.0.0 the library is the
programver package (VersionDialog, programver/dialog.py) and main.py is a demo,
not the module itself — see Known Issues for what changed and
the README for current usage. This
page is pending a rewrite for 2.0.
One module, three functions, no dependencies.
main.py
├── get_resource_path(filename) resolve against __file__
├── openLicense() read LICENSE.txt → its own window
├── openEULA() read EULA.txt → its own window
└── ProgramVer() the main window, then mainloop()
base_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(base_dir, filename)Resolves against the module, not the working directory, so the window works wherever it is launched from and survives being copied into another project. Used for both images and both text files.
Builds the window and calls mainloop() itself, so it blocks until closed. That makes it a
drop-in call from a menu handler, and it means calling it from an existing Tkinter application
starts a second event loop — see below.
Widgets, top to bottom: logo, name and version, trademark notice, licence blurb, the two buttons, and the Python-Powered badge at the bottom.
Note that neither PhotoImage is bound to a lasting reference. They survive because they are
locals of a function that blocks in mainloop() — if ProgramVer() were refactored to return
the window instead, both images would be garbage-collected and the labels would render blank
with no error.
Identical in shape: construct a Tk(), read a text file, insert it into a Text widget, pack.
Two things follow. Neither calls mainloop() — they rely on the main window's loop, which works
because they are invoked from a button callback inside it. And both construct a second Tk()
root rather than a Toplevel(); Tkinter supports one true root per process, so closing the
wrong window can take the others with it.
Neither file is present in the repository. See
internal/known-issues.md.
Every displayed string is a literal, each marked # change as needed. There is no parameter, no
config object, and no settings file. The intended workflow is copying main.py into your project
and editing it.
That is a reasonable design for a component this small — a configurable version would need a schema for something a developer edits once — but it does mean the shipped defaults are visible to anyone who forgets to change them.
Tkinter and os. Nothing to install, and nothing added to the dependency tree of whatever
project copies it in.
The design is sound; three files it opens are absent. imgs/dfdlogo.gif stops the window
entirely, and the two .txt files break a button each. MANIFEST.in lists the image for
packaging, so its absence is an omission rather than a decision.