Tkinter Guide
Tkinter Guide
Tkinter Basics
• Introduction
• Check the version of Tkinter
• Install Tkinter
• The first application
• The first object-oriented application
• Get information from a window
Designing viewports
• Introduction
• The Geometry Manager Pack
• The Grid geometry manager
• The Place geometry manager
Types of windows
Control variables
• Introduction
• Options menus
• Toolbars
• Status bar
• PyRemoto, an implementation example
With Python there are many possibilities to program a graphical user interface ( GUI ) but Tkinter is easy to use, it
is cross-platform and, in addition, it comes included with Python in its version for Windows, for Mac and for most
GNU/Linux distributions . It is considered the de facto standard in GUI programming with Python.
Tkinter is a binding of the Tcl / Tk library that is also available for other languages such as Perl and Ruby.
Despite its long history, its use is not very widespread among personal computer users because its visual
integration with operating systems was not good and it provided few widgets (controls). for
build the programs graphics.
However, starting with TKinter 8.5 the situation took a 180 degree turn in terms of visual integration, improving
significantly in this aspect; also in the number of widgets that are included and in the possibility of working with
styles and themes, which now allow you to fully customize the aesthetics of a program. Therefore, Tkinter is now
an attractive alternative and as recommended as others.
This tutorial is primarily intended to introduce the developer who is not familiar with GUI programming in Tkinter. To
do this, we will follow a series of examples that show, progressively, the use of the elements that are necessary to
build a graphical application: windows, geometry managers, widgets, menus, event management, fonts, styles and
themes. All at cruising speed. For the impatient.
Normally, the Tkinter package will be available in our Python installation, except in some GNU/Linux distributions.
To check the version of Tkinter installed there are several possibilities:
Install Tkinter
If in our Python installation, on a GNU/Linux computer, the Tkinter package is not found, install with:
(On other platforms, when Python is installed, the Tkinter modules are also included).
The following example creates an application that includes a window with a button at the bottom. When you press
the button the application ends its execution. A window is the fundamental element of a GUI application. It is the
first object that is created and the rest of the objects called widgets (labels, buttons, etc.) are placed on top of it.
etc.).
#!/usr/bin/env python
# -*- coding: utf-8 -*-
root = Tk ()
ttk . Button ( root , text = 'Exit' , command = quit ). pack ( side = BOTTOM )
# If the person presses the Close 'X' button, or # the 'Exit' button, the program will end.
root . mainloop ()
Below is the same application but object-oriented . Although this type of programming is always recommended with
Python, it is not essential. However, if we are going to work with Tkinter, it is
Applications.
From then,
all go to be advantages.
more appropriate, above all, because it facilitates the management of widgets and events that occur in the
Normally, when a graphical application is executed, it waits for a person to interact with it, to press a button, write
something in a text box, select an option from a menu, place the mouse in a certain position, etc., or, an event
occurs in which there is no human intervention, such as a process ending, the value of a variable changing, etc. In
any of these cases, the usual thing will be to link these events or events with some actions to be carried out, which
can be better implemented with the techniques of object-oriented programming.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
To conclude this chapter, an application based on the previous examples is included that serves one purpose,
specifically, to display information related to the window.
To do this, new widgets have been added to the application window: a button labeled "Info" and a box of text
that appears empty.
Also, a method has been included that will be called when the "Info" button is pressed to obtain the information
and insert it in the box of text:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
self . root = Tk ()
self . root . geometry ( '300x200' )
if __name__ == '__main__' :
main ()
In the application, the pack() method is used to place the widgets in a specific position within the window. This
method gives its name to one of the three existing geometry managers in Tkinter, which are responsible for this
task.
Introduction
Geometry managers are used to define the way widgets (controls) should be placed within a window. In Tkinter
there are three geometry managers: pack , grid and place .
If an application has several windows, each of them can be built with any of these managers, interchangeably. It
will be the developer who will have to choose the one that best solves the design they have. by in
front of in each moment.
Also, indicate that to build the windows you can use special widgets (frames, panels, etc.) that act as containers for
other widgets. These widgets are used to group various controls to make operation easier for users. In the
windows that are used, a manager can be used with the window and a different one to organize the controls within
these widgets.
same
using
Next, we are going to know the characteristics of the three geometric managers and develop a
The application consists of a typical system access window that shows the account of the current computer user in
an input box and presents another box to enter their password. At the bottom there are two buttons: one with the
text 'OK' to validate the password (by calling a method) and another with 'Cancel' to end the application.
below,
right
left.
With this manager, the organization of the widgets is done taking into account the sides of a window: top,
If several controls are located (all) on the top side or (all) on the left side of a window, we will construct a vertical
bar or a horizontal bar of controls. Although it is ideal for simple designs (toolbars, dialog boxes, etc.) it can also be
used with complex designs. Additionally, it is possible to make controls adjust to window size changes.
The example shows the commented application with its window built with the pack manager:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from tkinter import *
from tkinter import ttk , font import getpass
self . root = Tk ()
self . root . title ( "Access" )
# Change the formatting of the current font to bold to # highlight the two labels that accompany the
input # boxes. (For this change the # 'font' module has been imported at the beginning of the program):
# Defines the labels that accompany the input # boxes and assigns the above font format:
self . tag1 = ttk . Label ( self . root , text = "User:" , font = font )
self . tag2 = ttk . Label ( self . root , text = "Password:" , font = font )
# Defines two input boxes that will accept # strings of a maximum length of 30 characters.
# To the first of them 'self.ctext1' which will contain
# the name of the user, the variable is assigned
# 'self.user' to the 'textvariable' option. Any
# The value that the variable takes during the execution of the # program will be reflected in the input
box.
# In the second input box, the one with the password, # the same is done. Additionally, the # 'show'
option is set with a "*" (asterisk) to hide # typing of passwords:
self . ctext1 . pack ( side = TOP , fill = X , expand = True , padx = 5 , pady = 5 )
self . tag2 . pack ( side = TOP , fill = BOTH , expand = True , padx = 5 , pady = 5 )
self . ctext2 . pack ( side = TOP , fill = X , expand = True , padx = 5 , pady = 5 )
self . separate1 . pack ( side = TOP , fill = BOTH , expand = True , padx = 5 , pady = 5 )
self . button1 . pack ( side = LEFT , fill = BOTH , expand = True , padx = 5 , pady = 5 )
self . button2 . pack ( side = RIGHT , fill = BOTH , expand = True , padx = 5 , pady = 5 )
# When the program starts, focus # is assigned to the password input box so that # you can start
typing directly:
As we have mentioned before, the application allows you to change the dimension of the window. If we do so, the
widgets will adapt to the new size, taking into account the particular configuration of each one of them. To check
how it works we can drag the edges of the window to enlarge or reduce the size and check how the pack manager
works:
Also, to check how the fill option works we can change the current value X of the self.ctext1.pack widget to Y and
drag the edges of the window. If we drag down the widget it will expand vertically:
This geometric manager treats a window as if it were a grid, made up of rows and columns like a chess board,
where it is possible to place the widgets using a coordinate (row, column); taking into account that, if required, a
widget can occupy several columns and/or several rows.
With this manager it is possible to build complex windows and make the controls adjust to a new size. Its use is
recommended with layouts in which the controls must appear aligned in several columns or rows, that is, following
the shape of a table.
The following example is intended to illustrate how to use the grid manager with a non-resizable window. Also, use
a Frame widget with a 3D effect that will contain the rest of the controls:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
self . frame = ttk . Frame ( self . root , borderwidth = 2 , relief = "raised" , padding =( 10 , 10 ))
# Defines the rest of the widgets but in this case the first one
# parameter indicates that they will be placed in the widget of the
# previous frame 'self.frame'.
self . tag1 = ttk . Label ( self . frame , text = "User:" , font = font , padding =( 5 , 5 ))
self . tag2 = ttk . Label ( self . frame , text = "Password:" , font = font , padding =( 5 , 5 ))
self . frame . grid ( columns = 0 , row = 0 ) self . tag1 . grid ( columns = 0 , row = 0 ) self . ctext1 . grid
( columns = 1 , row = 0 , columnspan = 2 ) self . tag2 . grid ( column = 0 , row = 1 )
self . ctext2 . grid ( columns = 1 , row = 1 , columnspan = 2 )
self . separate1 . grid ( columns = 0 , row = 3 , columnspan = 3 ) self . button1 . grid ( column = 1 , row
=4)
self . button2 . grid ( column = 2 , row = 4 )
if __name__ == '__main__' :
main ()
Next, the application is implemented with a grid with the possibility of adapting the widgets to the window space,
when it changes size:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
self . root . columnconfigure ( 0 , weight = 1 ) self . root . rowconfigure ( 0 , weight = 1 ) self . frame .
columnconfigure ( 0 , weight = 1 ) self . frame . columnconfigure ( 1 , weight = 1 ) self . frame .
columnconfigure ( 2 , weight = 1 ) self . frame . rowconfigure ( 0 , weight = 1 ) self . frame .
rowconfigure ( 1 , weight = 1 ) self . frame . rowconfigure ( 4 , weight = 1 )
if __name__ == '__main__' :
main ()
After running the application, if we expand the size of the window we can check how the controls adjust to the new
available space according to the directions described in each sticky option:
Also, to see how the weights work, we will change the weight that is assigned to row 4 , which is where the '
Accept ' and ' Cancel ' buttons are located, with the value 5 to multiply by 5 the space to be added in this row
when the window expands:
This manager is the easiest to use because it is based on absolute positioning to place the widgets, although the
work of "calculating" the position of each widget is usually quite laborious. We know that a window has a certain
width and height (usually measured in pixels). Well, with this method to place a widget we will simply have to
choose the coordinate (x,y) of its expressed location in pixels.
The position (x=0, y=0) is located in the upper-left corner of the window.
With this manager the size and position of a widget will not change when modifying the dimensions of a window.
Finally, we show the famous application made with the place geometry manager. In this case, the way to display
the validation message is using a label that changes color depending on whether the password is correct or not.
Also, it uses an additional method to "clean up" the error message when the mouse is clicked on the password
input box. The widget event is associated with the method using the bind() method.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# window
In the previous entry we discussed the different geometry managers that are used to design the windows of an
application. Next, we are going to explore the different types of windows that we can create and the uses
that have.
In Tkinter there are two types of windows: application windows , which are usually the ones that start and end
graphical applications; and from which the dialog windows are accessed, which together
constitute th Interfac of user.
e e
Both, from a design point of view, are built exactly the same with the managers.
of geometry alr known: pack , grid and place .
ea
The following example shows an application window with an ' Open ' button that each time it is pressed opens a
different child (dialog) window and in a different position. We will observe that the daughter windows that are
generated are always located on a higher plane with respect to those created previously. Furthermore, if we open
several windows we can interact without problems with all of them, change their positions,
close them, etc
In this case, the pack geometry manager is used to create both the application window and the daughters, but we
will notice some differences in the code:
self.root Tk()
Dialog windows (children) are defined with Toplevel() :
self.dialogue = toplevel()
The wait_window() method causes the dialog window to listen to local events while it waits.
be closed:
self.root.wait_window(self.connect)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
window = 0
posx_y = 0
self . root = Tk ()
# Defines the dimension of the window 300x200 # that will be located at the coordinate x=500,y=50
Application . window += 1
Application . posx_y += 50
tamypos = '200x100+' + str ( Application . posx_y )+ \ '+' + str ( Application . posx_y )
self . dialogue . geometry ( tamypos ) self . dialogue . resizable ( 0 , 0 )
if __name__ == '__main__' :
main ()
The child windows in the previous example are of the non-modal type because while they exist it is possible to
interact freely with them, without any limit, except that if we close the main window all the windows will be closed.
daughters open.
An obvious example that uses non-modal windows is in the most well-known office applications, which allow
working with several documents at the same time, each of them open in its own window, allowing the user to
switch without restrictions from one window to another.
The opposite case is that of modal windows . When a modal window is open, it will not be possible to interact with
other application windows until it is closed.
A typical example is some dialog windows used to set application preferences, which require them to be closed
before others are allowed to open.
To demonstrate this, we use the following example in which it is only possible to keep only one window open
daughter, although the we close we will can open othe
Yeah r.
The grab_set() method is used to create the modal window and the transiet() method is used to convert the dialog
window to a transient window , causing it to be hidden when the application window is minimized.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
Control variables
Control variables are special objects that are associated with widgets to store their values and make them available in
other parts of the program. They can be of numeric, string and boolean type.
When a control variable changes value, the widget that uses it automatically reflects this, and vice versa.
Control variables are also used to connect multiple widgets of the same type, for example, multiple Radiobutton
controls. In this case they will take one of several possible values.
Control variables are declared differently depending on the type of data they store: integer = IntVar () # Declare
variable of type integer float = DoubleVar () # Declare variable of type float string = StringVar () # Declare variable of
type string boolean = BooleanVar () # Declare variable of type boolean
Also, when declaring a variable it is possible to assign an initial value: blog = StringVar ( value = "Python for
impatients" )
set() method
The set() method assigns a value to a control variable. Used to modify the value or state of a widget: name =
StringVar ()
art_id = IntVar ()
name . set ( "Python for the impatient" )
art_id . set ( 1 )
blog = ttk . Entry ( window , textvariable = name , width = 25 ) arti = ttk . Label ( window , textvariable = art_id )
get() method
The get() method obtains the value that a control variable has at a given time. Used when it is necessary to read the
value of a control: print ( 'Blog:' , name . get ())
trace() method
The trace() method is used to "detect" when a variable is read, changes value or is deleted:
widget.trace(type, function)
The first argument sets the type of event to check: ' r ' variable read, ' w ' variable write, and ' u ' variable delete. The
second argument indicates the function that will be called when the event occurs.
In the following example, a control variable of type string is defined and with the trace() method its reading and value
change are associated with two functions that are called when these events occur. Specifically, when the set() method
is used the ' change() ' function will be called and when the get() method is used the ' read() ' function will be called.
variable = StringVar () variable . trace ( "w" , change ) variable . trace ( "r" , read ) variable . set ( "Hello" ) print
( variable . get ()) print ( variable . get ())
When building a window with several widgets, different strategies can be followed to validate the data entered
during the execution of a program:
• One possible option could validate the information and perform the calculations after it is entered, for example,
after a button is pressed.
• Another possibility could be using the trace() method and the ' command ' option, to validate and calculate the
information just at the moment that a widget and its associated variable change value.
The program in this example calculates the cost of a train trip taking into account the number of passengers; the
type of ticket (one-way or round-trip); the class in which you travel (which can be economy, first or luxury class);
the distance in kilometers and the price per kilometer (by default it is 0.10 euro cents).
The calculation of the amount to pay is carried out by multiplying the number of travelers by km and price, with the
following increments:
• If the class is first, the total is multiplied by 1.2 and if it is luxury, it is multiplied by 2.
Validation and subsequent calculation
In the first solution, the validation of the data and the calculation of the amount to pay is carried out after pressing
h butto "Calculate"
e n .
#!/usr/bin/env python
# -*- coding: utf-8 -*-
self . image1 = ttk . Label ( self . root , image = train , anchor = "center" )
self . tag1 = ttk . Label ( self . root , text = "Travelers:" )
self . trip = Spinbox ( self . root , from_ = 1 , to = 20 , wrap = True , textvariable = self . num_via , state =
'readonly' )
self . idavue = ttk . Checkbutton ( self . root , text = 'Round Trip' , variable = self . ida_vue , onvalue = True
, offvalue = False )
self . tag2 = ttk . Label ( self . root , text = "Class:" )
self . class1 = ttk . Radiobutton ( self . root , text = 'Tourist' ,
variable = self . class , value = 't' )
self . class2 = ttk . Radiobutton ( self . root , text = 'First' ,
variable = self . class , value = 'p' )
self . class3 = ttk . Radiobutton ( self . root , text = 'Luxury' ,
variable = self . class , value = 'l' )
self . tag3 = ttk . Label ( self . root , text = "Distance Kilometers):" )
self . dist = ttk . Entry ( self . root , textvariable = self . km , width = 10 )
self . tag4 = ttk . Label ( self . root , text = "Price:" )
self . cost = ttk . Entry ( self . root , textvariable = self . price , width = 10 )
self . tag5 = ttk . Label ( self . root , text = "To Pay (euros):" )
self . tag6 = ttk . Label ( self . root , textvariable = self . total , foreground = "yellow" , background = "black"
, borderwidth = 5 , anchor = "e" )
self . separate1 = ttk . Separator ( self . root , orient = HORIZONTAL )
self . button1 = ttk . Button ( self . root , text = "Calculate" , command = self . calculate )
self . button2 = ttk . Button ( self . root , text = "Exit" , command = quit )
self . image 1 . pack ( side = TOP , fill = BOTH , expand = True , padx = 10 , pady = 5 )
self . tag1 . pack ( side = TOP , fill = BOTH , expand = True , padx = 10 , pady = 5 )
self . journey . pack ( side = TOP , fill = X , expand = True , padx = 20 , pady = 5 )
self . idavue . pack ( side = TOP , fill = X , expand = True , padx = 20 , pady = 5 )
self . tag2 . pack ( side = TOP , fill = BOTH , expand = True , padx = 10 , pady = 5 )
self . class1 . pack ( side = TOP , fill = BOTH , expand = True , padx = 20 , pady = 5 )
self . class2 . pack ( side = TOP , fill = BOTH , expand = True , padx = 20 , pady = 5 )
self . class3 . pack ( side = TOP , fill = BOTH , expand = True , padx = 20 , pady = 5 )
self . tag3 . pack ( side = TOP , fill = BOTH , expand = True , padx = 10 , pady = 5 )
self . dist . pack ( side = TOP , fill = X , expand = True , padx = 20 , pady = 5 )
self . tag4 . pack ( side = TOP , fill = BOTH , expand = True , padx = 10 , pady = 5 )
self . cost . pack ( side = TOP , fill = X , expand = True , padx = 20 , pady = 5 )
self . tag5 . pack ( side = TOP , fill = BOTH , expand = True , padx = 10 , pady = 5 )
self . tag6 . pack ( side = TOP , fill = BOTH , expand = True , padx = 20 , pady = 5 )
self . separate1 . pack ( side = TOP , fill = BOTH , expand = True , padx = 5 , pady = 5 )
self . button1 . pack ( side = LEFT , fill = BOTH , expand = True , padx = 10 , pady = 10 )
self . button2 . pack ( side = RIGHT , fill = BOTH , expand = True , padx = 10 , pady = 10 )
self . root . mainloop ()
data_error = False
total = 0
try :
km = int ( self . km . get ())
price = float ( self . price . get ())
except :
data_error = True
if not data_error :
total = self . via_num . get () * km * price
if self . ida_vue . get ():
total = total * 1.5
if self . class . get () == 'p' :
total = total * 1.2
elif self . class . get () == 'l' :
total = total * 2
self . total . set ( total )
else :
self . total . set ( "ERROR!" )
if __name__ == '__main__' :
main ()
In the second solution the ' Calculate ' button is not used. Validation and calculation are performed by changing the
value of any widget, displaying the result immediately. For the data entry widgets ( Entry() ) two traces are defined to
detect any change in the data and in the rest of the widgets the option is used ' command '.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
self . via_num = IntVar ( value = 1 ) self . ida_vue = BooleanVar () self . class = StringVar ( value = 't' ) self
. km = IntVar ( value = 1 )
self . price = DoubleVar ( value = 0.10 )
self . total = DoubleVar ( value = 0.0 ) # Define traces with control variables from Entry() widgets
self . calculate ()
self . image1 = ttk . Label ( self . root , image = train , anchor = "center" )
self . tag1 = ttk . Label ( self . root , text = "Travelers:" )
self . trip = Spinbox ( self . root , from_ = 1 , to = 20 , wrap = True , textvariable = self . num_via , state =
'readonly' , command = self . calculate )
self . idavue = ttk . Checkbutton ( self . root , text = 'Round Trip' , variable = self . ida_vue , onvalue = True
, offvalue = False , command = self . calculate )
self . tag2 = ttk . Label ( self . root , text = "Class:" )
self . class1 = ttk . Radiobutton ( self . root , text = 'Tourist' , variable = self . class , value = 't' , command =
self . calculate )
self . class2 = ttk . Radiobutton ( self . root , text = 'First' , variable = self . class , value = 'p' , command =
self . calculate )
self . class3 = ttk . Radiobutton ( self . root , text = 'Luxury' , variable = self . class , value = 'l' , command =
self . calculate )
self . tag3 = ttk . Label ( self . root ,
self . button1 = ttk . Button ( self . root , text = "Exit" , command = quit )
self . image 1 . pack ( side = TOP , fill = BOTH , expand = True , padx = 10 , pady = 5 )
self . tag1 . pack ( side = TOP , fill = BOTH , expand = True ,
padx = 10 , pady = 5 )
self . journey . pack ( side = TOP , fill = X , expand = True ,
padx = 20 , pady = 5 )
self . idavue . pack ( side = TOP , fill = X , expand = True , padx = 20 , pady = 5 )
self . tag2 . pack ( side = TOP , fill = BOTH , expand = True ,
padx = 10 , pady = 5 )
self . class1 . pack ( side = TOP , fill = BOTH , expand = True ,
padx = 20 , pady = 5 )
self . class2 . pack ( side = TOP , fill = BOTH , expand = True ,
padx = 20 , pady = 5 )
self . class3 . pack ( side = TOP , fill = BOTH , expand = True ,
padx = 20 , pady = 5 )
self . tag3 . pack ( side = TOP , fill = BOTH , expand = True ,
padx = 10 , pady = 5 )
self . dist . pack ( side = TOP , fill = X , expand = True , padx = 20 , pady = 5 )
self . tag4 . pack ( side = TOP , fill = BOTH , expand = True ,
padx = 10 , pady = 5 )
self . cost . pack ( side = TOP , fill = X , expand = True ,
padx = 20 , pady = 5 )
self . tag5 . pack ( side = TOP , fill = BOTH , expand = True ,
padx = 10 , pady = 5 )
self . tag6 . pack ( side = TOP , fill = BOTH , expand = True , padx = 20 , pady = 5 )
self . separate1 . pack ( side = TOP , fill = BOTH , expand = True , padx = 5 , pady = 5 )
self . button1 . pack ( side = RIGHT , fill = BOTH , expand = True , padx = 10 , pady = 10 )
self . root . mainloop ()
data_error = False
total = 0
try :
if __name__ == '__main__' :
main ()
Introduction
Tkinter has specific widgets to include option menus of different types in an application. In addition, following some
guidelines in the construction of windows it is possible to add other elements such as bars of tools
and of state .
All of these components are frequently used in interface development because they make it much easier for users to
interact with graphical applications.
Options menus
Menus can be built by grouping several drop-down submenus in a menu bar, using button-based menus, or using
typical contextual menus that change their available options depending on where they are activated in the application
window.
Among the types of options that can be included in a menu are those whose status represents a logical value of
activated or deactivated ( add_checkbutton ); those that allow you to choose an option from among several existing
ones ( add_radiobutton ) and those that directly execute a method or function ( add_command ).
Menu options can include icons and be associated with shortcuts or key combinations that have the same effect as if
they were selected with a mouse click. Also, at a given time, they can be disabled to prevent them from being
selected.
Toolbars
A Tkinter application, in addition to option menus, can incorporate toolbars built from buttons stacked horizontally or
vertically. These toolbars are often located just below the application menu bar and execute the most used processes
in the system.
Status bar
Status bars are frequently used in graphics programs to display information that is useful to users. Normally, they
occupy the last line of the application window and in some cases they can be hidden to leave more space available for
said window.
Application window
PyRemoto is an example that aims to show how to include menus and bars in a Tkinter-based application.
The main window of this application has a title bar, a menu bar with three drop-down submenus with different types of
options, a context menu that is activated by clicking with the right mouse button anywhere in the window, a of tools
with two buttons with images and a status bar that can be hidden or shown using the " View status bar " option of the
" Options " submenu.
Contextual menu
Submenu "Options"
In the " Options " submenu there is the " Save " option that will be enabled when an option is chosen from among
those available in this submenu; and will be disabled when the " Save " option itself is used, - intended - to save the
preferences selected by the user.
The example application uses images of different sizes that are located in a folder called " image ". These images are
used in the title bar, submenus, toolbar, and in the " About " dialog window of the " Help " submenu. They have been
obtained from the site flaticon.com , which offers collections of images organized by different themes to programmers
and graphic designers.
Also, the program includes several key combinations associated with different menu options,
declared with h bind() method.
e
As works?
The application is started by the main() function which checks that all images in the application exist in the " image "
folder. If all the images are available, the application object will be created using the PyRemoto() class. This class has
a __init__() method that builds the application window, menus, toolbar, and a status bar.
The application is incomplete but it teaches how to organize the methods that are called from the different options
of the menus and bars.
Finally, the example includes the " About " dialog window, which is of a modal type, to show how to open this type of
window from a menu option.
#!/usr/bin/env python
# INITIALIZE VARIABLES
self . root = Tk ()
# SET APPLICATION WINDOW PROPERTIES: self . root . title ( "PyRemoto " + __version__ ) # Title
self . icon1 = PhotoImage ( file = self . icons [ 0 ]) # App icon self . root . iconphoto ( self . root , self . icon1
) # Assign app icon self . root . option_add ( "*Font" , "Helvetica 12" ) # Default Font self . root . option_add
( '*tearOff' , False ) # Disable floating submenus self . root . attributes ( '-fullscreen' , True ) # Maximize full
window self . root . minsize ( 400 , 300 ) # Set minimum window size
# DECLARE VARIABLES FOR DEFAULT OPTIONS: # (These values could be read from a file
# setting)
self . menu2 . add_checkbutton ( label = 'StatusBar' , variable = self . status , onvalue = 1 , offvalue = 0 ,
command = self . f_verstatus )
self . menu2 . add_separator ()
self . menu2 . add_radiobutton ( label = 'ssh' , variable = self . CFG_CONEXTYPE , command = self .
f_changepc , value = 1 )
self . menu2 . add_radiobutton ( label = 'sftp' , variable = self . CFG_CONEXTYPE , command = self .
f_changepc , value = 2 )
self . menu2 . add_radiobutton ( label = 'rdp' , variable = self . CFG_CONEXTYPE , command = self .
f_changepc , value = 3 )
self . menu2 . add_separator ()
self . menu2 . add_radiobutton ( label = 'xterm' , variable = self . CFG_TIPOEMUT , command = self .
f_changepc , value = 1 )
self . menu2 . add_radiobutton ( label = 'uxterm' , variable = self . CFG_TIPOEMUT , command = self .
f_changeropc , value = 2 )
self . menu2 . add_radiobutton ( label = 'xfce4-terminal' , variable = self . CFG_TIPOEMUT ,
command = self . f_changepc , value = 3 )
self . menu2 . add_separator ()
self . menu2 . add_radiobutton ( label = 'Thunar' ,
variable = self . CFG_TYPEEXP , command = self . f_changepc , value = 1 )
self . menu2 . add_radiobutton ( label = 'Nautilus' , variable = self . CFG_EXPTYPE , command = self .
f_changeropc , value = 2 )
self . menu2 . add_separator ()
self . menu2 . add_command ( label = 'Save' ,
command = self . f_saveoption , state = "disabled" , underline = 0 ,
accelerator = "Ctrl+g" )
menu3 . add_command ( label = 'Web' , command = self . f_web ) menu3 . add_command ( label =
'Keyboard shortcuts' , command = self . f_shortcuts )
icon4 = PhotoImage ( file = self . icons [ 3 ]) menu3 . add_command ( label = "About" , command = self
. f_about , image = icon4 , compound = LEFT )
# DEFINE TOOLBAR:
self . icon5 = PhotoImage ( file = self . icons [ 4 ]) icon6 = PhotoImage ( file = self . icons [ 5 ])
# info1 = os.uname().sysname
# info2 = os.uname().nodename
# info3 = os.uname().machine
message = " " + info1 + ": " + info2 + " - " + info3
self . barest = Label ( self . root , text = message ,
# DECLARATE HOTKEYS:
if self . menu2 . entrycget ( 13 , "state" ) == "normal" : self . menu2 . entryconfig ( 13 , state = "disabled"
) self . f_saveconfig ()
about = Toplevel ()
about . geometry ( "320x200" )
about . resizable ( width = False , height = False ) about . title ( "About" )
frame1 = ttk . Frame ( about , padding =( 10 , 10 , 10 , 10 ), relief = RAISED )
frame1 . pack ( side = TOP , fill = BOTH , expand = True ) tag1 = Label ( frame1 , image = self . icon5 ,
relief = 'raised' )
tag1 . pack ( side = TOP , padx = 10 , pady = 10 , ipadx = 10 , ipady = 10 )
label2 = Label ( frame1 , text = "PyRemoto " + __version__ , foreground = 'blue' , font = self . font )
tag2 . pack ( side = TOP , padx = 10 )
tag3 = Label ( marco1 , text = "Python for the impatient" )
tag3 . pack ( side = TOP , padx = 10 )
button1 = Button ( frame1 , text = "Exit" , command = about . destroy )
button1 . pack ( side = TOP , padx = 10 , pady = 10 )
button1 . focus_set ()
about . transient ( self . root )
self . root . wait_window ( about )
# APP FEATURES
app_folder = os . getcwd ()
img_folder = app_folder + os . sep + "image" + os . sep
if not error1 :
my_app = PyRemote ( img_folder , icons )
return ( 0 )
if __name__ == '__main__' :
main ()