Return Book

Return Book

Above UI we are going to create by Tkinter for returning book in our Library management system desktop application. For that first we create a window and configure its title, size and color. Here we are creating a window at Top Level so we can add this window at the top of any other window.

    
        self.root = tk.Toplevel(self)
        self.root.title("Return Book")
        color = "#FFFFFF"

        self.root.configure(bg="#585858")
        self.root.resizable(width=0, height=0)
        win_width = 1400
        print(1280 * 56.25 / 100)
        win_height = int(1280 * 56.25 / 100)
        self.root.geometry(str(win_width) + "x" + str(win_height))

        Util.center(self.root)

        # Get screen size
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        Util.set_font_size(screen_width, screen_height, win_width, win_height)

        self.width = win_width * 96 / 100
        self.height = win_height * 94 / 100
    

After creation of window, we will add a canvas background.

    
    bg_canvas = RoundBackgroundFrame(root, self.width, self.height, padding, cornerradius, self.color, "#585858") 
    bg_canvas.place(width=self.width, height=self.height, x=win_width / 2 - self.width / 2,y=win_height / 2 - self.height / 2)

    class RoundBackgroundFrame(tk.Canvas):

        def __init__(self, parent, width, height, padding, cornerradius, color, bg):
            tk.Canvas.__init__(self, parent, borderwidth=0, relief="flat", highlightthickness=0, bg=bg)

            original = Image.open("images/corner.png") 
            resized = original.resize((int(40), int(40)), Image.ANTIALIAS) 
            self.image_r_t = ImageTk.PhotoImage(resized)

            original = original.rotate(90, expand=0)
            resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
            self.image_l_t = ImageTk.PhotoImage(resized)

            original = original.rotate(90, expand=0)
            resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
            self.image_l_b = ImageTk.PhotoImage(resized)

            original = original.rotate(90, expand=0)
            resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
            self.image_r_b = ImageTk.PhotoImage(resized)

            self.shape(width, height, padding, cornerradius, color)
            (x0, y0, x1, y1) = self.bbox("all")
            width = (x1 - x0)
            height = (y1 - y0)
            self.configure(width=width, height=height)

        def shape(self, width, height, padding, cornerradius, color):
            self.create_polygon((padding, height - cornerradius - padding, padding, cornerradius + padding,
                        padding + cornerradius, padding, width - padding - cornerradius, padding,
                        width - padding, cornerradius + padding, width - padding,
                        height - cornerradius - padding, width - padding - cornerradius, height - padding,
                        padding + cornerradius, height - padding), fill=color, outline=color)

            self.create_image(width - self.image_r_t.width(), 0, image=self.image_r_t, anchor=NW)
            self.create_image(0, 0, image=self.image_l_t, anchor=NW)
            self.create_image(0, height - self.image_l_b.width(), image=self.image_l_b, anchor=NW)
            self.create_image(width - self.image_r_b.width(), height - self.image_r_b.width(), image=self.image_r_b,anchor=NW)

    

Once your window is created with custom background, we will create a frame with some reduced dimensions.

    
        self.width = self.width * 98 / 100
        self.height = self.height * 96 / 100
        self.base_frame = Frame(self.root, width=self.width, height=self.height, bg=self.color)
        bg_canvas.create_window(self.width / 100, self.height * 2 / 100, anchor=NW, window=self.base_frame)


    # Add Heading Name
    add_heading_label(self.base_frame, self.color, AppConstant.FONT_SIZE, self.height, self.width)

    def add_heading_label(base_frame, color, font_size, height, width):
        label_heading = Label(base_frame, text="Return Book", anchor=CENTER, bg=color,
                          font=("Lucida Grande", font_size + 6))
        label_heading.place(width=width * 90 / 100, height=height * 5 / 100, x=width * 5 / 100, y=height * 0.2 / 100)

    # Add line
    add_line_border(self.base_frame, self.color, self.height, self.width)

    def add_line_border(base_frame, color, height, width):
        line_canvas = Canvas(base_frame, bg=color, borderwidth=0, relief="flat", highlightthickness=0)
        line_canvas.place(width=width - 4, height=5, x=2, y=height * 7 / 100)
        line_canvas.create_line(0, 0, width, 0, fill="#787878")

    button_font = add_action_frame(self.base_frame, self.color, self.height, self.width)
    
    def add_action_frame(base_frame, color, height, width):
        afw = width * 0.35
        afh = height * 0.90

        button_font = ("Lucida Grande", AppConstant.FONT_SIZE - 6)
        label_frame_action = LabelFrame(base_frame, text="Actions", font=button_font, pady=afw * 2 / 100,
                                    padx=afw * 2 / 100, bg=color)
        label_frame_action.place(width=afw, height=afh, x=width * 0.65, y=height * 0.09)
        return button_font

    add_student_search_frame(self.base_frame, button_font, self.color, self.height, self.width)
    def add_student_search_frame(base_frame, button_font, color, height, width):
        sfw = width * 0.638
        sfh = height * 0.45

        label_frame_search = LabelFrame(base_frame, text="Search Student", font=button_font, pady=sfw * 2 / 100,
                                    padx=sfw * 2 / 100, bg=color)
        label_frame_search.place(width=sfw, height=sfh, x=0, y=height * 0.09)

    add_issued_book_frame(self.base_frame, button_font, self.color, self.height, self.width)
    def add_issued_book_frame(base_frame, button_font, color, height, width):
        sfw = width * 0.638
        sfh = height * 0.40l

        label_frame_search = LabelFrame(base_frame, text="Issued Book", font=button_font, pady=sfw * 2 / 100,
                                padx=sfw * 2 / 100, bg=color)
        label_frame_search.place(width=sfw, height=sfh, x=0, y=height * 0.59)

        
    

