Image1Link Image2Link Image3Link Image4Link

TkGridGUI

Builds A Python Tkinter Gui Graphic User Interface Using The Grid Geometry Manager.

See the Code at: https://github.com/sonofeft/TkGridGUI

See the Docs at: https://sonofefttkgridgui.readthedocs.io/en/latest/

See PyPI page at:https://pypi.python.org/pypi/tkgridgui

TkGridGUI is a graphic user interface for creating python Tkinter applications.

The user creates a fully “wired” python Tkinter GUI application by placing widgets into a hierarchical grid structure.

TkGridGUI generates python source code for all the basic Tkinter widgets, Button, Label and Entry, as well structures such as menus, notebooks and statusbars. Within the generated python source code, user application code is placed in designated areas.

Common widget bindings, keyboard shortcuts and StringVar objects are created by default.

The workflow moves between placing widgets, editing widget properties, adding application logic to the generated python source code and testing the application after each change.

TkGridGUI runs on Linux and Windows with python 2 and 3.

TkGridGUI

Contents:

QuickStart

Install TkGridGUI

The easiest way to install TkGridGUI is:

pip install tkgridgui

    OR on Linux
sudo pip install tkgridgui
    OR perhaps
pip install --user tkgridgui

Installation From Source

Much less common, but if installing from source, then the best way to install tkgridgui is still pip.

After navigating to the directory holding TkGridGUI source code, do the following:

cd full/path/to/tkgridgui
pip install -e .

    OR on Linux
sudo pip install -e .
    OR perhaps
pip install --user -e .

This will execute the local setup.py file and insure that the pip-specific commands in setup.py are run.

Verify tkinter

In Theory tkinter is included with all standard Python distributions. (In practice, it might not be included.) It’s almost certainly there on a Windows machine, however, on Linux you might have to try:

sudo apt-get update
sudo apt-get install python-tk
sudo apt-get install python3-tk

In order to get Tkinter/tkinter for python 2 & 3.

You can test the installation from a terminal window with:

>>> import Tkinter       # python2
>>> Tkinter._test()      # python2

>>> import tkinter       # python3
>>> tkinter._test()      # python3

This should pop up a small test window.

Running TkGridGUI

After installing with pip a launch command line program called tkgridgui or, on Windows, tkgridgui.exe will be in your machine’s system path.

Simply typing:

tkgridgui

will run TkGridGUI.

If not, then there may be an issue with your system path. The path for the tkgridgui executable might be something like:

/usr/local/bin/tkgridgui             (if installed with sudo pip install -e .)
     or
/home/<user>/.local/bin/tkgridgui    (if installed with pip install -e .)
     or
C:\Python27\Scripts\tkgridgui.exe    (on Windows)

Make sure your system path includes the proper path above.

Grid Notebook

When TkGridGUI launches, it presents the grid notebook shown below. When first opened, only the “Main” tab is on the notebook, however, as container widgets like Frames or RadioGroups are placed, their tabs will appear.

Widgets are selected from the listbox at the far left and are placed on the grid notebook with a left click. The widget to be placed is also highlighted at the lower left (in the example below, a green Button).

If additional rows or columns are needed, they can be inserted with the “+” operators along the blue upper and left side controls.

If weights are needed to control widget size when the main window is resized, the gold “wt” controls along the bottom and right side can be used. (don’t forget to set the sticky attribute of any widgets to be controlled by weight).

Additional features such as Main Menu or Status Bar can be selected with the check boxes along the left.

_images/empty_grid_notebook.jpg

Click Image to View Fill Size

Basic Usage:
  Select Widget in Listbox with Left Click.
  Place Widget with Left Click in grid.

Edit Widget:
  Right Click Widget in Grid or Preview Window.

Move Widget:
  Left Button Drag and Drop in Grid.

Duplicate Widget:
  Left Click Widget in Grid.
  Left Click in grid to place the duplicate.

Insert Row or Column with Left Click on "+" control.

Add Weight to row or column with "wt" control.

