Content description:
In the current post I am adding search box methods (for focus-in, focus-out and to handle text entered into the search box).
I define methods that display windows for creating a new car and for displaying repairs.
The methods for handling the search field are: on_entry_in(), on_entry_out() and on_entry_return().
The on_entry_in() method removes the text in the search box and turns it black.
def on_entry_in(self, event):
self.search_entry.config(fg='black')
self.search_variable.set('')
The on_entry_out() method shows the 'Search car by VRN' text greyed out in the search box.
def on_entry_out(self, event):
self.search_entry.config(fg='grey')
self.search_variable.set('Search car by VRN')
In the on_entry_return() method, I check whether something has been entered in the search field and if so, I search for a car by the given registration number and enter its data into the Treeview widget.
def on_entry_return(self, event):
vrn = self.search_variable.get()
if vrn == '':
self.show_cars()
else:
car = self.helper.search_by_vrn(vrn)
self.car_tview.delete(*self.car_tview.get_children())
if car:
car = list(car)
car.insert(0, 1)
self.car_tview.insert('', 'end', values=car)
The add_car() method creates a new window in which you can enter data about the new vehicle..
def add_car(self):
add_car = NewCarWindow(self.root, self)
The show repairs() method displays the repair window for the selected car.
def show_repairs(self):
car = self.__get_car_from_selection()
if car:
repairs = RepairsWindow(self.root, car)
The NewCarWindow class in the new_car.py file describes a simple form for entering data about a new vehicle.
During form validation, it is checked whether all fields have been completed. Then, using the add_car() method of the Helper class, a new vehicle is created in the database.
import tkinter as tk
from sql_helper import Helper
class NewCarWindow():
def __init__(self, root, parent):
self.top_level = tk.Toplevel(root)
self.helper = Helper()
self.parent = parent
x = self.top_level.winfo_screenwidth()
y = self.top_level.winfo_screenheight()
geometry = '+{}+{}'.format(int((x / 2) - 100),
int((y / 2) - 100))
size = self.top_level.geometry(geometry)
self.top_level.title('Add car')
self.top_level.grab_set()
label_make = tk.Label(self.top_level, text='Make: ',
font=12, padx=20, pady=10).grid(row=0, column=0)
label_model = tk.Label(self.top_level, text='Model: ',
font=12, padx=20, pady=10).grid(row=1, column=0)
label_year = tk.Label(self.top_level, text='Year: ',
font=12, padx=20, pady=10).grid(row=2, column=0)
label_vrn = tk.Label(self.top_level, text='VRN: ',
font=12, padx=20, pady=10).grid(row=3, column=0)
label_vin = tk.Label(self.top_level, text='VIN: ',
font=12, padx=20, pady=10).grid(row=4, column=0)
self.make_sv = tk.StringVar()
self.model_sv = tk.StringVar()
self.year_sv = tk.StringVar()
self.vrn_sv = tk.StringVar()
self.vin_sv = tk.StringVar()
self.info_sv = tk.StringVar()
entry_make = tk.Entry(
self.top_level, text=self.make_sv)
entry_make.focus_set()
entry_make.grid(row=0, column=1)
entry_model = tk.Entry(
self.top_level, text=self.model_sv).grid(row=1, column=1)
entry_year = tk.Entry(
self.top_level, text=self.year_sv).grid(row=2, column=1)
entry_vrn = tk.Entry(
self.top_level, text=self.vrn_sv).grid(row=3, column=1)
entry_vin = tk.Entry(
self.top_level, text=self.vin_sv).grid(row=4, column=1)
info_label = tk.Label(self.top_level, textvariable=self.info_sv,
font=12, padx=10, pady=10, fg='red').grid(row=5, column=0, columnspan=2)
save_button = tk.Button(self.top_level, text='Save',
command=self.save_new_car)
save_button.bind('<Return>', self.save_new_car)
save_button.grid(row=6, column=1, sticky='W', padx=10)
cancel_button = tk.Button(self.top_level, text='Cancel',
command=self.top_level.destroy)
cancel_button.grid(row=6, column=1, sticky='W', padx=70)
cancel_button.bind('<Return>', self.top_level.destroy)
def save_new_car(self, event=None):
if self.make_sv.get() and self.model_sv.get() and self.year_sv.get() and self.vrn_sv.get() and self.vin_sv.get():
self.helper.add_car(self.make_sv.get(),
self.model_sv.get(),
self.year_sv.get(),
self.vrn_sv.get(),
self.vin_sv.get())
self.top_level.destroy()
self.parent.show_cars()
else:
self.info_sv.set('Please fill in all entry fields')
The RepairsWindow class of the repairs.py file describes a window displaying repairs for a given car. You can also add a new repair note using the add_repair method of this class.
import tkinter as tk
from tkinter import ttk
from sql_helper import Helper
from date_picker import DatePicker
class RepairsWindow():
def __init__(self, root, car):
self.top_level = tk.Toplevel(root)
self.root = root
self.top_level.title('Repairs')
self.top_level.grab_set()
self.car = car
self.helper = Helper()
x = self.top_level.winfo_screenwidth()
y = self.top_level.winfo_screenheight()
geometry = '+{}+{}'.format(int((x / 2) - 150),
int((y / 2) - 150))
size = self.top_level.geometry(geometry)
toolbox_frame = tk.Frame(self.top_level)
toolbox_frame.grid(column=0, row=0, sticky='W')
self.add_repair_img = tk.PhotoImage(file='Resources/add_repair.gif')
add_repair_button = tk.Button(
toolbox_frame, image=self.add_repair_img, command=self.add_repair)
add_repair_button.grid(column=0, row=0, sticky='W')
add_repair_button.bind('<Return>', self.add_repair)
add_repair_button.bind('<KP_Enter>', self.add_repair)
if car.sold:
add_repair_button.config(state='disabled')
col_headers = ('No', 'Date', 'Description')
self.repairs_tv = ttk.Treeview(self.top_level, columns=col_headers,
show='headings', selectmode='none')
self.repairs_tv.tag_configure('c1', background='ivory2')
self.repairs_tv.tag_configure('c2', background='ivory3')
for i, col in enumerate(col_headers):
self.repairs_tv.heading(col, text=col)
self.repairs_tv.column(col, anchor='center')
if i == 0:
self.repairs_tv.column(col, width=50, stretch='NO')
self.repairs_tv.grid(column=0, row=2, sticky='NSWE')
scrollbar = tk.Scrollbar(self.top_level, command=self.repairs_tv.yview)
scrollbar.grid(column=1, row=2, sticky='NS')
self.show_repairs()
def add_repair(self, event=None):
self.add_repair_frame = tk.Frame(self.top_level)
self.add_repair_frame.grid(
column=0, row=1, pady=20, sticky='WE')
date_label = tk.Label(self.add_repair_frame,
text='Date:').grid(column=0, row=2)
self.date_sv = tk.StringVar()
self.date_entry = tk.Entry(self.add_repair_frame,
text=self.date_sv)
self.date_entry.focus_set()
self.date_entry.grid(column=1, row=2, sticky='W')
self.cal_img = tk.PhotoImage(file='Resources/calendar.gif')
show_cal_btn = tk.Button(self.add_repair_frame, image=self.cal_img,
command=self.show_cal, relief='flat').grid(column=1, row=2, sticky='W', padx=170)
description_label = tk.Label(self.add_repair_frame,
text='Description:').grid(column=0, row=3)
self.description_sv = tk.StringVar()
self.description_entry = tk.Entry(self.add_repair_frame,
text=self.description_sv)
self.description_entry.grid(column=1, row=3, ipadx=200)
save_button = tk.Button(self.add_repair_frame, text='Save',
command=self.save_repair)
save_button.grid(column=1, row=4, pady=10, sticky='E')
save_button.bind('<Return>', self.save_repair)
save_button.bind('<KP_Enter>', self.save_repair)
cancel_button = tk.Button(self.add_repair_frame, text='Cancel',
command=self.cancel_repair)
cancel_button.grid(column=1, row=4, sticky='E', padx=60)
cancel_button.bind('<Return>', self.cancel_repair)
cancel_button.bind('<KP_Enter>', self.cancel_repair)
def cancel_repair(self, event=None):
self.add_repair_frame.grid_remove()
def save_repair(self, event=None):
if self.date_sv.get() and self.description_sv.get():
self.helper.add_repair(self.car, self.date_sv.get(),
self.description_sv.get())
self.show_repairs()
self.add_repair_frame.grid_remove()
def show_repairs(self):
repairs = self.helper.show_repairs(self.car)
self.repairs_tv.delete(*self.repairs_tv.get_children())
for i, repair in enumerate(repairs, start=1):
repair = (i, repair[0], repair[2])
if i % 2:
self.repairs_tv.insert('', 'end', values=repair, tag='c1')
else:
self.repairs_tv.insert('', 'end', values=repair, tag='c2')
def show_cal(self, event=None):
date_picker = DatePicker(self.top_level, self.date_entry, '%d-%m-%Y')
self.description_entry.focus_set()
In the next post I will describe my DatePicker class for Tkinter.
