Creació de finestres
Fins ara, les aplicacions que hem fet amb python no tenien cap botó, ni caixes de text a on poder escriure ni finestres elegants, i estavem obligats a guiar a l'usuari mitjançant preguntes textuals. D'ara endavant, crearem les nostres aplicacions amb interfície gràfica.
Per fer-ho, estudiarem el paquet "tkinter", que és considerat un estàndar per a la creació d'interfícies gràfiques d'usuari (GUI), i veurem que crear finestres a on es desenvolupin les nostres aplicacions no és complicat.
El següent codi mostra com crear una finestra:
Com es pot veure, la finestra no conté res, però és la primera passa que s'ha de donar. Cal fixar-se al codi i notar que:
S'ha hagut d'importar el paquet "tkinter".
S'ha creat un nou objecte gràfic ("app", encara que el nom podia haver estat qualsevol) que és una instància de la classe Tk(). És a dir, s'ha creat una finestra fent servir el paquet importat.
S'han modificat el títol i les dimensions de la finestra.
De moment, la nostra aplicació no és gens espectacular, però anirem afegint més substància. Per exemple, es pot començar creant un "Hello World" gràfic! Només necessitarem una etiqueta que poder aferrar dins la finestra amb el text adequat.
Com es pot veure, s'ha afegit una etiqueta ("Label") dins la finestra "app" i amb l'atribut "text" que ens interessa. Per finalitzar, només cal empaquetar-la ("pack()"). Com a resultat, la nova finestra mostra el text que volem.
Notem que fins ara no ens hem preocupat per la col·locació de l'etiqueta. L'opció "pack()" apila els objectes de la nostra finestra un damunt s'altre. Ja arribarem a una distribució més elaborada...
Però, anem a afegir un objecte que realitzi alguna funció.
Com a darrer element, s'ha introduït un botó ("Button") dins la finestra "app", amb el text "OK" i que realitza el comandament ("command") "app.destroy". A més, el botó s'ha empaquetat amb l'etiqueta dins la finestra.
Exercicis:
1. Crea la teva primera finestra amb una "Label" i un "Button" seguint les passes anteriors i explica quina és la funció del botó en aquesta aplicació.
Mètodes set() i get()
A les etiquetes (objectes "Label") l'usuari no pot escriure, encara que noltros podriem modificar el seu contingut des del codi. D'altra banda, si volem introduir una "caixa de text" a la que l'usuari pugui escriure, haurem de fer servir la sintaxi:
a on
Es defineix la variable ("valor") que emmagatzemarà l'input de l'usuari.
Es crea l'objecte "caixa" com a instància de la classe "Entry()", dins "app" i amb l'atribut "textvariable" lligat a la variable "valor", que és del tipus "StringVar()" (un text que es pot modificar).
S'empaqueta la caixa amb tota la resta.
L'atribut "textvariable" permet modificar el text que mostra una etiqueta o una caixa de text. Per fer-ho, s'ha de fer servir el mètode "set":
valor.set("Allò que es vulgui escriure")
D'aquesta manera es canvia la variable "valor" que és la que determina què hi ha dins l'objecte.
Si pel contrari es vol llegir el que hi ha escrit a la caixa per fer-ho servir per alguna cosa, s'ha de fer servir el mètode "get":
contingut = valor.get()
Per exemple, jugant amb etiquetes i caixes i els seus mètodes "get" i "set" es pot escriure un programa com el següent:
Exercicis:
2. Modifica el "Hello World!" gràfic que has fet a l'exercici 1 perquè el botó no tanqui la finestra, si no que modifiqui el missatge a "Goodbye World!".
Nota: el "command" del botó haurà d'executar una funció (amb el nom que vulguis) a la que es modifiqui el valor del text de l'etiqueta.
3. Modifica el programa anterior perquè et demani el nom de l'usuari i escrigui un missatge de salutació personalitzat ("Hello Fulanito!").
4. Crea una aplicació capaç de passar de graus Farenheit a Celsius que contengui una caixa de text (input) amb la seva etiqueta descriptiva, una etiqueta per al resultat (output) amb la seva etiqueta descriptiva i dos botons, un per fer la transformació i un altre per tancar la finestra.
5. Fes les següents millores al codi de l'exercici anterior:
Afegeix botons per canviar de Celsius a Farenheit, de Celsius a Kelvin i de Kelvin a Celsius.
Investiga a internet i cerca quina és la manera de canviar els color de fons dels botons, les etiquetes, les finestres...
Layouts (esquemes de disposició)
Fins ara no ens hem preocupat de la col·locació dels objectes dins la finestra. Ara anem a veure com situar cada element de manera elegant.
Dins del paquet "tkinter" de Python n'hi ha diferents formes d'organitzar el objectes dins d'una finestra:
pack(): com ja hem vist, aquest layout apila per defecte els objectes verticalment, però existeixen altres opcions que no hem tractat fins ara.
Les modificacions que es mostren no són les úniques que existeixen, però ens basta amb una mostra del que es pot fer.
place(): amb aquest esquema de col·locació podrem distribuir d'una manera més flexible els objectes per la finestra donant les seves coordenades x i y amb les seves dimensions. Exemple:
grid(): aquest darrer layout permet crear una graella imaginaria de manera que la nostra finestra s'assembla un full de càlcul. Cada casella d'aquest "grid" ens permetrà col·locar un objecte.
L'atribut "columnspan" correspon al nombre de columnes que ocupa un objecte en cas de ser més ample que els altres.
Cal fer notar que els tres layouts no poden coincidir dins la mateixa finestra. Per tant, abans de començar a escriure, s'ha de triar molt bé quin dels tres s'adaptarà millor a la nostra aplicació.
Exercicis:
1. Crea una calculadora com la de la imatge. Ja l'anirem complicant.
2. Afegeix els botons de resta, multiplicació i divisió i col·loca'ls d'una manera que et sembli elegant. Canvia també els colors i millora la presentació en general.
3. Fixa't que l'aplicació anterior, encara que ja fa la seva feina, no funciona com les calculadores a les que estam acostumats. El problema que ens trobarem per fer una calculadora més sofisticada sirà que amb una única caixa de text haurem de donar els inputs i els resultats. Ja veurem com fer-ho!
De moment, fes servir el "grid layout" per crear l'estructura de l'aplicació tal com es veu a la imatge.
4. Per donar una funcionalitat més avançada a la nova versió de la nostra calculadora, fixem-nos en les calculadores de butxaca:
Com es pot veure, per tal de poder realitzar operacions complexes de manera clara per a l'usuari, disposen de dues "pantalles". La primera per escriure l'operació a realitzar i la segona per mostrar el resultat. Anem a procedir de la mateixa manera. Modifica l'exercici anterior per obtenir:
Ara es tracta de crear una funció, "btnClic", que sigui capaç d'anar escrivint a la primera pantalla l'operació que es vol calcular, i una segona funció, "btnIgual", per resoldre l'operació i escriure el resultat a la segona caixa de text. Per fer-ho, haurem de jugar amb els mètodes .get() i .set().
Funció "btnClic": Tots els botons hauran de cridar a aquesta funció per tal d'anar escrivint l'operació. Per tant, les passes que haurà de fer són:
Llegir el text que hi ha escrit a la caixa1 --> .get()
Escriure a la caixa1 el text que hi havia escrit més la tecla pitjada --> .set()
Funció "btnIgual": Només s'haurà de pitjar el botó "Igual" quan es vulgui avaluar l'expressió escrita a la caixa1. Per tant, la feina que haurà de fer aquesta funció és:
Llegir el text que hi ha escrit a la caixa1 --> .get()
Avaluar la cadena de text de la caixa1 i tornar a transformar-ho en text. Això es fa amb la funció "eval" de Python i amb str().
Escriure a la caixa2 el resultat obtingut.
NOTA: Quan es vol cridar a una funció des del "command" d'un botó i se li vol passar qualque paràmetre (el nombre corresponent a la tecla o l'operació de suma, resta,...) s'han de fer servir les funcions lambda:
5. Afegeix les funcions corresponents als botons "Clear" i "Ans" de manera que la primera buidi la caixa1 i escrigui un "0" a la caixa2, i la segona, buidi la caixa2 i escrigui el darrer resultat calculat dins la caixa1 per poder continuar fent feina amb ell.
6. Exercici d'investigació: Cerca per Google com es pot afegir un menú "Arxiu" a la nostra finestra que tengui com opcions, per exemple, saludar, netejar les dues caixes de text i tancar la finestra.