Select Corresponding Tab for Widgets in Frames, RadioGroups etc.

Preview Window

As widgets are added, the preview window will show the current state of the widgets in the application.

_images/example_preview_window.jpg _images/example_grid_notebook.jpg

Click Image to View Fill Size

Widget Attributes

Right click on a widget either in the Preview Window or the Grid Notebook to set its properties.

The example below shows the options available for a Button widget.

Note that for Color or Font, there are pop-up dialogs to select values for color or font.

Many of the options have drop-down selections for enumerated inputs like relief, state, cursor, etc.

_images/edit_button.jpg

Click Image to View Fill Size

Contrast Ratio

For widgets with a foreground and background color, a color selection control is present that helps select colors that comply with WCAG 2 Contrast Ratio guidance.

Contrast Ratio WCAG 2 see: https://en.wikipedia.org/wiki/Template:Color_contrast_ratio

_images/fg_bg_contrast_editor.jpg

Click Image to View Fill Size

Save Tkinter Application

When the GUI has been designed to your liking, or at various stages along the way, you can save your work with the menu option File/Save.

Two files are saved…

  1. An application definition file (*.def) that defines all the application’s attributes.
  2. A python source code file (*.py) with all of the Tkinter implemented statements.

Definition File

The definition file is structured like a configuration file with the overall attributes in the section call [app_attr] and each widget like [Button_1] etc. shown below that.:

[app_attr]
hideokbutton = no
hasstddialmess = no
add_menu_ctrl_keys = yes
name = example
guitype = main
hasstdalarm = no
menu = File\n  New\n  Open\n  Save\n\n  Exit\nHelp\n  Sounds\n    Moo\n    Meow
resizable = yes
hasmenu = yes
height = 151
width = 425
hasstddialcolor = no
col_weights =
row_weights =
hasstddialfile = no
y = 55
x = 1107
hasstatusbar = yes

[Button_1]
widget_type = Button
tab_label = Main
row = 2
col = 1
rowspan =
text = Push Me
docstring =
width = 15
columnspan =

[Button_2]
widget_type = Button
tab_label = Main
row = 3
col = 1
.
.
.

Python Tkinter File

The generated python code is designed to run under both python 2 and 3.

As such the import section checks for python version.

if sys.version_info < (3,):
    from future import standard_library
    standard_library.install_aliases()
    from ttk import Combobox, Progressbar, Separator, Treeview, Notebook
else:
    from tkinter.ttk import Combobox, Progressbar, Separator, Treeview, Notebook

from tkinter import *

All of the widgets are created by their own make method in order to organize the code.

self.make_Button_1( self.grid_frame ) #  Button: Push Me : at Main(2,1)
self.make_Button_2( self.grid_frame ) #  Button: Say Hello : at Main(3,1)
self.make_Entry_1( self.grid_frame )  #  Entry:  at Main(4,2)
self.make_Entry_2( self.grid_frame )  #  Entry:  at Main(5,2)
self.make_Label_1( self.grid_frame )  #  Label: My dog has fleas : at Main(6,3)
self.make_Label_2( self.grid_frame )  #  Label: Now is not the time for barking : at Main(7,3)

Menu items create keyboard accelerator keys by default.

# use both upper and lower characters for keyboard accelerator options.
self.master.bind("<Control-N>", lambda event: self.menu_File_New())
self.master.bind("<Control-n>", lambda event: self.menu_File_New())
self.master.bind("<Control-O>", lambda event: self.menu_File_Open())
self.master.bind("<Control-o>", lambda event: self.menu_File_Open())
self.master.bind("<Control-S>", lambda event: self.menu_File_Save())
self.master.bind("<Control-s>", lambda event: self.menu_File_Save())
self.master.bind("<Control-E>", lambda event: self.menu_File_Exit())
self.master.bind("<Control-e>", lambda event: self.menu_File_Exit())

User Code Areas

In general the generated python code is intended to be augmented with user code.

