#############################นำเข้าโมดูล################################
from tkinter import *                                   #นำเข้าโมดูล tkinter เพื่อใช้งาน GUI
from tkinter import ttk, messagebox                    #นำเข้า Widget ttk เพื่อใช้งาน Combobox และ Widget messagebox ที่อยู่ในโมดูล tkinter
import sqlite3                                          #นำเข้าโมดูล sqlite3 เพื่อใช้งานฐานข้อมูล

#############################สร้างฐานข้อมูลและตาราง################################
cn = sqlite3.connect('studentform.db')                   #เชื่อมต่อฐานข้อมูล studentform.db
cur = cn.cursor()                                       #สร้างตัวแปร Cursor ในการชี้ตำแหน่งในฐานข้อมูล
cur.execute('''create table if not exists student          
(
stid int(10),
name varchar(30),
age int(2),
gender varchar(10),
level varchar(30),
school varchar(50),
grade float(10),
primary key(stid)
)
''')                                                        #สร้างตาราง student โดยกำหนด 7 ฟิลด์ข้อมูล 


#############################สร้างหน้าต่างโปรแกรม################################
root = Tk()                                               #เรียกใช้เมธอด Tk() เพื่อสร้างหน้าต่างโปรแกรมขึ้นมา โดยใส่ไว้ในตัวแปร root
root.geometry("550x700")                                #กำหนดขนาดกว้าง x ยาวของหน้าต่าง root
root.resizable(0,0)                                        #ไม่ให้มีการขยายหน้าจอทั้งในแนวกว้างและยาว
root.title("กรอกข้อมูลนักเรียน")                                 #ตั้งชื่อ Title ด้านบนหน้าต่าง root


#############################กำหนดตัวแปร################################
stid = StringVar()                                         #ประกาศตัวแปรแต่ละช่อง Entry สำหรับรับค่าที่ป้อนเข้ามา
name = StringVar()
age = StringVar()
gender = StringVar()
gender.set("0")                                            #กำหนดค่าเริ่มต้นให้ช่อง Entry ที่รับค่าเพศให้เป็น 0 คือไม่เลือกตัวเลือกใดเลย
level = StringVar()
level.set("Select Level")                                    #กำหนดค่าเริ่มต้นให้ช่อง Entry ที่รับค่าชั้นเรียนให้แสดงข้อความว่า Select Level
school = StringVar()
grade = StringVar()


#####################สร้างฟังก์ชันเมื่อคลิกเลือกแถวใน Listbox############################
def selection(event) :                                      #สร้างฟังก์ชัน selection() โดยมีการส่งค่าอาร์กิวเมนต์ event ในการคลิกเลือกแถวใน Listbox มายังฟังก์ชันด้วย
    try :
        value = showlist.get(showlist.curselection())         #นำข้อมูลแถวที่เลือกใน Listbox เก็บไว้ในตัวแปร value ซึ่งข้อมูลที่จะเป็นชนิด Tuple (คล้ายอาร์เรย์)
        stid.set(value[0])                                   #นำแต่ละค่าในตัวแปร value ไปแสดงในแต่ละช่อง Entry
        name.set(value[1])
        age.set(value[2])
        gender.set(value[3])
        level.set(value[4])
        school.set(value[5])
        grade.set(value[6])
    except :      #ถ้าเกิดข้อผิดพลาดขึ้น ให้ผ่านไป ไม่ต้องแจ้งเตือนอะไร
        pass

#############################สร้างฟังก์ชันเคลียร์ค่า################################
def reset() :                                                   #สร้างฟังก์ชัน reset()  เพื่อเซ็ตค่าทุกช่องให้เป็นค่าว่าง
    stid.set("")
    name.set("")
    age.set("")
    gender.set("0")
    level.set("Select Level")
    school.set("")
    grade.set("")
    showlist.delete(0, END)