Now Create a Search UI for Search Student in database. First we create a entry box to search Students with Student Id and Student Name.

    
        self.ce_student_entry = CustomEntry(self.base_frame, 300, 55, 10, 2, self.color, "Search Student",
                                            "images/ic_search.png")
        self.ce_student_entry.place(x=25, y=87)
        self.ce_student_entry.entry.bind('', self.search_student)

         

Here's the logic to search data in student table

    
    def search_student(self, *arg):

        if self.ce_student_entry.entry.get() != "":
            self.tree.delete(*self.tree.get_children())
            self.book_tree_view.delete(*self.book_tree_view.get_children())
            self.selected_book_tree.delete(*self.selected_book_tree.get_children())

            conn = Util.connect_db()
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM `student` WHERE `name` LIKE ? OR `student_id` LIKE ?",
                        ('%' + str(self.ce_student_entry.entry.get()) + '%',
                        '%' + str(self.ce_student_entry.entry.get()) + '%'))
            fetch = cursor.fetchall()

            count = 0
            for data in fetch:
                if count % 2 == 0:
                    self.tree.insert('', 'end', values=data, tags=('even',))
                else:
                    self.tree.insert('', 'end', values=data, tags=('odd',))
                count = count + 1

            # for data in fetch:
            # self.tree.insert('', 'end', values=data)
            cursor.close()
            conn.close()
        else:
            self.reset_book()

        def reset_book(self):
        self.tree.delete(*self.tree.get_children())
        conn = Util.connect_db()
        cursor = conn.cursor()
        cursor.execute('SELECT * FROM student')
        sql_output = cursor.fetchall()

        count = 0
        for data in sql_output:
            if count % 2 == 0:
                self.tree.insert('', 'end', values=data, tags=('even',))
            else:
                self.tree.insert('', 'end', values=data, tags=('odd',))
            count = count + 1

We have created a Database named "library.db", lets connect that database and put that code in seperate class "Util" because we are going to use it multiple time in our project.

    
    class Util:

        @staticmethod
        def connect_db():
            db = None
            try:
                db = sql.connect("library.db")
                return db
            except sql.Error as error:
                print("Failed to insert data into sqlite table", error)

    