That user code is protected from change at each TkGridGUI Save command by placing it in protected user code areas.

For example, each widget’s make method has an area for user code marked by comments so that save operations do not overwrite customizations to the basic generated python code.

In the Button_1 example below, the text, width, row and column attributes will be overwritten every time TkGridGUI saves the file.

The bind command, however, will not be overwritten because it is in the protected user code area.

# TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Button_1"
def make_Button_1(self, frame):
    """      Button: Push Me : at Main(2,1)"""
    self.Button_1 = Button( frame , text="Push Me", width="15")
    self.Button_1.grid(row=2, column=1)

    # >>>>>>insert any user code below this comment for section "make_Button_1"

    self.Button_1.bind("<ButtonRelease-1>", self.Button_1_Click)

The same idea applies to the Button_1_Click method.

When the button is clicked, the user code will be executed and that code is protected from overwrite from TkGridGUI.

# TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Button_1_Click"
def Button_1_Click(self, event): #bind method for component ID=Button_1
    """      Button: Push Me : at Main(2,1)"""

    # >>>>>>insert any user code below this comment for section "Button_1_Click"
    # replace, delete, or comment-out the following
    print( "executed method Button_1_Click" )
    self.statusMessage.set("executed method Button_1_Click")

User code is protected for the automatically generated StringVar callback routines.

Whenever the value of the Entry_1_StringVar changes, this method is called.

# TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Entry_1_StringVar_traceName"
def Entry_1_StringVar_Callback(self, varName, index, mode):
    """       Entry:  at Main(4,2)"""

    # >>>>>>insert any user code below this comment for section "Entry_1_StringVar_traceName"
    # replace, delete, or comment-out the following
    print( "Entry_1_StringVar_Callback varName, index, mode",varName, index, mode )
    self.statusMessage.set("    Entry_1_StringVar = "+self.Entry_1_StringVar.get())
    print( "    new StringVar value =",self.Entry_1_StringVar.get() )

The automatically generated Menu routines also have user code areas.

Placing user menu logic in the protected user code area prevents TkGridGUI from overwriting it on Save operations.

# TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "menu_File_New"
def menu_File_New(self):

    # >>>>>>insert any user code below this comment for section "menu_File_New"
    # replace, delete, or comment-out the following
    self.statusMessage.set("called menu_File_New")
    print( "called menu_File_New" )

Examples

Named Color Dialog

The dialog for picking named colors within TkGridGUI was created by TkGridGUI.

The two images below show the dialog before and after a color is selected.

The objective of the dialog is to present named colors to the user for selection.

As an aid to selection, the colors can be sorted in four different ways; by hue, luminance, hex code or color name.

Once selected, the large Label at the top of the dialog uses the selected color as its background and gives the name, hex value, luminance, and contrast ratio with either white or black foreground depending on which is better.

_images/named_color_dialog.jpg _images/named_color_dialog_clicked.jpg

Click Image to View Fill Size

TkGridGUI Layout

The TkGridGUI layout for this project is very simple, just 4 widgets on the Main tab and two additional container tabs; an empty LabelFrame and a RadioGroup.

Each widget was selected from the listbox at the far left (labeled Widgets) and placed into the grid by Left Clicking at each grid location ((1,1) through (4,1)).

Note that when the mouse is over a widget on the grid interface (see Label_1 at (2,1) below) that the same widget is highlighted in the preview window (see the red Label_1 in the preview window below).

_images/mouse_over_highlight.jpg _images/mouse_over_highlight_preview.jpg

Click Image to View Fill Size

The RadioGroup tab holds ONLY RadioButtons by definition. The images below show the grid layout and preview for the RadioGroup_1 tab.

Again note the mouse-over highlight feature.

_images/radio_group_highlight.jpg _images/radio_group_highlight_preview.jpg

User Code

The empty Colors LabelFrame_1 is populated entirely with user code.

Each color has a Label object that has bind attributes to enable a mouse-over pop-up that shows the color’s name, as well as Left Click selection.

