Applications¶
In this section we are showing some practical applications.
Calculator¶
The first example is a pocket calculator.
First, we just do the layout for the buttons:
App.lb = Label('0.0')
App.lb.grid(columnspan=4)
Button('AC', ).grid(row=1)
Button('±').grid(row=1, column=1)
Button('%').grid(row=1, column=2)
Button(':').grid(row=1, column=3)
"""Create calculator buttons."""
from tklib import *
class Demo(App):
def __init__(self):
super().__init__()
App.lb = Label('0.0')
App.lb.grid(columnspan=4)
Button('AC', ).grid(row=1)
Button('±').grid(row=1, column=1)
Button('%').grid(row=1, column=2)
Button(':').grid(row=1, column=3)
Button('7').grid(row=2, column=0)
Button('8').grid(row=2, column=1)
Button('9').grid(row=2, column=2)
Button('x').grid(row=2, column=3)
Button('4').grid(row=3, column=0)
Button('5').grid(row=3, column=1)
Button('6').grid(row=3, column=2)
Button('-').grid(row=3, column=3)
Button('1').grid(row=4, column=0)
Button('2').grid(row=4, column=1)
Button('3').grid(row=4, column=2)
Button('+').grid(row=4, column=3)
Button('0').grid(row=5, columnspan=2, sticky='we')
Button('.').grid(row=5, column=2)
Button('=').grid(row=5, column=3)
if __name__ == '__main__':
Demo().run()
Then we are going to add callback functions to the keys:
Button('7', 'App.lb["text"] = float(App.lb["text"])*10 + 7').grid(row=2, column=0)
Button('8', 'App.lb["text"] = float(App.lb["text"])*10 + 8').grid(row=2, column=1)
Button('9', 'App.lb["text"] = float(App.lb["text"])*10 + 9').grid(row=2, column=2)
Button('x').grid(row=2, column=3)
"""Create calculator buttons."""
from tklib import *
class Demo(App):
def __init__(self):
super().__init__()
s = ttk.Style()
s.configure('TButton', font='Arial 18', padding=5)
App.lb = Label('0', font='Arial 36')
App.lb.grid(columnspan=4, sticky='e')
Button('C', 'App.lb["text"] = 0.0').grid(row=1)
Button('±').grid(row=1, column=1)
Button('%').grid(row=1, column=2)
Button(':').grid(row=1, column=3)
Button('7', 'App.lb["text"] = float(App.lb["text"])*10 + 7').grid(row=2, column=0)
Button('8', 'App.lb["text"] = float(App.lb["text"])*10 + 8').grid(row=2, column=1)
Button('9', 'App.lb["text"] = float(App.lb["text"])*10 + 9').grid(row=2, column=2)
Button('x').grid(row=2, column=3)
Button('4', 'App.lb["text"] = float(App.lb["text"])*10 + 4').grid(row=3, column=0)
Button('5', 'App.lb["text"] = float(App.lb["text"])*10 + 5').grid(row=3, column=1)
Button('6', 'App.lb["text"] = float(App.lb["text"])*10 + 6').grid(row=3, column=2)
Button('-').grid(row=3, column=3)
Button('1', 'App.lb["text"] = float(App.lb["text"])*10 + 1').grid(row=4, column=0)
Button('2', 'App.lb["text"] = float(App.lb["text"])*10 + 2').grid(row=4, column=1)
Button('3', 'App.lb["text"] = float(App.lb["text"])*10 + 3').grid(row=4, column=2)
Button('+').grid(row=4, column=3)
Button('0', 'App.lb["text"] = float(App.lb["text"])*10 + 0').grid(row=5, columnspan=2, sticky='we')
Button('.').grid(row=5, column=2)
Button('=').grid(row=5, column=3)
if __name__ == '__main__':
Demo().run()
It turns out that it is simpler to place the calculator logic into a separate function, based on a single character:
def calculate(self, c):
"""Calculator for 4 basic operations."""
if c in '0123456789.±+-/*%c=':
if c in '0123456789':
if self.pos:
self.val += int(c) * 10**self.pos
self.pos -= 1
else:
self.val *= 10
self.val += int(c)
if c == '.':
self.pos = -1
if c == '%':
self.val *= 0.01
elif c in '+-/*':
self.val2 = self.val
self.val = 0
self.pos = 0
self.op = c
elif c == '=':
e = str(self.val2) + self.op + str(self.val)
self.val = eval(e)
if c == 'c':
self.val = 0
self.pos = 0
self.lb['text'] = self.val
"""Create calculator buttons."""
from tklib import *
class Demo(App):
def __init__(self):
super().__init__()
s = ttk.Style()
s.configure('TButton', font='Arial 18', padding=5)
self.lb = Label('0', font='Arial 36', width=15, anchor='e')
self.val = 0
self.pos = 0
self.val2 = 0
App.root.bind('<Key>', self.cb)
def cb(self, event=None):
"""React to key press events."""
c = event.char
if c != '':
self.calculate(c)
def calculate(self, c):
"""Calculator for 4 basic operations."""
if c in '0123456789.±+-/*%c=':
if c in '0123456789':
if self.pos:
self.val += int(c) * 10**self.pos
self.pos -= 1
else:
self.val *= 10
self.val += int(c)
if c == '.':
self.pos = -1
if c == '%':
self.val *= 0.01
elif c in '+-/*':
self.val2 = self.val
self.val = 0
self.pos = 0
self.op = c
elif c == '=':
e = str(self.val2) + self.op + str(self.val)
self.val = eval(e)
if c == 'c':
self.val = 0
self.pos = 0
self.lb['text'] = self.val
if __name__ == '__main__':
Demo().run()
And finally we put everything together. New Calculator instances can be created via a button press or via a menu.
"""Create calculator buttons."""
from tklib import *
class Calculator():
def __init__(self):
self.win = Window('Calculator')
s = ttk.Style()
s.configure('TButton', font='Arial 18', padding=5)
self.lb = Label('0', font='Arial 44', width=15, anchor='e')
self.lb.grid(columnspan=4)
buttons = 'c±%/789*456-123+ 0.='
for i, b in enumerate(buttons):
Button(b, lambda c=b: self.calculate(c)).grid(row=i//4+1, column=i%4)
self.val = 0
self.pos = 0
self.val2 = 0
self.op = ''
self.win.top.bind('<Key>', self.cb)
def cb(self, event=None):
"""React to key press events."""
c = event.char
if c != '':
self.calculate(c)
def calculate(self, c):
"""Calculator for 4 basic operations."""
if c in '0123456789.±+-/*%c=':
if c in '0123456789':
if self.pos:
self.val += int(c) * 10**self.pos
self.pos -= 1
else:
self.val *= 10
self.val += int(c)
elif c == '.':
self.pos = -1
elif c == '%':
self.val *= 0.01
elif c == '±':
self.val *= -1
elif c in '+-/*':
self.val2 = self.val
self.val = 0
self.pos = 0
self.op = c
elif c == '=':
e = str(self.val2) + self.op + str(self.val)
self.val = eval(e)
if c == 'c':
self.val = 0
self.pos = 0
self.lb['text'] = self.val
class Demo(App):
def __init__(self):
super().__init__()
Button('New calculator', Calculator)
Menu('App')
Item('Calculator', Calculator)
if __name__ == '__main__':
Demo().run()