Fetch data from database and show it student in table form with the use of "Treeview" of Tkinter.

    

    style = ttk.Style()
        #  style.element_create("Custom.Treeheading.border", "from", "default")
        style.layout("Custom.Treeview.Heading", [
            ("Custom.Treeheading.cell", {'sticky': 'nswe'}),
            ("Custom.Treeheading.border", {'sticky': 'nswe', 'children': [
                ("Custom.Treeheading.padding", {'sticky': 'nswe', 'children': [
                    ("Custom.Treeheading.image", {'side': 'right', 'sticky': ''}),
                    ("Custom.Treeheading.text", {'sticky': 'we'})
                ]})
            ]}),
        ])
        style.configure("Custom.Treeview", highlightthickness=0, bd=0, font=('Calibri', 11), rowheight=30)

        self.table_heading()
        


        self.tree = ttk.Treeview(self.base_frame, height=5, columns=("c1", "c2", "c3", "c4"),
                                 selectmode="extended", show='tree', style="Custom.Treeview")
        self.tree.tag_configure('odd', background='#DFEBF6', foreground="#000000", )
        self.tree.tag_configure('even', background='#FFFFFF', foreground="#000000", )
        self.tree.place(x=20, y=180)
        self.tree.bind('<>', self.on_select)
        self.get_book_data()
        def get_book_data(self):
            db = Util.connect_db()
            cursor = db.cursor()

            cursor.execute('SELECT * FROM student')
            sql_output = cursor.fetchall()

        vsby = ttk.Scrollbar(self.base_frame, orient="vertical", command=self.tree.yview)
        vsby.place(x=self.width / 2 + 150, y=180, height=153)
        self.tree.configure(yscrollcommand=vsby.set)

        self.tree.column("#1", anchor=tk.CENTER)
        self.tree.column("#2", anchor=tk.CENTER)
        self.tree.column("#3", anchor=tk.CENTER)
        self.tree.column("#4", anchor=tk.CENTER)
        self.tree.heading("#1", text="Student ID", anchor=tk.CENTER)
        self.tree.heading("#2", text="Student Name")
        self.tree.heading("#3", text="Contact No")
        self.tree.heading("#4", text="Email_id")

        self.tree.column("#0", width=0)
        self.tree.column("#1", width=140)
        self.tree.column("#2", width=210)
        self.tree.column("#3", width=210)
        self.tree.column("#4", width=228)

    

We have created our own heading for student table, lets configure it.

    
    def table_heading(self):
        heading_y = 153
        bg_color = "#2929ff"

        canvas = Canvas(self.base_frame, width=788, height=30)
        canvas.create_rectangle(0, 0, 790, 30, fill=bg_color)
        canvas.place(x=20, y=heading_y - 3)

        student_id_label = Label(self.base_frame, text="Student Id",
                                    font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                    foreground="white")
        student_id_label.place(x=40, y=heading_y, width=140)

        student_id_label.configure(anchor="center")

        student_name_label = Label(self.base_frame, text="Name",
                                    font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                    foreground="white")
        student_name_label.place(x=216, y=heading_y, width=140)
        student_name_label.configure(anchor="center")

        student_contact_no = Label(self.base_frame, text="Contact No",
                                    font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                    foreground="white")
        student_contact_no.place(x=425, y=heading_y, width=140)
        student_contact_no.configure(anchor="center")

        student_email_id = Label(self.base_frame, text="Email Id",
                                    font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                    foreground="white")
        student_email_id.place(x=632, y=heading_y, width=140)
        student_email_id.configure(anchor="center")
        

Fetch data from database and show it in book table form with the use of "Treeview" of Tkinter.

    
    self.book_tree_view = ttk.Treeview(self.base_frame, height=6, columns=("c1", "c2", "c3", "c4", "c5", "c6"),
                                           show='tree', style="Custom.Treeview")
        self.book_tree_view.tag_configure('odd', background='#DFEBF6', foreground="#000000", )
        self.book_tree_view.tag_configure('even', background='#FFFFFF', foreground="#000000", )

        self.book_tree_view.place(x=20, y=self.height * 0.68)

        self.book_tree_view.bind('<>', self.on_remove)

        self.book_tree_view.column("#0", width=0)
        self.book_tree_view.column("#1", width=80, anchor=tk.CENTER)
        self.book_tree_view.column("#2", width=230, anchor=tk.CENTER)
        self.book_tree_view.column("#3", width=170, anchor=tk.CENTER)
        self.book_tree_view.column("#4", width=70, anchor=tk.CENTER)
        self.book_tree_view.column("#5", width=150, anchor=tk.CENTER)
        self.book_tree_view.column("#6", width=100, anchor=tk.CENTER)

        self.book_tree_view.bind('<>', self.on_select_book_tree)
        self.book_table_heading()

        def on_select_book_tree(self, *arg):
        current_item = self.book_tree_view.focus()
        print(self.book_tree_view.item(current_item)["values"][0])
        self.selected_book_tree.delete(*self.selected_book_tree.get_children())
        current_item = self.book_tree_view.focus()
        self.selected_row.append(self.book_tree_view.item(current_item)["values"][0])
        self.selected_book_tree.insert("", 'end', text="",
                                       values=(
                                           self.book_tree_view.item(current_item)["values"][0],
                                           self.book_tree_view.item(current_item)["values"][1],
                                           self.book_tree_view.item(current_item)["values"][5]))

        self.show_button()

    