# >>>>>>insert any user code below this comment for section "top_of_init"

self.labelD = {} # index=(row,col): value=Label object
row = 0
col = 0
for (lum, lum_p05, h, r, g, b, cstr, name) in h_sorted_colorL:
    lab = Label( self.LabelFrame_1 , text="  ", width="3", padx=0, pady=0,
                 font=("times", "6", "normal"))
    lab.grid(row=row, column=col)
    self.labelD[ (row,col) ] = lab
    lab.configure( background=cstr, relief="raised" )

    lab.bind("<Enter>", self.label_enter)
    lab.bind("<Leave>", self.label_leave)
    lab.bind("<ButtonRelease-1>", self.ColorPickLabel_LeftClick)

    col += 1
    if col>=COL_COUNT:
        col = 0
        row += 1

In the validate method, the dialog returns the user selection in the result dictionary.

def validate(self):
    self.result = {} # return a dictionary of results

    # >>>>>>insert any user code below this comment for section "dialog_validate"
    # set values in "self.result" dictionary for return

    self.result["named_color"] = self.named_selectionT

Test Dialog

Note that every dialog created by TkGridGUI automatically includes a Testdialog feature that runs when the python file is run stand-alone.

_images/test_dialog.jpg
class _Testdialog:
    def __init__(self, master):
        frame = Frame(master, width=300, height=300)
        frame.pack()
        self.master = master
        self.x, self.y, self.w, self.h = -1,-1,-1,-1

        self.Button_1 = Button(text="Test Dialog", relief="raised", width="15")
        self.Button_1.place(x=84, y=36)
        self.Button_1.bind("<ButtonRelease-1>", self.Button_1_Click)

    def Button_1_Click(self, event): #click method for component ID=1
        dialog = named_color_picker(self.master, "Test Dialog")
        print( '===============Result from Dialog====================' )
        print( dialog.result )
        print( '=====================================================' )

def main():
    root = Tk()
    app = _Testdialog(root)
    root.mainloop()

if __name__ == '__main__':
    main()

WorkFlow

For both Dialogs and Main Applications the workflow consists of:

* Position Widget in TkGridGUI
* Edit Widget Properties in TkGridGUI
* Save to Generated Python File
* In Source Code Editor, Modify User Code
* Run Python File Stand-Alone
* Refactor/Make Corrections
* Repeat Cycle

While this is not a perfect implementation of Test Driven Development , it captures one of the main ideas behind TDD that development relies on the repetition of a very short development cycle.

Each change to the GUI under development can be incremental and can be tested incrementally.

Cross-Platform Font Dialog

The dialog for picking fonts within TkGridGUI was created by TkGridGUI.

The two images below show the dialog with a cross-platform font selected (Times) and with a platform-specific font selected (Chiller).

The objective of the dialog is to present several cross-platform fonts to the user for selection using the Radiobuttons along the upper left, or any of the detectted system fonts in the Listbox along the upper right. Additional attributes of the font can be set with the Checkbutton controls labeled Bold, Italic, Underline and Overstrike. The font size can be selected from the numeric Listbox or set manually in the Entry control just above that Listbox.

Once selected, the Label at the top of the dialog describes the choice (Times 28 bold roman) and (Chiller 48 bold roman) in the examples below.

The label spanning the width of the dialog just above the OK and Cancel buttons show the font as it displayed by a label.configure(font=selected_font) command.

_images/font_dialog_times.jpg _images/font_dialog_chiller.jpg

Click Image to View Fill Size

TkGridGUI Layout

The TkGridGUI layout for this project is shown below. Many of the widgets on the Main tab use rowspan and columnspan to achieve the desired layout (see impage marked in red below).

Rowspan and columnspan are applied by Right-Clicking a widget on the grid after it is placed and entering the desired integer value for the number of rows or columns to be spanned.

_images/font_main_grid_notebook.jpg _images/font_main_grid_notebook_markup.jpg

