diff --git a/README.md b/README.md index b1bb266..0b9b67e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Guia interactiva con la resolución de los retos propuestos en el libro [Python by Example](https://www.google.cl/books/edition/Python_by_Example/gDGdDwAAQBAJ) de *Nichola Lacey* -## Retos básicos +### Retos Básicos - [001-011](./basic/basic01.py) - [012-019](./basic/basic02.py) @@ -14,7 +14,7 @@ de *Nichola Lacey* - [045-051](./basic/basic06.py) - [052-059](./basic/basic07.py) -## Retos Turtle +### Retos Turtle - [060](./trtl/turtle01.py) - [061](./trtl/turtle02.py) @@ -26,7 +26,7 @@ de *Nichola Lacey* - [067](./trtl/turtle08.py) - [068](./trtl/turtle09.py) -## Retos Intermedios +### Retos Intermedios - [069-079](./interm/interm01.py) - [080-087](./interm/interm02.py) @@ -36,6 +36,24 @@ de *Nichola Lacey* - [111-117](./interm/interm06.py) - [118-123](./interm/interm07.py) +### Retos Tkinter + +- [124](./tkgui/tk01.py) +- [125](./tkgui/tk02.py) +- [126](./tkgui/tk03.py) +- [127](./tkgui/tk04.py) +- [128](./tkgui/tk05.py) +- [129](./tkgui/tk06.py) +- [130](./tkgui/tk07.py) +- [131](./tkgui/tk08.py) +- [132](./tkgui/tk09.py) +- [133](./tkgui/tk10.py) +- [134](./tkgui/tk11.py) +- [135](./tkgui/tk12.py) +- [136](./tkgui/tk13.py) +- [137](./tkgui/tk14.py) +- [138](./tkgui/tk15.py) + ## Uso ```sh diff --git a/main.py b/main.py index 0729729..76ce014 100755 --- a/main.py +++ b/main.py @@ -13,7 +13,8 @@ def toc(): 3) Intermedios 069-123 4) Tkinter 124-138 5) SQLite 139-145 - ... + 6) Finales 146-150 + s) Salir """ print(content) @@ -104,12 +105,12 @@ def tkinter_challenges(): clear() print(content) opcs_default(1) - selection = user_input(1) + selection = user_input(2) match selection: case 1: tkgui.challenges01() case 2: - #tkgui.challenges02() + tkgui.challenges02() pass case 'v': return @@ -132,7 +133,7 @@ def main(): clear() print(header) toc() - selection = user_input(10) + selection = user_input(6) match selection: case 1: basic_challenges() @@ -143,16 +144,10 @@ def main(): case 4: tkinter_challenges() case 5: + #sqlite_challenges() pass case 6: - pass - case 7: - pass - case 8: - pass - case 9: - pass - case 10: + #final_challenges() pass case 's': select_ok = True diff --git a/tkgui/example02.py b/tkgui/example02.py new file mode 100644 index 0000000..645ae53 --- /dev/null +++ b/tkgui/example02.py @@ -0,0 +1,57 @@ +import tkinter as tk + + +window = tk.Tk() +window.geometry("606x606") +window.configure(background="cyan") + +title_icon = tk.PhotoImage(file = "./imgs/devfzn_64x64.png") +window.iconphoto(False, title_icon) + +#logo = tk.PhotoImage(file = "./imgs/devfzn_250x250.png") +#logoimage = tk.Label(image=logo) +#logoimage.place(x=3, y=3, width=600, height=600) + +# Re-asignable +photo1 = tk.PhotoImage(file = "./imgs/devfzn_250x250.png") +photobox1 = tk.Label(window, image=photo1) +photobox1["image"] = photo1 +photobox1.place(x=3,y=3,width=600,height=600) + +sel_name = tk.StringVar(window) +sel_name.set("Selecciona nombre") +lst_name = tk.OptionMenu(window, sel_name, "Bob", "Ret", "Znorb") +lst_name.place(x=253, y=75) + +photo2 = tk.PhotoImage(file = "./imgs/img_4.png") +photobox2 = tk.Label(window, image=photo2) +photobox2.place(x=203,y=203,width=250,height=250) + +lbl_msg = tk.Message(text='', font="Verdana 48") +lbl_msg.place(x=80, y=520, width=420, height=60) +lbl_msg["justify"] = "center" + +def clicked(): + sel = sel_name.get() + msg = f"Hola {sel}" + lbl_msg["text"] = msg + match sel: + case 'Bob': + photo = tk.PhotoImage(file = "./imgs/img_1.png") + photobox2.image = photo + case 'Ret': + photo = tk.PhotoImage(file = "./imgs/img_2.png") + photobox2.image = photo + case 'Znorb': + photo = tk.PhotoImage(file = "./imgs/img_3.png") + photobox2.image = photo + case _: + photo = tk.PhotoImage(file = "./imgs/devfzn_250x250.png") + photobox2.image = photo + photobox2["image"] = photo + photobox2.update() + +button = tk.Button(text="Click", command=clicked) +button.place(x=253, y=30, width=150, height=25) + +window.mainloop() diff --git a/tkgui/imgs/devfzn_100x100.png b/tkgui/imgs/devfzn_100x100.png new file mode 100644 index 0000000..60fb320 Binary files /dev/null and b/tkgui/imgs/devfzn_100x100.png differ diff --git a/tkgui/imgs/devfzn_250x250.png b/tkgui/imgs/devfzn_250x250.png new file mode 100644 index 0000000..dd84b07 Binary files /dev/null and b/tkgui/imgs/devfzn_250x250.png differ diff --git a/tkgui/imgs/devfzn_64x64.png b/tkgui/imgs/devfzn_64x64.png new file mode 100644 index 0000000..93fff2b Binary files /dev/null and b/tkgui/imgs/devfzn_64x64.png differ diff --git a/tkgui/imgs/error.png b/tkgui/imgs/error.png new file mode 100644 index 0000000..c9ff966 Binary files /dev/null and b/tkgui/imgs/error.png differ diff --git a/tkgui/imgs/iconart.png b/tkgui/imgs/iconart.png new file mode 100644 index 0000000..9d600a7 Binary files /dev/null and b/tkgui/imgs/iconart.png differ diff --git a/tkgui/imgs/img_1.png b/tkgui/imgs/img_1.png new file mode 100644 index 0000000..c63bc30 Binary files /dev/null and b/tkgui/imgs/img_1.png differ diff --git a/tkgui/imgs/img_2.png b/tkgui/imgs/img_2.png new file mode 100644 index 0000000..bbe4ba0 Binary files /dev/null and b/tkgui/imgs/img_2.png differ diff --git a/tkgui/imgs/img_3.png b/tkgui/imgs/img_3.png new file mode 100644 index 0000000..b25bbb2 Binary files /dev/null and b/tkgui/imgs/img_3.png differ diff --git a/tkgui/imgs/img_4.png b/tkgui/imgs/img_4.png new file mode 100644 index 0000000..c3ee5b3 Binary files /dev/null and b/tkgui/imgs/img_4.png differ diff --git a/tkgui/imgs/ini.png b/tkgui/imgs/ini.png new file mode 100644 index 0000000..81b7bf3 Binary files /dev/null and b/tkgui/imgs/ini.png differ diff --git a/tkgui/imgs/ok.png b/tkgui/imgs/ok.png new file mode 100644 index 0000000..67394b5 Binary files /dev/null and b/tkgui/imgs/ok.png differ diff --git a/tkgui/tk10.py b/tkgui/tk10.py new file mode 100644 index 0000000..7597435 --- /dev/null +++ b/tkgui/tk10.py @@ -0,0 +1,53 @@ +from os import getcwd as pwd +import tkinter as tk + +def tk_10(): + """Create your own icon that consists of several vertical multi-coloured + lines. Create a logo which measures 200 x 150, using Paint or another + graphics package. Create the following window using your own icon and + logo.When the user enters their name and clicks on the Press Me button + it should display "Hello" and their name in the second text box.""" + base_path = f"{pwd()}/tkgui/imgs" + c_bg="magenta" + window = tk.Tk() + window.geometry("400x300") + window.configure(background=c_bg) + + title_icon = tk.PhotoImage(file = f"{base_path}/devfzn_64x64.png") + window.iconphoto(False, title_icon) + window.title("Saludo Tk") + + photo1 = tk.PhotoImage(file = f"{base_path}/img_4.png") + photobox1 = tk.Label(window, image=photo1) + photobox1["image"] = photo1 + photobox1["bg"] = c_bg + photobox1.place(x=70,y=0,width=250,height=200) + + name_in = tk.Entry() + name_in.place(x=120, y=200, width=160, height=30) + + lbl_name = tk.Message(text="Nombre", font="Verdana 12") + lbl_name["bg"] = c_bg + lbl_name["width"] = 70 + lbl_name["justify"] = "center" + lbl_name.place(x=40, y=200, width=70, height=30) + + lbl_msg = tk.Message(text="", font="Verdana 18") + lbl_msg.place(x=160, y=240, width=200, height=30) + lbl_msg["justify"] = "left" + lbl_msg["width"] = 200 + lbl_msg["bg"] = c_bg + + def clicked(): + sel = name_in.get() + name_in["text"] = "" + msg = f"Hola {sel}" + lbl_msg["text"] = msg + name_in.focus() + + button = tk.Button(text="Click", command=clicked) + button.place(x=40, y=240, width=100, height=30) + name_in.focus() + + + window.mainloop() diff --git a/tkgui/tk11.py b/tkgui/tk11.py new file mode 100644 index 0000000..6763096 --- /dev/null +++ b/tkgui/tk11.py @@ -0,0 +1,97 @@ +from os import getcwd as pwd +import tkinter as tk +from random import randint + +def tk_11(): + """Create a new program that will generate two random whole numbers between + 10 and 50. It should ask the user to add the numbers together and type in + the answer. If they get the question correct, display a suitable image such + as a tick; if they get the answer wrong, display another suitable image such + as a cross. They should click on a Next button to get another question.""" + base_path = f"{pwd()}/tkgui/imgs" + window = tk.Tk() + window.title("Sumas TK") + window.geometry("380x470") + + title_icon = tk.PhotoImage(file = f"{base_path}/devfzn_64x64.png") + window.iconphoto(False, title_icon) + + def generate(): + num = randint(10,50) + txt_box_1["fg"] = "black" + txt_box_1["bg"] = "magenta" + txt_box_1["text"] = f"{num}" + num = randint(10,50) + txt_box_2["fg"] = "black" + txt_box_2["bg"] = "magenta" + txt_box_2["text"] = f"{num}" + txt_num_in.delete(0, 'end') + img_ini = tk.PhotoImage(file = f"{base_path}/ini.png") + box_img.image = img_ini + box_img["image"] = img_ini + box_img.update() + lbl_resp["text"] = "" + txt_num_in.focus() + + lbl_info = tk.Label(text="SUMA", font="Verdana 50") + lbl_info.place(x=40, y=25, width=300, height=75) + + txt_box_1 = tk.Message(text="", font="Verdana 30") + txt_box_1["fg"] = "red" + txt_box_1["bg"] = "cyan" + txt_box_1["justify"] = "center" + txt_box_1["width"] = 80 + txt_box_1.place(x=40, y=160, width=80, height=80) + + lbl_plus = tk.Label(text="+", font="Verdana 20") + lbl_plus.place(x=125, y=185, width=20, height=20) + lbl_equal = tk.Label(text="=", font="Verdana 20") + lbl_equal.place(x=235, y=185, width=20, height=20) + + txt_box_2 = tk.Message(text="", font="Verdana 30") + txt_box_2["fg"] = "red" + txt_box_2["bg"] = "cyan" + txt_box_2["justify"] = "center" + txt_box_2["width"] = 80 + txt_box_2.place(x=150, y=160, width=80, height=80) + + def check(): + num_1 = txt_box_1["text"] + num_2 = txt_box_2["text"] + resp = txt_num_in.get() + resp = resp.replace(' ', '') + if resp.isdigit() and (int(resp) == int(num_1)+int(num_2)): + lbl_resp["text"] = "¡Correcto!" + img_resp = tk.PhotoImage(file = f"{base_path}/ok.png") + box_img.image = img_resp + else: + lbl_resp["text"] = "¡Incorrecto!" + img_resp = tk.PhotoImage(file = f"{base_path}/error.png") + box_img.image = img_resp + box_img["image"] = img_resp + box_img.update() + btn_launch.focus() + + btn_launch = tk.Button(text="Generar", command=generate) + btn_launch.place(x=40, y=110, width=300, height=35) + btn_launch.focus() + + txt_num_in = tk.Entry(font="Verdana 30") + txt_num_in["fg"] = "black" + txt_num_in["bg"] = "cyan" + txt_num_in["justify"] = "center" + txt_num_in["width"] = 4 + txt_num_in.place(x=265, y=160, width=80, height=80) + + btn_check = tk.Button(text="Comprobar", command=check) + btn_check.place(x=40, y=260, width=300, height=35) + + lbl_resp = tk.Label(text="", font="Verdana 20") + lbl_resp.place(x=40, y=400, width=300, height=75) + + img_ini = tk.PhotoImage(file = f"{base_path}/ini.png") + box_img = tk.Label(window, image=img_ini) + box_img["image"] = img_ini + box_img.place(x=138,y=310,width=100,height=100) + + window.mainloop() diff --git a/tkgui/tk12.py b/tkgui/tk12.py new file mode 100644 index 0000000..b630875 --- /dev/null +++ b/tkgui/tk12.py @@ -0,0 +1,57 @@ +from os import getcwd as pwd +import tkinter as tk + +def tk_12(): + """Create a simple program that shows a drop-down list containing several + colours and a Click Me button. When the user selects a colour from the list + and clicks the button it should change the background of the window to that + colour. For an extra challenge, try to avoid using an if statement to do this.""" + base_path = f"{pwd()}/tkgui/imgs" + window = tk.Tk() + window.title("Colores TK") + window.geometry("380x400") + + title_icon = tk.PhotoImage(file = f"{base_path}/devfzn_64x64.png") + window.iconphoto(False, title_icon) + window["bg"] = "white" + + colours = [ + 'dark slate gray', + 'slate gray', + 'cornflower blue', + 'dodger blue', + 'deep sky blue', + 'dark turquoise', + 'pale goldenrod', + 'tomato', + 'violet red', + 'purple', + 'DarkOrchid2', + 'DarkOrchid4', + ] + + lbl_info = tk.Label(text="COLORES", font="Verdana 50") + lbl_info["bg"] = "white" + lbl_info.place(x=40, y=25, width=300, height=75) + + lst_color = tk.Listbox() + for i, color in enumerate(colours): + lst_color.insert(i, color) + lst_color["justify"] = "center" + lst_color.place(x=40, y=160, width=300, height=220) + + def apply_color(): + try: + color = lst_color.curselection()[0] + window["bg"] = colours[color] + lbl_info["bg"] = colours[color] + except IndexError: + window["bg"] = "white" + lbl_info["bg"] = "white" + lst_color.focus() + + btn_chng_color = tk.Button(text="Aplicar Color", command=apply_color) + btn_chng_color.place(x=40, y=110, width=300, height=35) + btn_chng_color.focus() + + window.mainloop() diff --git a/tkgui/tk13.py b/tkgui/tk13.py new file mode 100644 index 0000000..bd471ed --- /dev/null +++ b/tkgui/tk13.py @@ -0,0 +1,60 @@ +from os import getcwd as pwd +import tkinter as tk + +def tk_13(): + """Create a program that will ask the user to enter a name and then select + the gender for that person from a drop-down list. It should then add the + name and the gender (separated by a comma) to a list box when the user + clicks on a button.""" + base_path = f"{pwd()}/tkgui/imgs" + window = tk.Tk() + window.title("Personal Data TK") + window.geometry("590x200") + + title_icon = tk.PhotoImage(file = f"{base_path}/devfzn_64x64.png") + window.iconphoto(False, title_icon) + common_bg = "dodger blue" + window["bg"] = common_bg + + gender_ops = [ 'Privado', 'Masculino', 'Femenino', 'Otro' ] + + lbl_info = tk.Label(text="Lista Usuarios", font="Verdana 18") + lbl_info["bg"] = common_bg + lbl_info.place(x=20, y=20, width=200, height=20) + + box_name = tk.Entry() + box_name["justify"] = "left" + box_name.place(x=120, y=62, width=140, height=30) + box_name.focus() + + sel_gen = tk.StringVar(window) + sel_gen.set("género") + lst_genders = tk.OptionMenu(window, sel_gen, *gender_ops) + lst_genders.place(x=275, y=60, width=100) + + lst_users = tk.Listbox() + lst_users["justify"] = "center" + lst_users.place(x=400, y=50, width=150, height=100) + + def add_user(): + name = box_name.get() + gender = sel_gen.get() + if gender != "género" and name != '': + new_user = f"{name},{gender}" + lst_users.insert('end', new_user) + box_name.delete(0,'end') + sel_gen.set("género") + box_name.focus() + else: + lst_genders.focus() + + btn_add = tk.Button(text="Agregar usuario", command=add_user) + btn_add.place(x=40, y=110, width=340, height=35) + + lbl_name = tk.Message(text="NOMBRE", font="Verdana 12") + lbl_name["bg"] = common_bg + lbl_name["width"] = 70 + lbl_name["justify"] = "left" + lbl_name.place(x=40, y=62, width=70, height=25) + + window.mainloop() diff --git a/tkgui/tk14.py b/tkgui/tk14.py new file mode 100644 index 0000000..ea676b1 --- /dev/null +++ b/tkgui/tk14.py @@ -0,0 +1,75 @@ +from os import getcwd as pwd +import tkinter as tk + +def tk_14(): + """Change program 136 so that when a new name and gender is added to the + list box it is also written to a text file. Add another button that will + display the entire text file in the main Python shell window.""" + base_path = f"{pwd()}/tkgui/imgs" + file_path = f"{pwd()}/tkgui/files/users.txt" + window = tk.Tk() + window.title("Personal Data TK") + window.geometry("590x220") + + title_icon = tk.PhotoImage(file = f"{base_path}/devfzn_64x64.png") + window.iconphoto(False, title_icon) + common_bg = "dodger blue" + window["bg"] = common_bg + + gender_ops = [ 'Privado', 'Masculino', 'Femenino', 'Otro' ] + + lbl_info = tk.Label(text="Lista Usuarios", font="Verdana 18") + lbl_info["bg"] = common_bg + lbl_info.place(x=20, y=20, width=200, height=20) + + box_name = tk.Entry() + box_name["justify"] = "left" + box_name.place(x=120, y=62, width=140, height=30) + box_name.focus() + + sel_gen = tk.StringVar(window) + sel_gen.set("género") + lst_genders = tk.OptionMenu(window, sel_gen, *gender_ops) + lst_genders.place(x=275, y=60, width=100) + + lst_users = tk.Listbox() + lst_users["justify"] = "center" + lst_users.place(x=400, y=50, width=150, height=140) + + def add_user(): + name = box_name.get() + gender = sel_gen.get() + if gender != "género" and name != '': + new_user = f"{name},{gender}" + lst_users.insert('end', new_user) + box_name.delete(0,'end') + sel_gen.set("género") + box_name.focus() + with open(file_path, '+a') as file: + file.write(new_user+"\n") + else: + lst_genders.focus() + + def show_users(): + print(("NOMBRE".rjust(10)).ljust(15), "GENERO".rjust(10)) + with open(file_path, 'r') as file: + users = file.readlines() + for user in users: + name = user.split(',')[0] + gender = user.split(',')[1].replace('\n','') + print((name.rjust(10)).ljust(15), + (gender.ljust(10)).rjust(12)) + + btn_add = tk.Button(text="Agregar usuario", command=add_user) + btn_add.place(x=40, y=110, width=340, height=35) + + lbl_name = tk.Message(text="NOMBRE", font="Verdana 12") + lbl_name["bg"] = common_bg + lbl_name["width"] = 70 + lbl_name["justify"] = "left" + lbl_name.place(x=40, y=62, width=70, height=25) + + btn_show = tk.Button(text="Mostrar en Consola", command=show_users) + btn_show.place(x=40, y=150, width=340, height=35) + + window.mainloop() diff --git a/tkgui/tk15.py b/tkgui/tk15.py new file mode 100644 index 0000000..8ae66f7 --- /dev/null +++ b/tkgui/tk15.py @@ -0,0 +1,53 @@ +from os import getcwd as pwd +import tkinter as tk + +def tk_15(): + """Save several images in the same folder as your program and call them + 1.gif, 2.gif, 3.gif, etc. Make sure they are all .gif files. Display one + in a window and ask the user to enter a number. It should then use that + number to choose the correct file name and display the correct image.""" + path_base = f"{pwd()}/tkgui/imgs" + com_bg = "DarkOrchid2" + window = tk.Tk() + window.geometry("310x420") + window.configure(background=com_bg) + + title_icon = tk.PhotoImage(file = f"{path_base}/devfzn_64x64.png") + window.iconphoto(False, title_icon) + + photo1 = tk.PhotoImage(file = f"{path_base}/devfzn_250x250.png") + lbl_img = tk.Label(window, image=photo1) + lbl_img["image"] = photo1 + lbl_img["bg"] = com_bg + lbl_img.place(x=30,y=160,width=250,height=250) + + ent_num = tk.Entry(font="Verdana 20") + ent_num["justify"] = "center" + ent_num.place(x=200, y=100, width=50, height=50) + + lbl_msg = tk.Message(text="Ingresa un número (1-4)", font="Verdana 16") + lbl_msg["width"] = 150 + lbl_msg["bg"] = com_bg + lbl_msg["justify"] = "center" + lbl_msg.place(x=40, y=95, width=150, height=60) + + def clicked(): + sel = ent_num.get() + sel = sel.replace(' ', '') + if sel.isdigit() and (0 < int(sel) < 5): + photo = tk.PhotoImage(file = f"{path_base}/img_{sel}.png") + lbl_img.image = photo + else: + ent_num.delete(0, 'end') + photo = tk.PhotoImage(file = f"{path_base}/error.png") + lbl_img.image = photo + lbl_img["image"] = photo + lbl_img.update() + ent_num.focus() + + button = tk.Button(text="Click", command=clicked) + button["bg"] = "tomato" + button.place(x=40, y=30, width=220, height=50) + ent_num.focus() + + window.mainloop() diff --git a/tkgui/tkgui.py b/tkgui/tkgui.py index 312e926..232ec5c 100644 --- a/tkgui/tkgui.py +++ b/tkgui/tkgui.py @@ -1,17 +1,25 @@ -from . import tk01 as ex01 -from . import tk02 as ex02 -from . import tk03 as ex03 -from . import tk04 as ex04 -from . import tk05 as ex05 -from . import tk06 as ex06 -from . import tk07 as ex07 -from . import tk08 as ex08 -from . import tk09 as ex09 +from . import ( + tk01 as ex01, + tk02 as ex02, + tk03 as ex03, + tk04 as ex04, + tk05 as ex05, + tk06 as ex06, + tk07 as ex07, + tk08 as ex08, + tk09 as ex09, + tk10 as ex10, + tk11 as ex11, + tk12 as ex12, + tk13 as ex13, + tk14 as ex14, + tk15 as ex15 +) from common.common import ( - user_input, - print_run_func, - opcs_default, - clear + user_input, + print_run_func, + opcs_default, + clear ) tab = ' ' @@ -57,3 +65,36 @@ def challenges01(): exit(0) case _: continue + +def challenges02(): + select_ok = False + while not select_ok: + clear() + print(tab, '1)', ex10.tk_10.__doc__) + print(tab, '2)', ex11.tk_11.__doc__) + print(tab, '3)', ex12.tk_12.__doc__) + print(tab, '4)', ex13.tk_13.__doc__) + print(tab, '5)', ex14.tk_14.__doc__) + print(tab, '6)', ex15.tk_15.__doc__) + opcs_default(1) + selection = user_input(6) + match selection: + case 1: + print_run_func(ex10.tk_10) + case 2: + print_run_func(ex11.tk_11) + case 3: + print_run_func(ex12.tk_12) + case 4: + print_run_func(ex13.tk_13) + case 5: + print_run_func(ex14.tk_14) + case 6: + print_run_func(ex15.tk_15) + case 'v': + return + case 's': + select_ok = True + exit(0) + case _: + continue