We have created our own heading for book table, lets configure it.

    
    def book_table_heading(self):
        win_height = int(1280 * 65 / 100)
        heading_y = win_height / 2
        text_color = "white"
        bg_color = "#2929ff"

        canvas = Canvas(self.base_frame, width=790, height=30)
        canvas.create_rectangle(0, 0, 800, 30, fill=bg_color)
        canvas.place(x=20, y=heading_y - 3)

        book_id_label = Label(self.base_frame, text="Book Id",
                              font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                              foreground=text_color)
        book_id_label.place(x=28, y=heading_y, width=100)
        book_id_label.configure(anchor="center")

        book_name_label = Label(self.base_frame, text="Name",
                                font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                foreground=text_color)
        book_name_label.place(x=165, y=heading_y, width=140)
        book_name_label.configure(anchor="center")

        book_authorname_label = Label(self.base_frame, text="Author",
                                      font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                      foreground=text_color)
        book_authorname_label.place(x=365, y=heading_y, width=140)
        book_authorname_label.configure(anchor="center")

        book_price = Label(self.base_frame, text="Price",
                           font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                           foreground=text_color)
        book_price.place(x=530, y=heading_y, width=55)
        book_price.configure(anchor="center")

        book_price = Label(self.base_frame, text="Assign Date", width=30,
                           font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                           foreground=text_color)
        book_price.place(x=595, y=heading_y, width=140)
        book_price.configure(anchor="center")

        fine_count = Label(self.base_frame, text="Fine",
                           font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                           foreground=text_color)
        fine_count.place(x=744, y=heading_y, width=60)
        fine_count.configure(anchor="center")

    

Fetch data from database and show it in selected table in action Frame form with the use of "Treeview" of Tkinter.

    

    self.selected_book_table_heading()

        self.selected_row = []
        self.book_list = []

        self.selected_book_tree = ttk.Treeview(self.base_frame, height=1, show="tree")
        self.selected_book_tree.place(x=self.width / 2 + 220, y=180)
        self.selected_book_tree["columns"] = "1", "2", "3"
        self.selected_book_tree.column("#0", width=0)
        self.selected_book_tree.column("#1", width=70)
        self.selected_book_tree.column("#2", width=230)
        self.selected_book_tree.column("#3", width=100)

        self.selected_book_tree.column("#1", anchor=tk.CENTER)
        self.selected_book_tree.column("#2", anchor=tk.CENTER)
        self.selected_book_tree.column("#3", anchor=tk.CENTER)

        

We have created our own heading for selected table, lets configure it.

    
    def selected_book_table_heading(self):
        heading_y = 150
        heading_y = 153
        bg_color = "#2929ff"
        text_color = "#ffffff"
        canvas = Canvas(self.base_frame, width=400, height=30)
        canvas.create_rectangle(0, 0, 1000, 30, fill=bg_color)
        canvas.place(x=self.width / 2 + 220, y=heading_y - 3)
        book_id_label = ttk.Label(self.base_frame, text="Book Id",
                                  font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                  foreground=text_color)
        book_id_label.place(x=self.width / 2 + 225, y=heading_y, width=100)
        book_id_label.configure(anchor="center")

        book_name_label = ttk.Label(self.base_frame, text="Name",
                                    font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                    foreground=text_color)
        book_name_label.place(x=self.width / 2 + 293 + 80, y=heading_y, width=100)
        book_name_label.configure(anchor="center")

        fine_label = ttk.Label(self.base_frame, text="Fine",
                               font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                               foreground=text_color)
        fine_label.place(x=self.width / 2 + 435 + 87, y=heading_y, width=100)
        fine_label.configure(anchor="center")

    

after we create three button "Return","Renew","Lost" repectively.

    

    def show_button(self):
        self.add_button1 = RoundedButton(self.base_frame, 250, 130 / 2.56, self.color, "images/button3.png",
                                         "Return",
                                         font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
                                         command=self.return_click)
        self.add_button1.place(x=960, y=self.height * 0.50)

        self.add_button2 = RoundedButton(self.base_frame, 250, 130 / 2.56, self.color, "images/button3.png",
                                         "Renew",
                                         font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
                                         command=self.renew_click)
        self.add_button2.place(x=960, y=self.height * 0.60)

        self.add_button3 = RoundedButton(self.base_frame, 250, 130 / 2.56, self.color, "images/button3.png",
                                         "Lost",
                                         font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
                                         command=self.lost_click)
        self.add_button3.place(x=960, y=self.height * 0.70)

    