RadioGroup_1 holds the Cross-Platform Font selections and is designed as shown below.

Note that when the mouse is over a widget on the grid interface (see Radiobutton at (2,0) below) that the same widget is highlighted in the preview window (see the red Helvetica Radiobutton in the preview window below).

The Checkbuttons are placed into LabelFrame_1 for the font Attributes in a very similar manner.

_images/radiogroup_1_grid.jpg _images/radiogroup_1_preview.jpg

User Code

User code is inserted below the # >>>>>>insert any user code comment lines in each of the generated methods.

For example, some initialization was done in the fonts dialog to set the default font to Helvetica size 10.

# >>>>>>insert any user code below this comment for section "top_of_init"

self.RadioGroup_1_StringVar.set("2") # make Helvetica the default
self.current_font_name = 'Helvetica'
self.Entry_2_StringVar.set( '10' )

In the validate method, the dialog returns the user selection in the result dictionary.

The selected font is returned both in string form and in tuple form.

def validate(self):
    self.result = {} # return a dictionary of results

    # >>>>>>insert any user code below this comment for section "dialog_validate"

    t = self.full_font_desc
    self.result["full_font_desc"] = t # return the tuple
    self.result["full_font_str"] = t[0].replace(' ','\ ') + ' %i '%t[1] + ' '.join(t[2:])

    return 1

Test Dialog

Note that every dialog created by TkGridGUI automatically includes a Testdialog feature that runs when the python file is run stand-alone.

_images/test_dialog.jpg

WorkFlow

The workflow for the font dialog is exactly the same as it was for the named color dialog above and consists of:

* Position Widget in TkGridGUI
* Edit Widget Properties in TkGridGUI
* Save to Generated Python File
* In Source Code Editor, Modify User Code
* Run Python File Stand-Alone
* Refactor/Make Corrections
* Repeat Cycle

Authors

Thank you for supporting TkGridGUI.

Development Lead

Patches and Ideas

Your Name Here

Initial Project Layout

TkGridGUI Framework was Created by: PyHatch

(PyHatch Initializes Files And Directory Structures For New Python Projects.)

See PyHatch Docs at: http://pyhatch.readthedocs.org/en/latest/

History

GitHub Log

  • Nov 19, 2018
    • (by: sonofeft)
      • Fixed integer text labels error
  • Nov 14, 2018
    • (by: sonofeft)
      • history update
  • Nov 14, 2018
    • (by: sonofeft)
      • Fixed erroneous wrap option for Canvas with scrollx
  • Nov 01, 2018
    • (by: sonofeft)
      • removed xrange from support file
      • added myshowinfo to improve Help display on Linux
      • Added font dialog example
  • Oct 31, 2018
    • (by: sonofeft)
      • remember duplicated widget with tab change.
      • added exportselection to Listbox source gen, fixed component numbering in New command
      • fixed Scale edit settings, remember path of last open file, save message
  • Oct 30, 2018
    • (by: sonofeft)
      • Updated History.rst
  • Oct 30, 2018
    • (by: sonofeft)
      • added named color to clipboard options, added accelerator keys
      • added examples page to docs
      • history update
  • Oct 30, 2018
    • (by: sonofeft)
      • Replaced tkfontchooser with cross_platform_fonts_Dialog
  • Oct 29, 2018
    • (by: sonofeft)
      • updated quickstart documentation
      • update history and readme
      • added color picker options
  • Oct 27, 2018
    • (by: sonofeft)
      • Added fg+bg color selector
  • Oct 25, 2018
    • (by: sonofeft)
      • history update
  • Oct 25, 2018
    • (by: sonofeft)
      • Fixed some coordination between PreviewWin and GridNotebook
  • Oct 24, 2018
    • (by: sonofeft)
      • removed warning for pre-alpha
      • passed basic Linux and Windows for py 2.7 and 3.x
      • working out multi-platform bugs
      • First Commit to GitHub
    • (by: Charlie Taylor)
      • Initial commit