#############################สร้างฟังก์ชันเพิ่มข้อมูลในตาราง################################
def adddata() :                                                 #สร้างฟังก์ชัน adddata()  เพื่อบันทึกข้อมูลในฐานข้อมูล
    #ตรวจสอบเงื่อนไข ถ้าทุกช่อง Entry ไม่มีค่าว่าง 
    if stid.get() != "" and name.get() != "" and age.get() != "" and gender.get() != "" and level.get() != "Select Level" and school.get() != "" and grade.get() != "" :
        cur.execute("select * from student where stid = ?", (stid.get(),))   #เรียกดูข้อมูลในตารางว่าฟิลด์ stid ตรงกับรหัสนักเรียนที่กรอกในช่อง Entry หรือไม่
        if cur.fetchall() == [] :    #ถ้าตรวจสอบทุกเรคอร์ดในตารางแล้ว รหัสนักเรียนที่กรอกในช่อง Entry ไม่ซ้ำกับฟิลด์ stid ของเรคอร์ดใดเลย ให้บันทึกข้อมูลในฐานข้อมูล
            cur.execute("insert into student (stid, name, age, gender, level, school, grade) values (?, ?, ?, ?, ?, ?, ?)", (stid.get(), name.get(), age.get(), gender.get(),
                                                                                                                             level.get(), school.get(), grade.get()))
            cn.commit()      #อัพเดตการเปลี่ยนแปลงของข้อมูลไปยังฐานข้อมูล
            reset()          #ไปยังฟังก์ชัน reset() เพื่อเซ็ตค่าทุกช่องให้เป็นค่าว่าง         
            showdata()      #ไปยังฟังก์ชัน showdata() เพื่อแสดงเรคอร์ดข้อมูลในตารางฐานข้อมูลในช่อง Listbox
        else :     #ถ้าตรวจสอบทุกเรคอร์ดในตารางแล้ว รหัสนักเรียนที่กรอกในช่อง Entry ซ้ำกับฟิลด์ stid ให้แสดงกล่องข้อความขึ้นมาเตือน
            messagebox.showwarning("เพิ่มข้อมูลไม่สำเร็จ", "ไม่สามารถเพิ่มข้อมูลนักเรียนได้ เนื่องจากรหัสนักเรียนซ้ำ")
            reset()         #ไปยังฟังก์ชัน reset() เพื่อเซ็ตค่าทุกช่องให้เป็นค่าว่าง
    else :  #ถ้าช่อง Entry บางช่องมีค่าว่าง ให้แสดงกล่องข้อความขึ้นมาเตือน
        messagebox.showwarning("ข้อมูลไม่ครบถ้วน", "กรุณากรอกข้อมูลใหม่ให้ครบทุกช่อง")  

#############################สร้างฟังก์ชันแสดงข้อมูลทั้งหมดในตาราง################################
def showdata() :            
    showlist.delete(0, END)
    cur.execute("select * from student")
    for row in cur.fetchall() :
        showlist.insert(END, row)

#############################สร้างฟังก์ชันค้นหาเรคอร์ดข้อมูลในตาราง################################
def searchdata() :
    showlist.delete(0, END)
    cur.execute("select * from student where stid = ?", (stid.get(),))
    for row in cur.fetchall() :
        showlist.insert(END, row)


#############################สร้างฟังก์ชันลบเรคอร์ดข้อมูล################################
def deletedata() :
    result = messagebox.askyesno("ลบข้อมูล", "คุณต้องการลบเรคอร์ดข้อมูลนี้ใช่หรือไม่")
    if result == True :
        cur.execute("delete from student where stid = ?", (stid.get(),))
        cn.commit()
        reset()
        showdata()
    else :
        pass

#############################สร้างฟังก์ชันแก้ไขข้อมูล################################
def editdata() :
    cur.execute("update student set stid = ?, name = ?, age = ?, gender = ?, level = ?, school = ?, grade = ? where stid = ?",
                (stid.get(), name.get(), age.get(), gender.get(), level.get(), school.get(), grade.get(), stid.get()))
    cn.commit()
    showdata()

#############################สร้าง Widget################################
lblTitle = Label(root, text = "Registration Form", width = 20, font = ("TH SarabunPSK", 30), fg = "blue").place(x = 125, y = 0)
lblID = Label(root, text = "ID : ", width = 20, font = ("TH SarabunPSK", 20)).place(x = 0, y = 60)
eID = Entry(root, font = ("TH SarabunPSK", 20), justify = "center", width = 30, textvar = stid).place(x = 150, y = 60)