Here the logic of these buttons click.

    
    def return_click(self):
        cur_item = self.book_tree_view.focus()
        cur_item2 = self.tree.focus()
        return_datetime = datetime.datetime.today().strftime('%Y-%m-%d')

        fine_paid = self.book_tree_view.item(cur_item)["values"][5]
        book_number = self.book_tree_view.item(cur_item)["values"][0]
        student_id = self.tree.item(cur_item2)["values"][0]
        print(fine_paid, book_number, return_datetime, student_id)

        response = messagebox.askokcancel("Are you sure?", " Do you want to return the Book ")
        if response:
            db = Util.connect_db()
            cursor = db.cursor()
            cursor.execute(
                "UPDATE readers SET return_datetime = ?, fine_paid = ? WHERE book_number = ? AND student_id = ?",
                (return_datetime, fine_paid, book_number, student_id))

            cursor.execute("SELECT book_available_count FROM book WHERE book_number IS ?", (book_number,))
            rows = cursor.fetchone()
            print(rows[0])

            id_count = Util.convert_string_to_int(rows[0]) + 1

            cursor.execute("UPDATE book SET book_available_count = ? WHERE book_number = ?",
                           (id_count, book_number,))

            db.commit()

            self.update_ui()

    def renew_click(self):
        cur_item = self.book_tree_view.focus()
        cur_item2 = self.tree.focus()
        return_datetime = datetime.datetime.today().strftime('%Y-%m-%d')
        fine_paid = self.book_tree_view.item(cur_item)["values"][5]
        book_number = self.book_tree_view.item(cur_item)["values"][0]
        student_id = self.tree.item(cur_item2)["values"][0]

        print("Hello Test")
        db = Util.connect_db()
        cursor = db.cursor()
        response = messagebox.askokcancel("Do you want to return", " Do you want to renew the book")
        print(response)

        s_no = None
        current_date = datetime.datetime.today().strftime('%Y-%m-%d')
        print(current_date)
        assigned_staff_id = AppConstant.STAFF_ID
        return_staff_id = ""

        if response:
            conn = Util.connect_db()
            cursor.execute(
                "UPDATE readers SET return_datetime = ?, fine_paid = ? WHERE book_number = ? AND student_id = ?",
                (return_datetime, fine_paid, book_number, student_id))
            conn.commit()
            return_date = None
            fine_paid = None
            cursor.execute("INSERT INTO readers VALUES (?,?,?,?,?,?,?,?)", (
                s_no, student_id, book_number, current_date, return_date, fine_paid, assigned_staff_id, return_staff_id,
            ))

            conn.commit()
            self.update_ui()

    def lost_click(self):
        cur_item = self.book_tree_view.focus()
        cur_item2 = self.tree.focus()
        return_datetime = datetime.datetime.today().strftime('%Y-%m-%d')
        fine_paid = self.book_tree_view.item(cur_item)["values"][5]
        book_number = self.book_tree_view.item(cur_item)["values"][0]
        student_id = self.tree.item(cur_item2)["values"][0]

        response = messagebox.askokcancel("Do you want to return", " DO you lost the book")
        print(response)
        if response:
            db = Util.connect_db()
            cursor = db.cursor()
            cursor.execute(
                "UPDATE readers SET return_datetime = ?, fine_paid = ? WHERE book_number = ? AND student_id = ?",
                (return_datetime, fine_paid, book_number, student_id))

            cursor.execute("SELECT book_count FROM book WHERE book_number = ?", (book_number,))
            sql_output = cursor.fetchone()
            book_count = Util.convert_string_to_int(sql_output[0]) - 1

            cursor.execute("UPDATE book SET book_count = ? WHERE book_number = ?", (
                book_count, book_number
            ))
            db.commit()
            self.update_ui()
            

At last we will manage closing of window

    
    def on_closing():
                        
        root.destroy()
        args[0].deiconify()
                       
    root.protocol("WM_DELETE_WINDOW", on_closing)
    

Programmer Mirta is for learning and training. Projects might be simple to improve learning. Projects are constantly reviewed to avoid errors, but we cannot assure full correctness of all content. While using Programmer Mitra, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 2021 by Programmer Mitra. All Rights Reserved.