Mercurial Log

  • Oct 23, 2018
    • (by: sonofeft)
      • added Help and started Docs
      • Some source cleanup
      • Added delete containers
  • Oct 22, 2018
    • (by: sonofeft)
      • added console_script launch, fixed self.MainWin, changed row/col insert
      • added changed file warnings for New, Open and Exit
      • fixed drag and drop, tab switching, error-on-open
  • Oct 19, 2018
    • (by: sonofeft)
      • made newForm more comprehensive.
      • Made menu ctrl keys optional
      • Added helpful line3 to Labels on grid_notebook
  • Oct 18, 2018
    • (by: sonofeft)
      • added accelerator keys to menu and some dialog fixes
      • added get_docstring
  • Oct 17, 2018
    • (by: sonofeft)
      • added button bind to Treeview
      • makes source with all widgets
      • made tab selections in grid_notebook affect Preview and visa-versa
      • fixed read of tabs with widgets
      • added x and xy scrolling
      • fixed moving Tabs on Notebook
  • Oct 16, 2018
    • (by: sonofeft)
      • First semi-working notebook
  • Oct 13, 2018
    • (by: sonofeft)
      • made highlight corrections for edited widget
      • wrapped all preview widgets with PW_Widget to enable scroll bars and future expansions
  • Oct 10, 2018
    • (by: sonofeft)
      • enabled y scrolling for Text, Canvas, Listbox and Treeview
      • changed duplicate widget label to show current selection as well
  • Oct 09, 2018
    • (by: sonofeft)
      • hooked up dialog StrinVar to results
      • added OK and Cancel buttons to dialog PreviewWin
      • got weights working for Main and container widgets
      • Fixed some basic weights functionality
  • Oct 08, 2018
    • (by: sonofeft)
      • added repaint_all_labels with rowspan columnspan logic
      • added rowspan colspan and duplicate widget
  • Oct 07, 2018
    • (by: sonofeft)
      • fixed load error with larger than default grid size
      • removed widget weight attribute
      • added friendly controls to edit widget attr
  • Oct 06, 2018
    • (by: sonofeft)
      • Added label to Canvas PreviewWin
      • made common StringVar for RadioGroups
      • first working rewrite of component source gen
      • started new component source gen logic
  • Oct 05, 2018
    • (by: sonofeft)
      • Menu and statusbar show on launch
      • put menu and statusbar on PreviewWin
      • fixed menu format in *.def file
  • Oct 04, 2018
    • (by: sonofeft)
      • set up Menubutton source generation
      • fixed Spinbox from_ and StringVar
      • corrected all print to py3.x
  • Oct 03, 2018
    • (by: sonofeft)
      • First semi-working source code generation
      • added basic source generation from tk_happy
      • added file read/save
      • lots of active interface updates
  • Oct 02, 2018
    • (by: sonofeft)
      • made editing a double click
      • Added edit dialog
  • Oct 01, 2018
    • (by: sonofeft)
      • got all widgets displaying
      • go PreviewWin working and drop onto container objects
  • Sep 30, 2018
    • (by: sonofeft)
      • made initial stand-alone grid_notebook
      • moved GridWidget out of project
  • Sep 29, 2018
    • (by: sonofeft)
      • added drag and drop
      • Added debug Add All Widgets Button
  • Sep 28, 2018
    • (by: sonofeft)
      • Added Notebook
  • Sep 26, 2018
    • (by: sonofeft)
      • started adding config_file
      • moved widget creation to widget_defs
      • commit just before removing None option
  • Sep 25, 2018
    • (by: sonofeft)
      • added cursor changes to grid controls
      • First commit of rough layout
  • Sep 24, 2018
    • (by: sonofeft)
      • First Created TkGridGUI with PyHatch

PyHatch

TkGridGUI Framework Created by: PyHatch on Sep 24, 2018

(PyHatch Initializes Files And Directory Structures For New Python Projects.)

See PyHatch Docs at: http://pyhatch.readthedocs.org/en/latest/

Indices and tables