lblName = Label(root, text = "Name : ", width = 20, font = ("TH SarabunPSK", 20)).place(x = 0, y = 100)
eName = Entry(root, font = ("TH SarabunPSK", 20), justify = "center", width = 30, textvar = name).place(x = 150, y = 100)

lblAge = Label(root, text = "Age : ", width = 20, font = ("TH SarabunPSK", 20)).place(x = 0, y = 140)
eAge = Entry(root, font = ("TH SarabunPSK", 20), justify = "center", width = 30, textvar = age).place(x = 150, y = 140)

lblGender = Label(root, text = "Gender : ", width = 20, font = ("TH SarabunPSK", 20)).place(x = 0, y = 180)
rbGender = Radiobutton(root, text = "Male", padx = 5, font = ("TH SarabunPSK", 20), variable = gender, value = "Male").place(x = 150, y = 180)
rbGender = Radiobutton(root, text = "Female", padx = 5, font = ("TH SarabunPSK", 20), variable = gender, value = "Female").place(x = 250, y = 180)

lblLevel = Label(root, text = "Level : ", width = 20, font = ("TH SarabunPSK", 20)).place(x = 0, y = 220)
cbLevel = ttk.Combobox(root, font = ("TH SarabunPSK", 20), justify = "center", width = 20, textvar = level)
cbLevel["values"] = ("ป.1", "ป.2", "ป.3", "ป.4", "ป.5", "ป.6", "ม.1", "ม.2", "ม.3", "ม.4", "ม.5", "ม.6")
cbLevel.place(x = 150, y = 220)

lblSchool = Label(root, text = "School : ", width = 20, font = ("TH SarabunPSK", 20)).place(x = 0, y = 260)
eSchool = Entry(root, font = ("TH SarabunPSK", 20), justify = "center", width = 30, textvar = school).place(x = 150, y = 260)

lblGrade = Label(root, text = "Grade : ", width = 20, font = ("TH SarabunPSK", 20)).place(x = 0, y = 300)
eGrade = Entry(root, font = ("TH SarabunPSK", 20), justify = "center", width = 30, textvar = grade).place(x = 150, y = 300)

btnReset = Button(root, text = "Reset", font = ("TH SarabunPSK", 20), width = 10, bg = "brown", fg = "white", command = reset).place(x = 125, y = 340)
btnAdd = Button(root, text = "Add", font = ("TH SarabunPSK", 20), width = 10, bg = "brown", fg = "white", command = adddata).place(x = 225, y = 340)
btnShow = Button(root, text = "Show", font = ("TH SarabunPSK", 20), width = 10, bg = "brown", fg = "white", command = showdata).place(x = 325, y = 340)
btnSearch = Button(root, text = "Search", font = ("TH SarabunPSK", 20), width = 10, bg = "brown", fg = "white", command = searchdata).place(x = 125, y = 385)
btnEdit = Button(root, text = "Edit", font = ("TH SarabunPSK", 20), width = 10, bg = "brown", fg = "white", command = editdata).place(x = 225, y = 385)
btnDelete = Button(root, text = "Delete", font = ("TH SarabunPSK", 20), width = 10, bg = "brown", fg = "white", command = deletedata).place(x = 325, y = 385)

#############################สร้าง Listbox แสดงข้อมูลออกทางหน้าจอ################################
showlist = Listbox(root, font = ("TH SarabunPSK", 18), width = 45, height = 8, selectmode = EXTENDED)
showlist.place(x = 75, y = 440)
showlist.bind('<<ListboxSelect>>', selection)  #สร้างเหตุการณ์ (event) เมื่อมีการเลือกแถวใน Listbox แล้วไปยังฟังก์ชัน selection

sb1 = Scrollbar(root)
sb1.place(x = 480, y = 550)
showlist.config(yscrollcommand = sb1.set)
sb1.config(command = showlist.yview)

#############################สร้างเมนู################################
menubar = Menu(root)
fileMenu = Menu(menubar, tearoff = 0)
fileMenu.add_command(label = "Close", command = root.destroy)   #คำสั่ง root.destroy คือคำสั่งปิดหน้าจอโปรแกรม
menubar.add_cascade(label = "File", menu = fileMenu)
root.config(menu = menubar)
root.mainloop()

