In this article, we are going to learn about data and classes in python Tkinter. We will save our GUIdata into Tkinter variables after that we will also start using OOP to extend the existing Tkinter classes to extend the built-in functionality of Tkinter. We will discuss mainly on data and classes in python Tkinter. This will lead us into creating reusable OOP components.
Some widgets (like text entry widgets, radio buttons and so on) can be connected directly to application variables by using special options: variable, textvariable, onvalue, offvalue, and value. This connection works both ways: if the variable changes for any reason, the widget it’s connected to will be updated to reflect the new value. These Tkinter control variables are used like regular Python variables to keep certain values. It’s not possible to hand over a regular Python variable to a widget through a variable or textvariable option.
We will discuss data and classes in python Tkinter. The below contents are of this article:
CONTENTS
- StringVAR()
- Data from a widget
- Module-level global variables
- Classes in GUI
- Callback functions
- Reusable GUI components
1.STRINGVAR()
As we are going to discuss data and classes in python Tkinter. We are going to start with the data. There are built-in programming types in Tkinter that differ slightly from the Python. Likewise, StringVar() is one such Tkinter type. Here is how we save data from the Tkinter GUI into variables so we can use that data.
Here are some of the available types of coding in Tkinter:
strVar = StringVar() | # Holds a string; the default value is an empty string “” |
intVar = IntVar() | # Holds an integer; the default value is 0 |
dbVar = DoubleVar() | # Holds a float; the default value is 0.0 |
blVar = BooleanVar() | # Holds a Boolean, it returns 0 for False and 1 for True |
Different languages call numbers with decimal points as floats or doubles. Tkinter calls them DoubleVar, which is known in Python as float datatype. Depending on the level of precision, float and double data can be different. Here, we are translating Tkinter DoubleVar into what Python turns into a Python float type.Here is an example which explains it.
import tkinter as tk
#create a instance of tkinter
win=tk.Tk()
#create Double var
doubleData=tk.DoubleVar()
print(doubleData.get())
doubleData.set(2.4)
print(type(doubleData))
add_doubles=1.22222222222222222222222
print(add_doubles)
print(type(add_doubles))
OUTPUT:
As we can see the default value for double var is 0.0 and it is printed. After adding with 1.2222 the Tkinter DoubleVar into what Python turns into a Python float type.
PRINTING THE VALUE USING STRINGVAR
import tkinter as tk #create a instance of tkinter win=tk.Tk() strData=tk.StringVar() strData.set("hello stringvar") #get value of strdata variable varData=strData.get() #print out current value of str data print(varData)
OUTPUT:
We are observing the string as the output
DEFAULT VALUES OF TKINTER INTVAR,DOUBLEVAR AND BOOLEANVAR
Print the default values of tkinter IntVar, DoubleVar, and BooleanVar types is as shown below.
We create an instance of the Tkinter StringVar type and assign it to our Python strData variable. After that, we use our variable to call the set() method on StringVar and after setting to a value, we get the value, save it in a new variable named varData, and then print out its value.
import tkinter as tk #create a instance of tkinter win=tk.Tk() strData=tk.StringVar() strData.set("hello stringvar") #get value of strdata variable varData=strData.get() #print out current value of str data print(varData) print(tk.IntVar()) print(tk.DoubleVar()) print(tk.BooleanVar())
OUTPUT
In the preceding screenshot, on the other hand the default values do not get printed, as we would have expected. The online literature mentions default values but we would not see those values until we call the get method on them. Otherwise, we just get a variable name that automatically increments (for example, PY_VAR3, as can be seen in the preceding screenshot).
we use the get method to display the default value
The value is PY_VAR0, not the expected 0 until we call the get method. Now we can see the default value. We did not call set, so we see the default value automatically assigned to each Tkinter type once we call the get method on each type: To know more you can refer to this.
import tkinter as tk #create a instance of tkinter win=tk.Tk() intData=tk.IntVar() print(intData) print(intData.get())
OUTPUT
Similarly,we can do it for other data types as well.
2.DATA FROM A WIDGET
Most importantly, When the user enters the data, we want to do something with it in our code. In this section we show how to capture data in a variable. In the previous section, we created several Tkinter class variables. They were standalone.
Now, we are connecting them to our GUI, using the data we get from the GUI and storing it in Python variables.We will be assigning a value from our GUI to a Python variable as given in the following example.
from tkinter import *
def click_me():
print(spin1.get())
root = Tk()
spin1 = Spinbox(root, from_=1, to=5)
spin1.pack()
button =Button(root, text="prnt", command=click_me)
button.pack()
root.geometry("300x300")
root.mainloop()
OUTPUT
In order to get the values out of our GUI written using Tkinter, we use the Tkinter get() method on an instance of the widget we wish to get the value from. In the preceding example, we used the Spinbox control, but the principle is the same for all widgets that have a get() method.
Once we have got the data, we are in a pure Python world, and Tkinter did serve us well in building our GUI. Therefore, we know how to get the data out of our GUI, we can use this data.
3.MODULE-LEVEL GLOBAL VARIABLES
Encapsulation is a major strength in any programming language, enabling us to program using OOP. Python is both OOP as well as procedural. We can create global variables that are localized to the module they reside in. They are global only to this module, which is one form of encapsulation. Because as we add more and more functionality to our GUI, we want to avoid naming conflicts that could result in bugs in our code.
import tkinter as tk
from tkinter import ttk
GLOBAL_CONST=42
print(GLOBAL_CONST)
OUTPUT
As a result, we can 42 is being printed to the console. We define a global variable at the top of our module, and we print out its value later, towards the bottom of our module.
In the preceding code snippet, we use the module-level global. It is easy to make a mistake by shadowing global, as demonstrated in the following:
import tkinter as tk from tkinter import ttk GLOBAL_CONST=42 def usingGlobal(): print(GLOBAL_CONST) usingGlobal()
This method also works and prints the output as 42 but In the preceding code snippet, we use the module-level global. It is easy to make a mistake by shadowing global, as demonstrated in the following:
import tkinter as tk
from tkinter import ttk
GLOBAL_CONST=42
def usingGlobal():
GLOBAL_CONST=777
print(GLOBAL_CONST)
usingGlobal()
OUTPUT
Therefore, Note how 42 becomes 777, even though we are using the same variable name.
There is no compiler in Python that warns us if we overwrite global variables in a local function. so consequently,This can lead to difficulties in debugging at runtime .When we qualify our local variable with the global keyword, we can print out the value of the global variable as well as overwrite this value locally:this is shown below.
import tkinter as tk
from tkinter import ttk
GLOBAL_CONST=42
def usingGlobal():
global GLOBAL_CONST
print(GLOBAL_CONST)
GLOBAL_CONST=777
print(GLOBAL_CONST)
usingGlobal()
OUTPUT
To sum up it is best to avoid global and accidentally shadowing variables by using the same name in different scopes. We can use OOP instead of using global variables. We played around with the global variables within procedural code and learned how it can lead to hard-to-debug bugs. In addition to the next recipe, we will move on to OOP, which can eliminate such bugs.
4.CLASSES IN GUI
So far, we have been coding in a procedural style. This is a quick scripting method from Python.We will turn our entire procedural code into OOP very simply. We just turn it into a class, indent all the existing code, and prepend self to all variables. We are involving both data and classes in python Tkinter.
ADVANTAGES OF CLASSES
Once our code gets larger and larger, we need to advance to coding in OOP because, among many other benefits, OOP allows us to move code around by using methods. Once we use classes, we no longer have to physically place code above the code that calls it. This gives us great flexibility in organizing our code.
HOW TO IMPLEMENT
Prepend all the variables with the self keyword and also bind the functions to the class by using self, which officially and technically turns the functions into methods. There is a difference between functions and methods. Python makes this very clear. .Here is examples classes in GUI.
from tkinter import *
class GUI(Tk):
def __init__(self):
super().__init__()
self.geometry("744x377")
def status(self):
self.var = StringVar()
self.var.set("Ready")
self.statusbar = Label(self, textvar=self.var, relief=SUNKEN, anchor="w")
self.statusbar.pack(side=BOTTOM, fill=X)
def click(self):
print("Button clicked")
def createbutton(self, inptext):
Button(text=inptext, command=self.click).pack()
if __name__ == '__main__':
window = GUI()
window.status()
window.createbutton("Click me")
window.mainloop()
OUTPUT
As a result, We have advanced our procedural code into OOP code. Most importantly, python enables us to write code in both a practical and a procedural style such as the C-programming language. Simultaneously, we have the option to code in an OOP style, such as Java, C#, and C++.
5.WRITING CALLBACK FUNCTIONS
What happens after clicking the button depends on whether we created an event handler and associated it with this button. If we did not create an event handler, clicking the button will not affect it. The event handler is a callback function (or method, if we use classes).
CALLBACK FUNCTION WORK
The callback method is also sitting there passively, like our GUI, waiting to be invoked. Once our GUI gets its button clicked, it will invoke the callback. The callback often does some processing and, when done, it returns the result to our GUI. In a sense, we can see that our callback function is calling our GUI back.Here are few examples.
from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
class Root(Tk):
def __init__(self):
super(Root, self).__init__()
self.title("Python Tkinter Spin Box")
self.minsize(640, 400)
#self.wm_iconbitmap('icon.ico')
self.spinBox()
def spinCallBack(self):
value = self.spin.get()
print(value)
self.scrollText.insert(INSERT, value)
def spinBox(self):
self.spin = ttk.Spinbox(self, from_=0, to=10, command=self.spinCallBack)
self.spin.grid(column=0, row=2)
scroll_w = 30
scroll_h = 10
self.scrollText = scrolledtext.ScrolledText(self, width=scroll_w, height=scroll_h, wrap=WORD)
self.scrollText.grid(column=1, row=2)
root = Root(
OUTPUT
So consequently, We created a callback method in the Root class which gets called when we select a value from the Spinbox widget because we bound the method to the widget via the command argument (command=self.spinCallback). This is a simple example of call back function using classes.
rom tkinter import *
class GUI(Tk):
def __init__(self):
super().__init__()
self.geometry("744x377")
def status(self):
self.var = StringVar()
self.var.set("Ready")
self.statusbar = Label(self, textvar=self.var, relief=SUNKEN, anchor="w")
self.statusbar.pack(side=BOTTOM, fill=X)
def click(self):
print("Button clicked")
def createbutton(self, inptext):
Button(text=inptext, command=self.click).pack()
if __name__ == '__main__':
window = GUI()
window.status()
window.createbutton("Click me")
window.mainloop()
OUTPUT
Therefore,When we click the button self.click function is involved and button clicked is printed.
6.CREATING REUSABLE GUI COMPONENTS
So, we will create reusable GUI components using Python. In this recipe, we will keep it simple by moving our ToolTip class into its module. Then, we will import and use it for displaying tooltips over several widgets of our GUI.
Here we are starting by breaking out our ToolTip class into a separate Python module. We will slightly enhance it to pass in the control widget and the tooltip text that we wish to display when we hover the mouse over the control.
Consider the following code:
''' tk_ToolTip_class101.py
gives a Tkinter widget a tooltip as the mouse is above the widget
tested with Python27 and Python34 by vegaseat 09sep2014
'''
try:
# for Python2
import Tkinter as tk
except ImportError:
# for Python3
import tkinter as tk
class CreateToolTip(object):
'''
create a tooltip for a given widget
'''
def __init__(self, widget, text='widget info'):
self.widget = widget
self.text = text
self.widget.bind("<Enter>", self.enter)
self.widget.bind("<Leave>", self.close)
def enter(self, event=None):
x = y = 0
x, y, cx, cy = self.widget.bbox("insert")
x += self.widget.winfo_rootx() + 25
y += self.widget.winfo_rooty() + 20
# creates a toplevel window
self.tw = tk.Toplevel(self.widget)
# Leaves only the label and removes the app window
self.tw.wm_overrideredirect(True)
self.tw.wm_geometry("+%d+%d" % (x, y))
label = tk.Label(self.tw, text=self.text, justify='left',
background='yellow', relief='solid', borderwidth=1,
font=("times", "8", "normal"))
label.pack(ipadx=1)
def close(self, event=None):
if self.tw:
self.tw.destroy()
# testing ...
if __name__ == '__main__':
root = tk.Tk()
btn1 = tk.Button(root, text="button 1")
btn1.pack(padx=10, pady=5)
button1_ttp = CreateToolTip(btn1, "mouse is over button 1")
btn2 = tk.Button(root, text="button 2")
btn2.pack(padx=10, pady=5)
button2_ttp = CreateToolTip(btn2, "mouse is over button 2")
root.mainloop()
We, have created a new Python module and place the ToolTip class code into it and then import this module into our primary module. We then reuse the imported ToolTip class by creating several tooltips, which can be seen when hovering the mouse over several of our GUI widgets.
OUTPUT
As a result, we can see several tooltip messages being displayed.
After reading this tutorial on “Data and classes in python Tkinter”, I hope you understood about data and classes in python Tkinter and I am pretty sure you want to know more about python. To know more about python you can refer to the following blogs.
1.https://iot4beginners.com/introduction-to-python/
2.https://iot4beginners.com/object-oriented-programming-in-python/
3.https://iot4beginners.com/layout-management-using-tkinter-python/
4.https://iot4beginners.com/plotting-graphs-with-matplotlib-python/