Python Nivel 2
Python Nivel 2
Programación
con Python
Nivel 2
Interfaces Gráficas y
Manejo de Bases de
Datos
Universidad Central de Venezuela, Facultad de Ciencias, Edif. III, Av. Los Ilustres, Los Chaguaramos, Caracas, Venezuela
Tlf. (58 212) 605-13-14 693-47-38 (telfax) correo [email protected] www.ceneac.com.ve
CENEAC - Programación con Python Nivel 2.
ÍNDICE
1. INTRODUCCIÓN............................................................................................................................. 1
2. REQUISITOS: DESCARGA, INSTALACIÓN Y CONFIGURACIÓN DE LAS
HERRAMIENTAS DE TRABAJO ................................................................................................ 2
2.1. Python .......................................................................................................................................... 2
2.2. PyQT ............................................................................................................................................. 3
2.3. Oracle MySQL Community ........................................................................................................... 4
2.4. PyMySQL ...................................................................................................................................... 5
2.5. PyCharm Community ................................................................................................................... 5
3. GESTIÓN DE EXCEPCIONES ...................................................................................................... 7
3.1. Sentencias try… except… finally ................................................................................................... 8
3.2. Información de contexto .............................................................................................................. 9
3.3. Lanzamiento intencional de excepciones .................................................................................... 9
3.4. Excepciones personalizadas ....................................................................................................... 10
4. PROGRAMACIÓN ORIENTADA A OBJETOS: CLASES, MÉTODOS Y HERENCIA ..... 11
4.1. Creación de una clase en Python ............................................................................................... 11
4.2. Modificadores de acceso para métodos y atributos .................................................................. 12
4.3. Atributos constantes .................................................................................................................. 13
4.4. Constructores ............................................................................................................................. 13
4.5. Herencia ..................................................................................................................................... 15
5. DISEÑO DE INTERFACES GRÁFICAS CON PYQT5 ............................................................ 17
5.1. Mostrar una ventana desde Python........................................................................................... 18
5.2. QMainWindow ........................................................................................................................... 21
5.3. Botones: Command Link Button, Push Button, Tool Button...................................................... 22
5.4. Check Box y Radio Button y Group Box...................................................................................... 23
5.5. Line Edit, Text Edit, Plain Text Edit ............................................................................................. 24
5.6. Etiquetas (Label) ......................................................................................................................... 26
5.7. List Widget ................................................................................................................................. 26
5.8. Combo Box ................................................................................................................................. 28
6. MÉTODOS Y EVENTOS DE PYQT5 .......................................................................................... 30
6.1. Toma de contacto con la gestión de eventos ............................................................................ 30
6.2. Eventos de PyQt ......................................................................................................................... 33
6.3. Métodos de PyQt ....................................................................................................................... 36
7. GESTIÓN DE BASES DE DATOS RELACIONALES CON PYTHON .................................. 43
7.1. Bases de datos centralizadas y distribuidas ............................................................................... 43
7.2. Conectar con MySQL Server desde Python ................................................................................ 43
7.3. Modificaciones ........................................................................................................................... 44
7.4. Consultas .................................................................................................................................... 46
7.5. Acceso a una base de datos SQLite ............................................................................................ 48
7.6. Cargar o crear una base de datos SQLite y operar sobre ella .................................................... 48
8. EJEMPLOS RESUELTOS ............................................................................................................ 51
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor.
CENEAC - Programación con Python Nivel 2.
1. INTRODUCCIÓN
Es bien sabido que Python es un lenguaje tan robusto como potente y parte de toda esa potencia, radica en
su capacidad de expandirse y adaptarse a diferentes entornos sin cambiar su esencia y facilidad de uso.
Justo en ello nos enfocaremos en este curso.
Hoy en día los aplicativos escritos en Python tienen una popularidad sin precedentes, y si bien en el nivel
anterior a este manual, se definieron muchos contenidos inherentes al lenguaje y se explicaron muchas
sentencias útiles, nos hemos limitado a recibir y mostrar datos desde y hacia un terminal dirigido por el
intérprete de Python. Sin embargo, en este curso adoptaremos un enfoque diferente. Mantendremos cada
concepto, cada práctica, cada palabra clave aprendida desde la toma de contacto con Python, hasta la
actualidad, pero los combinaremos con la creación de interfaces gráficas modernas, elegantes y
funcionales.
Una interfaz gráfica de usuario (en adelante, GUI por sus siglas en inglés), es un medio visual para
mostrar y recibir información del usuario, a través de un entorno más atractivo y fácil de entender que un
terminal. Toda aplicación dirigida a usuarios finales, como norma no escrita, debe contar con una GUI con
todas las características del aplicativo en cuestión, si lo que se quiere es garantizar la facilidad de uso y la
reducción de la curva de aprendizaje del software, sin descuidad claro, la elaboración de un manual de
usuario completo y entendible que complemente una GUI intuitiva.
En el curso usaremos PyQT. Es un conjunto de bibliotecas dedicadas a la creación de GUI’s en lenguaje
Python. Consiste en código fuente para Python y bibliotecas compiladas en C++ (lenguaje nativo de QT
Framework). Es de código abierto, multiplataforma, y bastante fácil de usar. Utilizado por cientos de
aplicativos, QT es quizás el Framework más conocido para el diseño de interfaces. Tiene un diseñador
gráfico y una suite de trabajo.
Ahora, no es extraño que una aplicación necesite almacenar de forma temporal o permanente, cierta
información en disco asociada a las funciones que realiza. Para esto, los archivos de texto plano pueden
servir algunas veces, sobre todo para realizar anotaciones o modificar alguna configuración existente, pero
si lo que necesitamos es almacenar configuraciones propias o registros de algún tipo y sobre todo, poder
leerlos de forma rápida y simple, necesitamos algún soporte con un formato que lo permita. Nada mejor
para este fin que una base de datos: fácil de usar, confiable, hermética, segura, ligera y rápida.
En este curso usaremos dos sistemas de gestión de bases de datos relacionales (Relational Database
Management System , en adelante RDBMS):
Oracle MySQL Community, el cual permite todo lo anterior, pero con un elemento adicional importante:
Corre sobre un servidor, esto implica que varias aplicaciones (escritas en Python, Java, C, C++ o cualquier
otro lenguaje para el que exista un conector de MySQL) puedan acceder al mismo tiempo a una misma
base de datos MySQL, cuyo servidor esté corriendo en una ubicación de red accesible y conocida por
todas ellas. Esto es una gran ventaja para sistemas distribuidos, portables y escalables. De ahí su amplia
popularidad en el campo laboral. MySQL Community es gratuito, pero su código es privativo desde su
adquisición por Oracle Corporation.
SQLite es el otro RDBMS. Si hay algo cercano a la eficacia, eso es SQLite. A diferencia de MySQL, no
corre sobre un servidor, por lo que su acceso desde distintas ubicaciones de red, es restringido. Sin
embargo, esta carencia es parte de su fuerte. Al no requerir un servidor para funcionar, el acceso a una
base de datos, no debe pasar por protocolos de red que lo ralenticen. Leer y escribir en una base de datos
SQLite es mucho más rápido que en una MySQL y dicha base de datos estará guardada en un único
archivo con el mismo nombre. SQLite se distribuye sin reconocimiento legal; esto quiere decir que usted
es libre de usarlo, estudiarlo, modificarlo y redistribuirlo con o sin sus modificaciones, incluso bajo
licencia comercial, sin necesidad de un permiso del autor. Es un software de dominio público.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 1
CENEAC - Programación con Python Nivel 2.
Empecemos por decir que son varias las cosas que necesitamos. Todas son gratuitas y la instalación de
algunas será más fácil que la de otras. Intentaremos explicar de forma clara y con abundancia de
ilustraciones, la forma de lograr una instalación limpia de todo lo que necesitamos:
Python. Intérprete y bibliotecas estándar
Un IDE para programar en Python, recomendado PyCharm Community o Visual Studio 2012 (o
posterior). Ambos son pesados y requieren un equipo de gama media-baja. Para equipos antiguos
es mejor un editor de código fuente como Notepad++ o el propio editor de Python, llamado IDLE
(Incluido en la instalación de Python 2.7 y posteriores).
PyQT, un conjunto de bibliotecas dedicadas al diseño de GUI’s para Python.
Oracle MySQL Community, un RDBMS
PyMySQL, conector de MySQL para las últimas versiones de Python
Por favor siga las instrucciones que a continuación se suministran, en estricto orden para lograr la
instalación y configuración de todo el software necesario.
2.1. Python
Descargue el instalador desde su página oficial:
https://www.python.org/downloads/release/python-351/
Seleccione la versión instalable acorde a su sistema operativo y la arquitectura del mismo. Recuerde que
las versiones x86 son para sistemas de 32 bits y las versiones x86-64, son para sistemas de 64 bits. Inicie
la instalación y verá una imagen como la siguiente:
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 2
CENEAC - Programación con Python Nivel 2.
Seleccione la casilla Add Python 3.6 to PATH, esto es para poder ejecutar Python desde un terminal, solo
con escribir su nombre.
Luego seleccione Customize Installation para indicar qué componentes se instalarán y para qué usuarios.
Le recomendamos que deje todas las opciones por defecto y luego pulse Next. Cuando lo haga, por favor
coloque las siguientes opciones:
Nota: La casilla Download debugging symbols requiere conexión a internet. Ella descargará los archivos
necesarios para que el depurador de su entorno de desarrollo pueda proveerle mayor información al
momento de ejecutar su aplicación sobre él. Si no posee conexión a internet, no la marque. Si planea
usar Visual Studio 2015 o 2017 para sus aplicativos en Python, es recomendable que marque también la
última casilla: Download debug binaries, recordando que, de igual manera, deberá tener conexión a
internet.
Luego de pulsar Install, iniciará la instalación del Python y al culminar, el instalador nos indicará el
mensaje: Setup was Successful, confirmando así que la instalación concluyó exitosamente. Pulse Close
para cerrar el instalador.
2.2. PyQT
El instalador de PyQT se acopla directamente a su instalación de Python, por lo que éste deberá ser
instalado antes que PyQT. La versión tratada en esta guía es PyQT 5.
Puede descargar PyQT desde acá:
https://sourceforge.net/projects/pyqt/
La instalación es sencilla. Siga los pasos del instalador, siempre seleccionando el botón Next y la
instalación concluirá sin problemas al cabo de unos cuantos segundos.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 3
CENEAC - Programación con Python Nivel 2.
En la parte de abajo aparecen dos enlaces de descarga. El primero es un instalador que descarga todo lo
necesario desde la web. El segundo incluye todo lo necesario para instalar MySQL Server y MySQL
Workbench. Le recomendamos el primero si posee conexión a internet en la máquina de destino, o el
segundo en caso contrario.
En todo caso, inicie el instalador y en los productos a instalar, seleccione los que usted necesite. Para
propósitos del curso, solo necesitamos MySQL Server. Opcionalmente, puede instalar MySQL
Workbench para operar sobre sus bases de datos de forma gráfica, sin embargo, no será usado en este
manual.
Luego de instalar MySQL Server, se iniciará una ventana de configuración de su RDBMS siempre y
cuando no tenga, o haya tenido, una instalación previa de MySQL. En esta ventana, elija un usuario (o
varios) para su base de datos, asígnele permisos y configure una nueva contraseña para el usuario root.
Tenga en cuenta que esta contraseña es la maestra por si ocurriera algún error en su sistema que necesite
acciones especiales o circunstancias en las que no posea permisos suficientes para ciertas operaciones, le
sugerimos que la anote en un lugar seguro.
Luego de configurar usuarios, permisos y contraseñas, continúe con el proceso de configuración, dejando
las opciones por defecto, o configurándolas en tanto sepa la finalidad de cada una.
Una vez concluido el proceso, si dejó las opciones por defecto, MySQL Server se iniciará de ahora en
adelante automáticamente con el sistema, como un servicio de Windows, por lo que, para poder usarlo, no
hará falta iniciarlo manualmente. Consulte la documentación en línea de MySQL Server si desea saber
cómo configurar ésta y otras opciones.
Nota: Es recomendable, que para cada aplicativo exista un sistema de permisos acorde a las actividades
que se van a realizar con la base de datos. Por cuestiones de seguridad, asigne a un usuario, solo los
privilegios necesarios para cumplir con sus funciones.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 4
CENEAC - Programación con Python Nivel 2.
2.4. PyMySQL
Ejecute un símbolo de sistema como administrador, y en él escriba:
“pip install pyMySQL”
Y espere por la instalación.
Al iniciar PyCharm, puede elegir importar configuraciones de una instalación previa de PyCharm, o
iniciarlo desde cero. Luego de seleccionar la opción de su preferencia, aparecerá una ventana de
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 5
CENEAC - Programación con Python Nivel 2.
bienvenida, pidiéndole elegir el tema del IDE, el mapeado del teclado y el color de fuente del editor de
código fuente.
Luego de un reinicio, puede pulsar la opción “New Project” para crear un juego proyecto. Seleccione la
ruta en la que lo guardará y espere un poco. Solo por ser el primer inicio, PyCharm analizará el directorio
de Python en busca de los archivos fuente que contiene, y los indexará. El avance de este proceso se puede
observar detalladamente haciendo clic en la parte inferior derecha del IDE, en el indicador “x process
running”.
Cree un nuevo archivo .py, haciendo clic derecho en el nombre de su proyecto y luego en New Python
File. Para ejecutar este archivo por primera vez, haga clic en Run Run…, luego seleccione el archivo y
éste se ejecutará. De ahora en adelante, para ejecutarlo, simplemente pulse el botón de flecha verde que
está arriba a la derecha del IDE, o directamente pulse Mayús+F10.
Una vez concluido el proceso, puede utilizar el IDE con todas sus funciones. Tómese un tiempo para
familiarizarse con ellas. Ya posee todas las herramientas configuradas y listas para funcionar.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 6
CENEAC - Programación con Python Nivel 2.
3. GESTIÓN DE EXCEPCIONES
Para evitar una excepción, el código anterior se pudo haber cambiado por este:
if __name__ == "__main__":
cadena = "43FFDB"
numero = int(cadena,16)
print(numero)
Así, la conversión se haría en hexadecimal y no en decimal.
Todo programa en Python debe poseer un correcto manejo de excepciones, para evitar que cualquier error
del usuario pueda comprometer la estabilidad de nuestro software.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 7
CENEAC - Programación con Python Nivel 2.
Un ejemplo interesante. Todo el código susceptible a generar excepciones, debe colocarse en el bloque
try. Si se genera una excepción en él, no se ejecutarán las líneas que estén por debajo de la que generó la
excepción y que se encuentren en el mismo try. En su lugar, se ejecutarán las sentencias correspondientes
al except que la atienda. Si se genera una excepción de tipo ZeroDivisionError, entonces se ejecutarán
solo las sentencias de ese except. Si no conocemos el nombre de la excepción, o no es relevante mostrar
un mensaje personalizado, puede usar except sin ningún tipo de excepción.
Sin importar si se genera o no una excepción, las instrucciones que haya en el bloque finally siempre se
ejecutarán.
Si no hay un except genérico y ninguno de los except cubre el error que se generó, la excepción saltará los
controles del try y terminará el programa. Si hay un bloque try, que contiene un finally, pero ningún
bloque except, y se genera una excepción, se interrumpirá igualmente el boque try, se ejecutarán las
instrucciones del finally, pero igualmente terminará el programa a causa de la excepción. Es decir, solo el
bloque except captura excepciones.
El bloque except no solo puede tener una excepción, puede tener varias, separadas por comas.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 8
CENEAC - Programación con Python Nivel 2.
Nota: Si queremos que una excepción no termine el programa, pero aun así no queremos tomar
acciones al respecto, basta con colocar un pass, como única sentencia del bloque except.
if __name__ == "__main__":
pedir_numero()
De nuevo, usamos a Exception como clase para nuestro error. Al ejecutar el ejemplo anterior y colocar en
un número en el texto solicitado, se generará una salida similar a la siguiente:
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 9
CENEAC - Programación con Python Nivel 2.
def __str__(self):
return self.valor
if __name__ == "__main__":
n = int(input("Numero: "))
if n == 1:
raise Propia("Error en entrada",10)
else:
raise Propia()
Se solicita un valor por teclado. Si este valor es 1, se genera una excepción propia por defecto. Si es
distinto a 1, se genera una excepción con parámetros solicitados. Estos parámetros van a una clase que
nosotros creamos, llamada Propia. Esta clase recibe dos parámetros opcionales en su constructor. Estos
parámetros serán el código del error y su texto. Note que se sobrescribe el método __str__ con la finalidad
de mostrar en pantalla el texto correcto cuando se lance la excepción. Este método debe devolver una
cadena de caracteres con el texto que se quiera mostrar.
Si colocamos un número distinto a 1, el resultado sería parecido a este:
Numero: 50
Traceback (most recent call last):
File "D:/PROYECTOS_PROGRAMACION/Python/CursoN2/Excepciones/ExcepcionesPropias.py", line 15,
in <module>
raise Propia()
__main__.Propia: Ha ocurrido un error. Código de error: 0
Nota: Si esta clase llamada Propia, tuviera otros atributos y métodos, se pueden usar desde el except,
como información de contexto. Actualmente, solo se tiene acceso al atributo valor, pues no existe algún
otro.
Aparte, Qt genera excepciones propias y PyCharm no nos avisará cuando ocurran. Si estamos iniciando
en PyQt5, encierre en un bloque try ese código que hace que su programa termine sin razón y muestre el
texto de la excepción en la salida estándar. Este es un consejo valioso si no quiere pasar horas revisando
el código en busca de la razón por la que falló su código. Le pedimos por favor que no subestime esta
sugerencia.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 10
CENEAC - Programación con Python Nivel 2.
4. PROGRAMACIÓN ORIENTADA A
OBJETOS:
CLASES, MÉTODOS Y HERENCIA
Cuando hablamos de programación orientada a objetos (en adelante POO), hablamos de un paradigma que
cambia por completo, la manera usual de hacer las cosas en la programación procedimental. Se trata de un
paradigma orientado a la claridad del código a través de su división por paquetes y clases. En este sentido,
cada ente manipulable por el lenguaje es un objeto. Una variable, una constante o un método son ejemplos
perfectos de lo que es un objeto.
Hablar de POO es hablar de clases. Una clase es un modelo, una plantilla para la creación de un objeto.
Podemos reducir el concepto y pensar en una clase como un nuevo tipo de dato del que podemos crear
variables.
Intentemos ver esto desde otro punto de vista. Tomemos los papeles de un arquitecto que, en pleno auge
de su carrera, tiene en sus manos la construcción de un edificio imponente. Para ello, nuestro arquitecto
debe elaborar un plano que contenga todas las especificaciones de la estructura. Este plano fija todas las
directrices para la construcción del edificio. Si hacemos una analogía con nuestros menesteres, podemos
asociar este plano, con una clase, y al edificio (entidad física basada en el plano) con el propio objeto. De
la misma forma en la que la elaboración de un plano, no implica necesariamente, la existencia de un
edificio basado en él, la existencia de una clase, no implica la existencia de un objeto basado en ella.
Puede haber cualquier cantidad de objetos basados en una clase, por lo que evidentemente, antes de crear
el objeto, debe existir la clase que lo represente, pero no al revés.
Sabemos lo que es una clase. Pero no un objeto. Un objeto es una instancia de una clase. Es una entidad
que posee un estado y un comportamiento determinado. El estado de un objeto, varía en función de los
atributos que tenga su clase y su comportamiento será el que establezcan los métodos de la misma.
def sumar(self):
return self.op1 + self.op2
def restar(self):
return self.op1 - self.op2
def multiplicar(self):
return self.op1 * self.op2
def dividir(self):
if not self.op2:
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 11
CENEAC - Programación con Python Nivel 2.
En el ejemplo anterior, se crea una clase llamada Calculadora. Esta clase tendrá dos atributos. Los
atributos de una clase, son variables declaradas adentro de ella y en nuestro caso, son Op1 y Op2
respectivamente. Cada uno de ellos, inicializado en cero.
Luego de los atributos hay cuatro funciones. De ahora en adelante, los llamaremos métodos, por estar
adentro de una clase. Estos métodos definen el comportamiento de un objeto basado en esa clase. Estos
métodos regresan un valor igual al resultado de la operación aritmética que representan. Así, suma,
regresa la adición de los dos atributos de la clase, resta devuelve la substracción, etc.
Prestemos especial atención a dos cosas. Primero, note que usamos la palabra self como primer parámetro
del método y luego, la usamos antes de los nombres de los atributos, para poder acceder a ellos. Esto es
porque cuando creamos atributos en una clase y usamos solo su nombre en un método, realmente no
estamos accediendo al atributo, sino creando una nueva variable con ese nombre, que será visible solo
para el método. Por ende, para diferenciar variables locales, de los atributos de la clase, cuando éstos
tienen el mismo nombre, se usa la palabra self, seguida de un punto y luego, el nombre del miembro de la
clase al que queremos acceder.
En cuanto al parámetro, es obligatorio que los métodos de una clase tengan a self como primer parámetro.
Esto no es solo una cuestión formal. Self está allí para cuando se quiera llamar al método sin utilizar
el objeto que lo contiene. De ser así, debe especificarse el parámetro self antes que el resto de los
parámetros. En todo caso, self contendrá una referencia a la propia clase, para poder acceder a los
atributos y métodos del objeto. Si se quiere llamar a un método de una clase, desde un objeto existente,
puede omitirse el parámetro self.
Como segunda aclaratoria, tenemos a raise. Es una palabra que lanza una excepción que, de no ser
capturada, termina súbitamente el programa con el mensaje y motivo que elijamos. En este caso, el error
es que la división por cero no está definida y por ende, no podemos mostrar un resultado certero, así que
lanzamos la excepción para que la persona que usó nuestra clase, pueda responder adecuadamente a ella.
Por último, se muestra la forma correcta de crear un objeto a partir de una clase. Se escribe el nombre de
la variable y luego del operador de asignación, se escribe el nombre de la clase, seguido de una pareja de
paréntesis. De esta forma, tenemos un objeto creado, con el nombre de la variable.
Para acceder a los miembros del objeto, se utiliza un punto. Escribimos el nombre del objeto, un punto y
luego el atributo o método al que quiero acceder.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 12
CENEAC - Programación con Python Nivel 2.
clase. Claro, esto no impide que otra clase pueda usar atributos o métodos declarados de esta forma, pero
sirve como indicativo para evitar que suceda.
def area_cuadrado(self):
return self.d1 * self.d2
def area_circulo(self):
return math.pi * pow(self.d1, 2)
def area_rectangulo(self):
return self.d1 * self.d2
def area_triangulo(self):
return (self.d1 * self.d2) / 2
def funcion_no_definida(self):
pass
En el ejemplo anterior podemos ver la declaración de un método para el que aún no existe una definición,
o cuerpo. También obsérvese el uso del paquete math, para usar la constante PI.
4.4. Constructores
Son métodos llamados automáticamente cuando se crea un nuevo objeto de una clase. Estos métodos son
muy útiles y su finalidad incluye, pero no se limita a:
- Darle un valor válido a cada atributo de la clase.
- Obligar al usuario de esta clase, a pasarle todos los datos que necesita para funcionar.
Para indicarle a Python que un determinado método es un constructor, debemos llamarlo __init__:
Ejemplo 9: Creación de constructores
class A:
lista = []
def __init__(self, p):
self.lista = p
def mostrar_lista(self):
for i in self.lista:
print (i)
En esta clase hay un constructor que recibe un parámetro llamado p. Cuando una clase no define un
constructor propio, Python le crea uno por defecto, sin parámetros y sin sentencias, solo para permitirnos
la creación de un objeto de la siguiente manera:
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 13
CENEAC - Programación con Python Nivel 2.
nuevo_objeto = NombreClase()
Sin embargo, cuando una clase define un constructor (como en el ejemplo), no hay constructor por
defecto, y si el constructor propio no puede recibir cero parámetros, es obligatorio pasarle al objeto, una
lista de parámetros tal, que coincida con la lista de parámetros solicitado por el constructor propio. En el
ejemplo anterior, estamos obligados a pasar un parámetro al constructor para evitar un error del intérprete.
Ampliemos el ejemplo anterior un poco:
Ejemplo 10: Constructores con parámetros
class A:
def __init__(self, p1, p2=-1):
if p2 != -1:
self.lista = [p1] * int(p2)
elif type(p1) is list or type(p1) is tuple:
self.lista = list(p1)
else:
print("ERROR, tipo de p1 es", type(p1))
return
print("Lista:\n", self.lista)
Antes de explicar la parte de este ejercicio que nos concierne, debemos aclarar un par de cosas. Primero
está el uso de type. Esta función nos regresa el tipo de la variable. Si usamos el operador is con él,
podemos compararlo con un tipo conocido. La sentencia if que la utiliza, puede ser interpretada como “Si
el tipo de p1 es lista, o el tipo de p1 es tupla, entonces…”. Y es así, en caso de que p1 sea de alguno de
esos dos tipos, creamos una nueva lista en el atributo homónimo de esa clase. Esto se hace para evitar
conversiones inválidas.
El segundo parámetro del método es por defecto, un entero. Si el constructor es llamado con un solo
parámetro, éste intentará copiar en una lista, los elementos de este parámetro. Si se le pasan dos
parámetros, entonces intentará crear una lista nueva de tantos elementos como indique p1, y cada uno de
esos elementos será igual a p2. Es decir, si los parámetros suministrados al método son 5 y 4, al imprimir
la lista, obtendremos una lista de cuatro elementos, llena de números cinco. La idea es multiplicar una lista
con un único elemento (el cinco) por cuatro. Esto se logra con la siguiente sentencia:
[ elemento ] * cantidad
De seguir siendo 5 y 4, los enteros suministrados, la lista sería:
[5, 5, 5, 5]
Ahora, en el ejemplo anterior se indican las formas válidas e inválidas de llamar al constructor. El
constructor se llama al crear el objeto. Veamos el resultado con cada una de las llamadas:
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 14
CENEAC - Programación con Python Nivel 2.
4.5. Herencia
Es una facultad que tienen las clases de poder utilizar como propios, los métodos y atributos de una o más
clases. Esto es importante para reutilizar código existente y evitar su reescritura. La herencia es uno de los
pilares de la POO. Su uso es universal en todos los lenguajes considerados orientados a objetos. Acá
explicaremos su uso.
Recordemos el ejemplo del arquitecto. Este profesional logró construir exitosamente el edificio y con base
en su éxito, recibe nuevas ofertas de empleo en las que debe construir edificios similares, pero no iguales
al primero que levantó. El nuevo edificio consiste en uno igual al anterior, pero con una piscina en el
último piso y un par de salones de fiesta en la planta baja. ¿Debería el arquitecto, elaborar un nuevo plano
desde cero para esta nueva obra? La respuesta es no. El plano anterior sirve, pues el edificio nuevo está
basado en el antiguo, solo que con varias modificaciones.
Entonces, si lo que se busca es eficiencia y reducción de costos, se utiliza el plano anterior y se le añaden
las modificaciones pertinentes. La creación del nuevo edificio consiste en la construcción del edificio
anterior y adicionalmente, en una piscina y dos salones de fiesta. De esta forma, solo se tuvo que elaborar
planos para estos objetos y no para el edificio entero. Establezcamos de nuevo una analogía de este
ejemplo, con la programación orientada a objetos, el plano viejo sería la clase base (también llamada
padre), y la subclase (o clase hija) sería el plano nuevo. De la misma forma en la que éste último, solo
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 15
CENEAC - Programación con Python Nivel 2.
debe contener la piscina y los dos salones de fiesta, la clase hija solo debe tener los métodos y atributos
inherentes a ella y no los de la clase base, pues al heredar de ella, ya los contendrá de forma implícita.
Veamos un ejemplo práctico a continuación, donde tenemos una clase llamada Animal y de ella heredarán
varias clases.
Ejemplo 11: Uso de herencia en Python
class Animal:
hábitat = ""
cría = "vivíparo"
class Ave(Animal):
color_alas = ""
altura_maxima = ""
class Pez(Animal):
profundidad_maxima = -500
respiración = "branquial"
class Mamífero(Animal):
cantidad_mamas = 4
class Perro(Mamífero):
raza = ""
nombre = ""
color_pelaje = ""
class Gato(Mamífero):
raza = ""
nombre = ""
tamaño = 0
atún = Pez()
atún.hábitat = "Acuático"
atún.cría = "Ovíparo"
Una clase que hereda de otra, debe especificar entre paréntesis, una o más clases (si son varias, separarlas
por comas), de las cuales quiere tomar todos sus atributos y métodos. Al hacerlo, esta clase hija contendrá
un conjunto de métodos y atributos heredados de otras clases, más los suyos propios. Cuando una clase
hereda de otra, y esta otra hereda a su vez, de una clase más, la clase hija contendrá los métodos y
atributos de su clase base y de toda la jerarquía a la que ésta pertenezca.
Volviendo al ejemplo anterior, la jerarquía de clases completa sería la siguiente:
Ave
Gato
Animal Mamífero
Perro
Pez
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 16
CENEAC - Programación con Python Nivel 2.
¿Cómo sería nuestra experiencia enfrente de un ordenador si los aplicativos que usamos con frecuencia
operaran siempre por líneas de comandos? ¿Qué éxito tendría una aplicación moderna destinada a
usuarios finales si ésta no tuviera una interfaz gráfica? Las respuestas a ambas preguntas compiten por ser
la más desalentadora. Es natural, e incluso imperativo que el atractivo de una aplicación, vaya de la mano
con su popularidad, por lo que en este manual veremos cómo aplicar en nuestras creaciones, diseños que
faciliten la comprensión y uso de las mismas.
Si bien, la creación de interfaces gráficas puede hacerse solo a código, o todo con un diseñador de GUI,
nosotros usaremos una combinación de ambos. Como bien se ha dicho, trabajaremos con QT Framework.
Es un conjunto de clases diseñadas originalmente para C++, pero que podemos usar en Python, sin
sacrificar rendimiento. Ahora, Python y PyQT deberán estar instalados en cada PC a la que queramos
distribuir nuestra aplicación, así que es bueno tenerlo en cuenta.
El diseñador que usaremos se llama Qt Designer y puede encontrarlo entre sus programas instalados. Qt
Designer le preguntará por el tipo de interfaz que desea crear. Seleccione Main Window y pulse Create. La
vista del programa será la siguiente:
La barra que está justo debajo del menú, es la barra de archivo y layout. No la usaremos más que para
guardar archivos, pero es muy útil para establecer el alineamiento automático de los controles, a la
ventana a la que pertenecen. Se sugiere investigar su uso.
La lista de la izquierda contiene todos los controles que Qt soporta. Los controles son componentes que
cumplen alguna función. Entre estos controles, están varios reconocibles por un usuario estándar, como
los campos de texto, botones, etiquetas, listas, etc.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 17
CENEAC - Programación con Python Nivel 2.
La ventana del centro es la ventana del diseñador, puede arrastrar cualquier control de la lista a la ventana
y posicionarlo donde prefiera. Ésta a su vez, también es un control, con eventos y propiedades
características.
Por último, tenemos a la derecha, tres ventanas acomodadas una debajo de otra. De arriba abajo, está el
inspector de objetos, donde aparecen todos los controles colocados en nuestra ventana, junto a su tipo y su
nombre. Para cambiar el nombre de un control, selecciónelo en el inspector y pulse F2.
Luego está el editor de propiedades. Vamos a darle un espacio mayor a esta herramienta, pues es
imprescindible un dominio de ella para poder culminar exitosamente una aplicación con GUI. Los objetos
gráficos en Qt, tienen propiedades. Una propiedad es una característica, o atributo de un objeto que
especifica la manera en la que éste se comportará.
De la misma manera en la que una persona tiene nombre, edad, sexo y dirección, una ventana en Qt tiene
ancho, alto, título, fuente, etc. Un campo de texto tiene fuente, color de texto, texto, ancho, alto, etc.
Cada una de esas características pueden ser editadas desde el código y su modificación repercute
directamente sobre el valor de los atributos de la clase en la que están basados, pero en el diseñador, la
cosa es más simple. Son campos que podemos modificar y si la propiedad está asociada a algo gráfico, los
cambios los podemos observar al instante. Por ejemplo, intente arrastrar un campo de texto (Line Edit) a
su ventana (en adelante, formulario), y cambie su propiedad “text” a un texto que usted desee. Al
abandonar la edición, notará que los cambios son aplicados inmediatamente.
Nota: Recuerde guardar el archivo .ui, antes de ejecutar el código Python, para que las últimas
modificaciones puedan ser ejecutadas también.
class Ventana(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("EjemploVentana.ui", self)
aplicacion = QApplication(sys.argv)
nueva_ventana = Ventana()
nueva_ventana.show()
sys.exit(aplicacion.exec())
Puede que, a simple vista, parezca algo confuso, pero luego de la explicación del código, todo quedará
mucho más claro.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 18
CENEAC - Programación con Python Nivel 2.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import uic
Primero incluimos en nuestro módulo, todos los otros módulos necesarios. sys contiene muchos métodos
útiles de la instancia que está corriendo. Como, por ejemplo, el método exit, que nos permite devolver un
valor al intérprete. Esto realmente no es necesario, pero es una buena costumbre. Del módulo QtWidgets,
necesitamos QApplication y QMainWindow. La primera es una clase que inicia, mantiene y gestiona una
instancia de una aplicación Qt, mientras que la segunda es una clase diseñada para representar una
ventana.
Como tercer import, uic, nos permite cargar archivos .ui a nuestro código Python.
class Ventana(QMainWindow):
Creamos una clase que herede de QMainWindow. Esto es una ventana personalizada, que contiene todos
los métodos y atributos de QMainWindow, pero con controles y métodos adicionales.
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("EjemploVentana.ui", self)
En el constructor de esta clase hija, tendremos dos sentencias. La primera llama explícitamente al
constructor de la clase base. Esto es para inicializar correctamente el objeto QMainWindow, que exige
obligatoriamente, una instancia de una clase como parámetro. Luego llamamos a loadUI. Este método se
encarga de cargar un archivo .ui y declarar en el código tantas variables como controles tengamos en el
formulario. En tal sentido, si en Qt Designer, colocamos un campo te texto y lo llamamos “txtTexto”,
tendremos una variable llamada “txtTexto” en nuestro código Python y sus métodos y atributos
disponibles, serán los de la clase correspondiente. Más adelante veremos esto a fondo.
aplicacion = QApplication(sys.argv)
Creamos una nueva aplicación Qt
nueva_ventana = Ventana()
Creamos una nueva ventana
nueva_ventana.show()
Mostramos la ventana creada
sys.exit(aplicacion.exec())
Lanzamos la aplicación, y con ella, el gestor de eventos para nuestra ventana. Mostrar la ventana no basta.
Ella necesita un hilo de ejecución encargado de procesar sus eventos y para ello, es el método exec().
Dependiendo del diseño dado a nuestro formulario en el diseñador, la ventana que se mostrará en pantalla,
es parecida a esta:
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 19
CENEAC - Programación con Python Nivel 2.
Nota: PyCharm ejecuta esta ventana de una forma limpia. Pero cuando ejecutamos el módulo desde el
explorador, aparece una ventana de comandos, junto a la ventana. Esto es porque, aunque el módulo
cargue una GUI, el programa aún es compatible con la línea de comandos. Para evitar esto, cambie la
extensión del archivo .py a .pyw y ya puede ejecutarlo sin una consola asociada.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 20
CENEAC - Programación con Python Nivel 2.
5.2. QMainWindow
Como dijimos en líneas anteriores, QMainWindow es la clase encargada de representar una ventana en Qt.
Crear una clase hija de ella, nos permite modificar esta ventana por defecto y adaptarla a nuestras propias
necesidades. QtMainWindow actúa como un contenedor de objetos. Esto implica que puede tener otros
controles adentro. Hay varios tipos de contenedores en Qt y el primero que veamos será este, por ser
indispensable en el desarrollo de una GUI. Veamos algunas de sus propiedades (Visibles en Qt Designer).
PROPIEDAD DESCRIPCIÓN
objectName Especifica el nombre del objeto. Este nombre será el que se
mostrará en el inspector de objetos y será el nombre que tendrá la
variable con la que se acceda a él.
windowModality Permite colocar la ventana en modo modal. Esto aplica solo para
aplicaciones que tengan múltiples formularios visibles a la vez.
Cuando un formulario se crea sobre otro y éste tiene
windowModal o applicationModal en esta propiedad, la ventana
que llamó a la nueva, no podrá ser utilizada hasta que esta última
sea cerrada.
enabled Si esta propiedad es True, el formulario podrá utilizarse
normalmente. Si no está marcada, no se podrá operar sobre el
formulario, ni sobre sus controles. No se podrá cambiar de
tamaño, ni mover, maximizar o minimizar. El formulario
permanece visible, pero inactivo.
geometry Permite cambiar el alto y ancho de la ventana en píxeles. También
permite ajustar la posición, pero en la vista de diseño, solo el alto
y ancho.
mínimumSize, maximumSize Ajustan cuál será el tamaño mínimo y máximo del formulario en
pixeles respectivamente. Cualquier tamaño menor al mínimo o
mayor al máximo, no es permitido.
font Permite elegir la el nombre, estilo y tamaño de la fuente que se
usará en el control
Nota: Cambiar cualquiera de estas propiedades, o de las otras no mencionadas, repercute directamente
en el comportamiento de la ventana cuando ésta sea ejecutada. Si cambió una propiedad en plan de
prueba, y no recuerda el valor que ésta tenía por defecto, no se preocupe. Cada propiedad tiene un
pequeño botón con una flecha roja en la parte derecha, que permite devolver la propiedad a sus valores
por defecto.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 21
CENEAC - Programación con Python Nivel 2.
Los botones son controles que le permiten al usuario, generar una acción cuando son pulsados. Hay varios
tipos de botones, los primeros tres que veremos, son los mencionados. En teoría, los tres son iguales en
funcionamiento; es decir, se pulsan y se genera un evento que será procesado y se tomará una acción
determinada. La diferencia con el primero (Command Link) es su apariencia, un poco más estilizada que
la del resto. El segundo (Push Button) es un botón corriente, y el tercero (Tool Button) está diseñado para
mostrar diálogos cuando se pulsa, aunque nada le impide comportarse como un Push Button. El control a
elegir en la mayoría de los casos, es un Push Button, pues es el indicado para la mayoría de las tareas.
Los botones, solo por ser objetos gráficos de QT, heredan muchas de las propiedades que ya hemos
descrito en QMainWindow, así que las que se repitan, no se colocarán nuevamente.
PROPIEDAD DESCRIPCIÓN
text Texto del botón
default (Solo Push y Cuando esta propiedad sea verdadera, el botón tendrá un aura azul,
Command Link) que indica que es el botón por defecto (Ver fig. 9). Cuando esto
suceda, al presionar ENTER, se pulsará el botón cambién. Es para
crear botones por defecto, y solo puede haber uno por formulario.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 22
CENEAC - Programación con Python Nivel 2.
Nota: Los colores del texto en los distintos controles se pueden cambiar ajustando los colores de la
propiedad Palette. Por defecto todos los controles comparten la paleta de colores del formulario al que
pertenecen. En tal sentido, al cambiar los colores del formulario, también se cambiarán los colores de
sus controles. Para tener colores distintos en cada control, modifique la paleta de colores de los mismos.
Pues éstos tienen precedencia sobre los del formulario.
Figura 10. Ejemplo de controles Radio Button, Check Box y Button Group
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 23
CENEAC - Programación con Python Nivel 2.
Nota: Si marca la casilla checked de un Radio Button, y la desmarca luego, la selección del control no
desaparecerá. Esto es porque una vez que se selecciona un Radio Button, ya no es posible
deseleccionarlo, a menos que se seleccione otro. Tenga eso en cuenta al momento de diseñar su
aplicación.
Figura 11. Ejemplo de Plain Text Edit, Text Edit y Line Edit
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 24
CENEAC - Programación con Python Nivel 2.
negros.
alignment (Solo Line Edit) Especifica si el texto estará centrado, hacia la derecha o
hacia la izquierda, tanto vertical como horizontal.
clearButtonEnabled (Solo Line Edit) Si se coloca en True, aparecerá un pequeño botón con
una “X” en la parte derecha del control. Si se pulsa, se
vacía el texto.
undoRedoEnabled (Solo Plain Text Edit Si esta propiedad es verdadera, se habilita el uso de
y Text Edit) Ctrl+Z y Ctrl+Shift+Z para deshacer y rehacer los
cambios realizados respectivamente.
lineWrapMode (Solo Plain Text Edit y Indica el comportamiento del texto cuando una línea de
Text Edit) éste es más larga que el ancho del control.
NoWrap: No sucede nada con el texto. Si las
barras horizontales están activas, se puede
acceder al texto oculto, desplazándolas.
WidgetWidht: Se ajusta el texto al ancho del
control.
tabChangesFocus (Solo Plain Text Edit Una propiedad interesante. Cuando se pulsa el botón
y Text Edit) Tab, por defecto se muestra una tabulación en el campo
de texto. Pero si esta propiedad está activa, al presionar
Tab, se cambia el foco del control al siguiente, tal cual
como si de otro control se tratase.
html (Solo Plain Text Edit y Text Edit) Indica el texto que tendrá el control. Este texto debe
estar en formato HTML si se quieren efectos.
acceptRichText (Solo Text Edit) Si es verdadero, se puede colocar texto enriquecido (con
formato) en el control, si es falso, no.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 25
CENEAC - Programación con Python Nivel 2.
Son controles elementales, pero indispensables para mostrar cualquier información en la ventana. Todo
texto mostrado en un Label será estático en un principio, es decir, no se podrá modificar, a no ser que
rompiendo con la esencia de un Label, el programador decida que el mismo pueda editarse.
Un Label no tiene muchas propiedades nuevas, pero tiene una en específico (textInteractionFlags) que
contiene a su vez, otras propiedades muy interesantes relativas a la forma en la que se comporta el texto de
la etiqueta con respecto al usuario, veamos las más relevantes de ellas:
PROPIEDAD DESCRIPCIÓN
TextSelectableByMouse Si está marcada, el texto del Label puede ser seleccionado
por el mouse.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 26
CENEAC - Programación con Python Nivel 2.
Un List Widget es un control que contiene una lista de ítems que el usuario puede seleccionar. Si la lista
de ítems es más larga que la cantidad de filas admitidas por el control, es usual que éste tenga una barra de
desplazamiento que nos permita visualizar los ítems restantes.
Estos controles son útiles para mostrar resultados de consultas en las que el usuario deba elegir una o más
opciones. Acá algunas de sus propiedades:
PROPIEDAD DESCRIPCIÓN
tabKeyNavigation Si esta propiedad está activa, al pulsar Tab, se cambiará al siguiente ítem
seleccionado y no al siguiente control (por defecto)
showDropIndicator Si esta propiedad está activada (por defecto), se pueden arrastrar ítems de
un lugar de la lista a otro lugar de la misma lista, u otro control
compatible.
alternatingRowColors Intercambia los colores de fondo de los ítems de la lista, tal cual como en
esta tabla.
selectionMode Configura la forma en la que los ítems pueden ser seleccionados:
NoSelection: No se puede seleccionar ningún ítem
SingleSelection: Solo se puede seleccionar un ítem.
MultiSelection: Se pueden seleccionar varios ítems. Si se selecciona
un ítem al inicio de la lista y se suelta el botón izquierdo del mouse y
luego se presiona sobre otro elemento, éste se seleccionará y los que
estaban seleccionados al inicio, se deseleccionan. Arrastrando el
puntero del mouse sobre los ítems, seleccionará varios.
ExtendedSelection: Igual que MultiSelection, salvo que una nueva
selección, no borra la anterior. Se pueden seleccionar todos los ítems
en cualquier orden.
ContinuousSelection: Al seleccionar un elemento, y luego
seleccionar otro, se seleccionan también, todos los ítems que haya
entre el primero y el segundo seleccionado. Esto garantiza siempre
una selección contigua.
sortingEnabled Los ítems se ordenarán a medida de que se vaya cambiando el contenido
del List Widget
viewMode Indica la vista de la lista, si se deja por defecto, queda como en la figura
14, sino, se organiza por íconos (en caso de que le hayamos cargado
algunos)
currentRow Indica el ítem que estará seleccionado por defecto
Nota: No hemos visto cómo agregar ítems a los controles List Widget. Esto es porque esta operación se
realiza en tiempo de ejecución, a través de código Python, que será tratado en el siguiente tema.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 27
CENEAC - Programación con Python Nivel 2.
Es otro de los controles ampliamente utilizados. El Combo Box, o lista desplegable, es similar a un List
Widget, solo que admite una única opción y en un principio está plegada. Estos controles son útiles en
aquellas situaciones en las que necesitemos una opción del usuario y tengamos poco espacio para colocar
una lista. Incluso con un espacio amplio, un Combo Box suele ser la opción más estilizada posible.
Estas son algunas de sus propiedades:
PROPIEDAD DESCRIPCIÓN
editable Si está activada, esta propiedad permite escribir sobre el Combo Box
como si fuera una línea de texto.
duplicatesEnabled Si esta propiedad está activa, se podrán colocar ítems con valores
idénticos en el control.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 28
CENEAC - Programación con Python Nivel 2.
Notas: Este fue un paseo por algunos de los controles más utilizados en el desarrollo de una GUI. Al igual
que con el List Widget, tampoco se ilustra por los momentos, la manera de agregar nuevos ítems en el
Combo Box.
Se le sugiere al lector, probar el resto de los controles, que no son pocos. Si necesita una orientación
acerca del uso de ellos, o de cualquier clase de PyQT, siéntase en la libertad de consultar la
documentación en línea de PyQT (en inglés):
http://pyqt.sourceforge.net/Docs/PyQt5/
o un curso muy completo de PyQT5, también en inglés:
https://programmica.com/builds/pyqt5-tutorial/pdf/PyQt5Tutorial.pdf
Tenga en cuenta una cosa. Nosotros (aquellas personas dedicadas a la redacción de material académico
de calidad, relativo a la programación y temas afines), nos damos a la tarea de poner a su disposición,
manuales como este que, si bien intentan abarcar todo un curso de creación de GUI y Bases de datos, no
tienen ánimos de cubrir las más de 300 clases de PyQT, por lo que la documentación oficial, siempre será
un referente para cualquier inquietud. La inmensa mayoría de la documentación de este y otros
lenguajes, así como las bibliotecas compatibles con ellos, está en idioma inglés, por lo que es aconsejable
su dominio, al menos a un nivel técnico.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 29
CENEAC - Programación con Python Nivel 2.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 30
CENEAC - Programación con Python Nivel 2.
Luego guardamos el archivo en el mismo directorio de nuestro archivo .pyw y ejecutamos el mismo
código que vimos antes, pero con algunas modificaciones, el nombre del archivo usado en esta guía para
este ejemplo es PruebaEvento.ui.
Ejemplo 13: Respuesta a eventos
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QEvent
from PyQt5 import uic
class Ventana(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("PruebaEvento.ui", self)
for i,j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
mi_ventana = Ventana()
mi_ventana.show()
sys.exit(app.exec())
Bien, el código nuevo puede ser un poco confuso para aquellos que recién inician con la programación
orientada a eventos, pero antes de que el pánico nos invada, expliquemos cada parte del ejemplo anterior.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QEvent
from PyQt5 import uic
Acá gestionamos las importaciones a nuestro módulo principal. Necesitamos a sys, para operar sobre los
argumentos de nuestro programa, los métodos de salida, etc. QtWidgets contiene las clases de los
controles de Qt. Muy útil. De QtCore tomaremos QEvent, que contiene una lista de enteros
correspondientes a cada uno de los eventos soportados por Qt. Y uic, para cargar la GUI.
class Ventana(QMainWindow):
def __init__(self):
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 31
CENEAC - Programación con Python Nivel 2.
QMainWindow.__init__(self)
uic.loadUi("PruebaEvento.ui", self)
Hasta aquí el código del constructor del Widget central, queda igual que el ejemplo que vimos con
anterioridad. Se llama al constructor de la clase base (QMainWindow) y luego cargamos la interfaz
gráfica desde un archivo. La llamada a loadUI también declara todas las variables locales necesarias para
operar sobre los controles que declaramos en Qt Designer.
for i,j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
Nota: Instalar un filtro de eventos solo para los controles que lo usarán, puede tener una ventaja de
rendimiento; sobre todo cuando la cantidad de controles es grande y no necesitamos manejar los
eventos de todos ellos. Si usa una gran cantidad de controles, quizás deba considerar añadir filtros para
ellos, uno por uno y solo para aquellos que lo requieran.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 32
CENEAC - Programación con Python Nivel 2.
Nota: Cuando el código de respuesta a un evento, sea mayor a 5 líneas de código, es recomendable,
colocarlo en un método de la clase y llamarlo desde el filtro de eventos. Esto es para evitar el código
spaghetti y ordenar mejor nuestro proyecto, por lo que se sugiere que, desde la etapa de planificación,
se tenga esto en mente: no contaminar el gestor de eventos y colocar allí, solo el mínimo código
necesario para que todo funcione.
FocusLost Es generado cuando un control pierde el foco. Esto sucede cuando otro
control lo toma.
Close Aplica para ventanas. Se genera cuando éstas se cierran.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 33
CENEAC - Programación con Python Nivel 2.
Hide También aplica para ventanas. Cuando ésta se minimiza, o se oculta por
código, se lanza este evento.
HoverEnter Se genera cuando el puntero del mouse entra en el área visible del
control.
Métodos:
pos(): Devuelve un objeto QPoint que contiene las coordenadas
X e Y, correspondientes a la posición exacta del puntero del
mouse con respecto al control. Para acceder a las coordenadas
del QPoint, puede escribir:
x = evento.pos().x()
y = evento.pos().y()
Teclas especiales (Ctrl, Alt, Alt Gr, teclas de función, etc) generan
eventos KeyPress. Cuando se pulsa una combinación de ellas, se genera
un evento KeyPress por cada nueva tecla presionada. En tal sentido,
Ctrl+Alt+A, genera tres eventos KeyPress.
Métodos:
key(): Tecla que fue pulsada. Este método devuelve un entero
que será igual a cualquiera de las constantes definidas en la clase
Qt (Módulo QtCore) que inicien con Key_.
text(): El texto introducido en el evento. Si es un caracter
imprimible y visible (Letras, símbolos o números), este método
lo devolverá. Si es un caracter imprimible pero no visible (saltos
de línea, backspaces, retornos de carro, etc), el método lo
devuelve, pero tenga cuidado si su plan es concatenarlos, pues el
resultado puede no ser el esperado. Si es una tecla no
imprimible, devuelve una cadena vacía.
modifiers(), indica si un modificador está pulsado al mismo
tiempo que la tecla del evento (que también puede ser un
modificador). Para ello puede hacer uso de las constantes
definidas en la clase Qt:
o ShiftModifier (Tecla Shift)
o ControlModifier (Tecla Ctrl)
o AltModifier (Tecla Alt)
o MetaModifier (Tecla Meta, o Windows®)
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 34
CENEAC - Programación con Python Nivel 2.
KeyRelease Se genera cuando una tecla fue soltada. Los métodos de este evento son
iguales a los de KeyPress.
MouseButtonRelease Se genera cuando se suelta el botón del mouse. Los métodos de este
evento son iguales a los del evento MouseButtonPress.
MouseButtonDblClick Se genera cuando se hace doble clic en un control. Los métodos de este
evento son iguales a los del evento MouseButtonPress.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 35
CENEAC - Programación con Python Nivel 2.
Paint Se genera cuando una porción de la ventana necesita ser repintada. Esto
puede pasar por varios motivos (se muestra la ventana, se oculta un
menú, se mueve un control, se mueve la ventana, se mueve una ventana
que está encima de la nuestra… etc.).
Métodos:
rect(): Devuelve un QRect con la porción de la ventana a ser
repintada. QRect tiene tres métodos que nos pueden ayudar a
saber la posición exacta:
o x(): Coordenada X de la esquina superior izquierda de la
región.
o y(): Coordenada Y de la esquina superior izquierda de la
región.
o widht(): Ancho de la región.
o height(): Alto de la región.
Wheel Se genera cuando se acciona la rueda del ratón (no el botón central)
hacia arriba o hacia abajo. El evento comparte los métodos de
MouseButtonPress.
Métodos:
delta(): Este método devuelve un entero que será positivo si se
desplazó la rueda hacia arriba, o un valor negativo si se
desplazó hacia abajo.
Nota: En la parte final de esta guía aparecen abundantes ejemplos acerca del uso de eventos.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 36
CENEAC - Programación con Python Nivel 2.
A continuación, una lista de los métodos más utilizados para los controles que hemos visto. Estos métodos
están disponibles para objetos de tipos específicos y tipos derivados de éstos. Por ejemplo, un método que
esté disponible para un control QMainWindow, también lo estará para todas aquellas clases creadas como
hijas de QMainWindow. QWidget engloba todos los controles (Ventanas incluidas), etc.
MÉTODO CLASES DESCRIPCIÓN Y USO
setTitle(titulo) QMainWindow Cambia el título de una ventana. Recibe una
cadena con el nuevo texto, como primer
parámetro.
showMinimized() QMainWindow Minimiza la ventana.
showMaximized() QMainWindow Maximiza la ventana.
showFullScreen() QMainWindow Expande la ventana a pantalla completa.
setNormal() QMainWindow Restaura la ventana a su tamaño original.
show() QMainWindow Muestra la ventana.
hide() QMainWindow Oculta la ventana.
close() QMainWindow Cierra la ventana.
isMinimized() QMainWindow Devuelve true si está minimizada. False en
caso contrario.
isMaximized() QMainWindow Devuelve true si está maximizada. False en
caso contrario.
isFullScreen() QMainWindow Devuelve true si está en pantalla completa.
False en caso contrario.
isHidden() QWidget Devuelve True si está oculto. False en caso
contrario.
isVisible() QWidget Devuelve True si está visible. False en caso
contrario.
hasFocus() QWidget Devuelve true si el control tiene el foco. False
en caso contrario.
height() QWidget Devuelve el alto del control, en píxeles.
width() QWidget Devuelve el ancho del control, en píxeles.
x() QWidget Devuelve la coordenada X, de la esquina
superior izquierda del control.
y() QWidget Devuelve la coordenada Y, de la esquina
superior izquierda del control.
resize(w, h) QWidget Cambia el tamaño del control o ventana. El
primer parámetro es el ancho, el segundo es el
alto.
setMaximumHeigth(n) QWidget Establece la altura máxima de un control.
Cualquier llamada a resize, con un valor de h,
mayor al pasado a esta función, funcionará
como si a dicho parámetro se le hubiera pasado
el valor máximo.
setMaximumWidth(n) QWidget Establece el ancho mínimo de un control Si se
llama a resize con un ancho mayor a este, el
ancho se adapta al máximo.
setMinimumHeight(n) QWidget Establece la altura mínima de un control.
setMinimumWidth(n) QWidget Establece el ancho mínimo de un control.
move(x, y) QWidget Cambia el Widget de posición. Puede recibir
move(pos) dos parámetros enteros (x e y) o un único
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 37
CENEAC - Programación con Python Nivel 2.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 38
CENEAC - Programación con Python Nivel 2.
self.texto.setAlignment(Qt.AlignVCenter |
Qt.AlignLeft)
setReadOnly(editable) Todos los campos de Si se le pasa True, como parámetro, el texto del
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 39
CENEAC - Programación con Python Nivel 2.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 40
CENEAC - Programación con Python Nivel 2.
self.lista.item(0).setText("Nuevo texto")
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 41
CENEAC - Programación con Python Nivel 2.
Nota: Si bien son muchos los métodos descritos acá, éstos no son más que una centésima parte de todos
los disponibles por todos los Widgets y otras clases no visibles. Se reitera la invitación a indagar en la
documentación de PyQt5 y si es entendido en C++, use la documentación oficial de Qt5.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 42
CENEAC - Programación con Python Nivel 2.
connection = pymysql.connect(host='localhost',
user='usuario',
password='contraseña',
cursorclass=pymysql.cursors.DictCursor)
cursor = connection.cursor()
sql = "CREATE DATABASE NombreBD"
cursor.execute(sql)
connection.commit()
connection.close()
Este es todo el código necesario para conectar Python con MySQL, crear una base de datos y cerrar la
conexión. Veamos la descripción de cada parte de este código:
import pymysql.cursors
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 43
CENEAC - Programación con Python Nivel 2.
Nota: Hay un parámetro llamado “db”, en el que debe suministrar un nombre de una base de datos a la
que el usuario que introdujo, tenga acceso. Solo por ser la primera vez que ejecutamos una conexión a
MySQL, se permite que no se pase este parámetro, pero ya que tenemos una base de datos creada, es
lógico suministrarla en el parámetro db para poder realizar modificaciones y consultas en ella.
cursor = conexion.cursor()
Se crea un nuevo cursor para la conexión
sql = "CREATE DATABASE NombreBD"
Creamos una cadena con la sentencia SQL a ejecutar
cursor.execute(sql)
Ejecutamos la sentencia
conexion.commit()
Guardamos los cambios en la base de datos
conexion.close()
Cerramos la conexión
7.3. Modificaciones
En SQL existen sentencias de modificación y consulta. Entre las sentencias de modificación, encontramos
a UPDATE, DROP, CREATE, INSERT, DELETE… etc. Las sentencias de modificación realizan
cambios en la base de datos y no regresan ningún resultado.
Al ejecutar una modificación, debemos subirla al servidor a través de un commit. Tenga en cuenta que esta
modificación puede fallar por diversos factores (Permisos de usuario insuficientes, errores de sintaxis,
identificadores inválidos, errores lógicos, conexión de red… etc.), y en caso de que esto suceda,
PyMySQL generará una excepción que, de no ser controlada, terminará abruptamente la ejecución de
nuestra aplicación. Ergo, es importante encerrar nuestras rutinas de acceso y modificación, en un bloque
try, en pro de evitar situaciones indeseadas.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 44
CENEAC - Programación con Python Nivel 2.
Para ejecutar una modificación, debemos iniciar sesión en el servidor, a través de un usuario y una
contraseña válidos, ejecutar las sentencias que deseemos, luego subir los cambios al servidor y cerrar la
conexión.
Ejemplo 15: Creación de una tabla en Python
import pymysql.cursors
connection = pymysql.connect(host='localhost',
user='ceneac',
password='clave',
db='ceneac',
cursorclass=pymysql.cursors.DictCursor)
cursor = connection.cursor()
try:
sql = """
CREATE TABLE clientes (
id INT NOT NULL AUTO_INCREMENT,
nombre VARCHAR(45) NOT NULL,
apellido VARCHAR(45) NOT NULL,
edad INT(3) NOT NULL,
rif VARCHAR(15) NOT NULL,
direccion VARCHAR(512) NULL,
PRIMARY KEY (id),
UNIQUE INDEX rif_u (rif ASC));
"""
cursor.execute(sql)
connection.commit()
except:
pass
finally:
connection.close()
Este código genera una nueva tabla en la base de datos llamada “ceneac”, siempre que ésta no exista. Note
que debe haber una base de datos con ese nombre para que la sentencia sea exitosa. La tabla tiene el
siguiente formato:
Columna Tipo Características
id Entero No puede ser NULL, clave primaria,
autoincrementable
nombre Alfanumérico No puede ser NULL
apellido Alfanumérico No puede ser NULL
edad Entero No puede ser NULL
rif Alfanumérico Único, no puede ser NULL
Dirección Alfanumérico
Si la ejecución de la sentencia no fue exitosa, se ejecutará el código debajo de except. En este caso no
hemos tomado acciones al respecto, pero de hacerlo, es allí donde debemos colocar el código necesario
para responder a los errores que pueda generar la sentencia SQL.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 45
CENEAC - Programación con Python Nivel 2.
Nota: Es recomendable que utilice comillas triples (""") en sus sentencias, para evadir el uso de
caracteres de escape innecesarios.
7.4. Consultas
Las consultas son un poco más complejas, pues son sentencias que devuelven algún tipo de contenido,
expresado en registros y columnas. Las sentencias que regresan datos, son SELECT, DESC (para
descripciones, no para ordenar), SHOW… etc.
Veamos cómo realizar consultas:
Ejemplo 16: Consultas a una base de datos desde Python
import pymysql.cursors
import pymysql.err
connection = pymysql.connect(host='localhost',
user='ceneac',
password='clave',
db='ceneac',
cursorclass=pymysql.cursors.DictCursor)
cursor = connection.cursor()
try:
sql = """
SELECT * FROM clientes WHERE edad > 22 ORDER BY apellido ASC
"""
cursor.execute(sql)
registro = cursor.fetchone()
while (registro != None):
print(registro['nombre'], registro['apellido'], registro['rif'])
registro = cursor.fetchone()
Hay varias cosas nuevas en este código, vamos a analizarlo línea por línea.
import pymysql.cursors
import pymysql.err
Incluimos otro módulo más, llamado “err”. Este módulo contiene la definición de errores de PyMySQL.
connection = pymysql.connect(host='localhost',
user='ceneac',
password='clave',
db='ceneac',
cursorclass=pymysql.cursors.DictCursor)
La conexión a la base de datos es idéntica.
cursor = connection.cursor()
try:
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 46
CENEAC - Programación con Python Nivel 2.
sql = """
SELECT * FROM clientes WHERE edad > 22 ORDER BY apellido ASC
"""
Se solicita una consulta a la tabla clientes, se tomarán todos aquellos cuya edad sea mayor a veintidós y se
ordenarán los resultados por apellido de forma ascendiente.
cursor.execute(sql)
Se ejecuta la consulta
registro = cursor.fetchone()
Se crea una nueva variable llamada registro y se le asigna el resultado de fetchone. Este método devuelve
un diccionario con un único registro. En este caso, el primero. Devuelve el diccionario y quita el registro
del cursor. Ahora registro contiene una fila completa. Cada clave de este diccionario, es el nombre de una
culumna de la base de datos. Es decir, si queremos obtener el valor del campo “dirección”, debemos usar:
Registro['direccion']
Ahora bien, si quisiéramos obtener no uno, sino todos los registros que coinciden con la consulta,
debemos usar fetchall. Este método nos devuelve una lista de diccionarios. Cada uno de los elementos de
la lista es un registro. Si solo queremos obtener algunos, usaríamos fetchmany. Este método recibe un
entero como parámetro, indicando la cantidad de registros que se tomarán de la consulta. Al igual que
fetchone, saca del cursor, todos los registros que se devolvieron. Si la consulta regresa con 1000 registros
y llamamos a fetchmany con 100, quedarían 900 en el cursor. Al igual que fetchall, regresa un diccionario
con las coincidencias
Nota: Cuidado con el uso de fetchall. Si la cantidad de registros es grande, puede tardar mucho tiempo la
consulta y gastar una enorme cantidad de recursos.
Si se llama a fetchone o a fetchall, y no hay registros para mostrar, la función regresa None.
finally:
connection.close()
Finalmente, cerramos la conexión con la base de datos.
Nota: None indica la ausencia de un valor determinado. Es compatible con todas las variables e indica un
identificador sin tipo ni valor.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 47
CENEAC - Programación con Python Nivel 2.
7.6. Cargar o crear una base de datos SQLite y operar sobre ella
El procedimiento no es muy distinto al utilizado en MySQL, por lo que son muy pocas las cosas nuevas
que tendremos que memorizar. El código utilizado para este fin es parecido al anterior, veamos un
ejemplo.
Ejemplo 17: Operar con SQLite desde Python
import sqlite3
conexion = sqlite3.connect("ejemplo.db")
cursor = conexion.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS Persona (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
nombre VARCHAR(45) NOT NULL,
apellido VARCHAR(45) NOT NULL);
""")
conexion.commit()
cursor.close()
conexion.close()
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 48
CENEAC - Programación con Python Nivel 2.
Nota: Puede escribir :memory: entre las comillas de la cadena suministrada a connect. Esto es para que
la base de datos resida en memoria y no en disco. Todo cambio realizado a ella, se perderá una vez
culminado el programa.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 49
CENEAC - Programación con Python Nivel 2.
Manual de programación en
Ejemplos y ejercicios
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 50
CENEAC - Programación con Python Nivel 2.
8. EJEMPLOS RESUELTOS
En esta sección de la guía aprenderemos a través de ejemplos completos, algunas acciones de utilidad.
Como se podrá imaginar, Qt es mucho más grande que el contenido programático de este texto, por lo que
acá veremos la forma de realizar algunos algoritmos comunes a través de algunas sentencias que no hemos
tenido la oportunidad de revisar anteriormente.
En estos ejemplos encontrará clases, funciones y métodos nuevos y útiles para ciertas tareas.
Ejemplo 18: Solicitar 5 números en 5 campos de texto y calcular su promedio.
Requisitos: crear un QMainWindow, con cinco campos QLineEdit, llamados “n1”, “n2”, “n3”, “n4” y
“n5”. Un QPushButton llamado “calcular” y un QLabel llamado “resultado”.
Código:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import uic
class Ventana(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("Ejemplo18.ui", self)
for i, j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
def obtener_promedio(self):
num1 = int(self.n1.text())
num2 = int(self.n2.text())
num3 = int(self.n3.text())
num4 = int(self.n4.text())
num5 = int(self.n5.text())
return (num1 + num2 + num3 + num4 + num5) / 5
if __name__ == "__main__":
app = QApplication(sys.argv)
mi_ventana = Ventana()
mi_ventana.show()
sys.exit(app.exec())
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 51
CENEAC - Programación con Python Nivel 2.
Ejemplo 19: Mostrar las coordenadas actuales del cursor del mouse en la pantalla.
Requisitos: crear un QMainWindow con un QLabel llamado “coordenadas” con su propiedad
mouseTracking en True y agrandado para toda la ventana.
Código:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import uic
class Ventana(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("Ejemplo19.ui", self)
for i, j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
mi_ventana = Ventana()
mi_ventana.show()
sys.exit(app.exec())
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 52
CENEAC - Programación con Python Nivel 2.
class Secundario(QDialog):
def __init__(self, texto):
QDialog.__init__(self)
uic.loadUi("Ejemplo20b.ui", self)
self.texto.setText(texto)
class VentanaPrincipal(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("Ejemplo20a.ui", self)
for i, j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
mi_ventana = VentanaPrincipal()
mi_ventana.show()
sys.exit(app.exec())
Nota: Puede pasar cualquier objeto al constructor de un Diálogo. Éstos se utilizan para mostrar ventanas
adicionales a la principal. Por cada diálogo debe existir una clase que lo atienda, tanto como la tiene una
ventana QMainWindow.
Como sugerencia, le invito a separar cada clase que contenga una ventana, en un módulo distinto, en pro
de facilitar la lectura de su código.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 53
CENEAC - Programación con Python Nivel 2.
Ejemplo 21: La fórmula para convertir grados centígrados a grados Fahrenheit es:
. Escribir un programa que permita convertir temperaturas
ingresadas de ºC a ºF y viceversa a medida que se escribe.
class VentanaPrincipal(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("Ejemplo21.ui", self)
for i, j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
mi_ventana = VentanaPrincipal()
mi_ventana.show()
sys.exit(app.exec())
Nota: En este ejemplo se utiliza un control no tratado hasta ahora. Es poco común, pero para estos casos
es el indicado. QDoubleSpinBox es un control que sirve solo para almacenar números reales. No tiene
una propiedad llamada text pero tiene una llamada value que devuelve el valor contenido en el control y
este valor será de tipo real. Por su parte, setValue modifica el valor del control. Así, mientras el usuario
escriba en uno, se cambia el otro. Un ejemplo corto, pero muy útil e ingenioso.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 54
CENEAC - Programación con Python Nivel 2.
class VentanaPrincipal(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("Ejemplo22.ui", self)
self.centrar_ventana()
for i, j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
def centrar_ventana(self):
ancho_pantalla = QApplication.desktop().width()
alto_pantalla = QApplication.desktop().height()
ancho_ventana = self.width()
alto_ventana = self.height()
xdef = (ancho_pantalla // 2) - (ancho_ventana // 2)
ydef = (alto_pantalla // 2) - (alto_ventana // 2)
self.move(xdef, ydef)
Nota: La clase QApplication tiene un método llamado desktop que nos devuelve información sobre el
escritorio. Entre esta información, puede estar el ancho y alto de la pantalla, expresado en píxeles.
El resto es fácilmente comprensible. Se obtiene el alto y ancho de la pantalla, luego el de la ventana y
luego mediante cálculos simples, hallamos el centro para la ventana, teniendo en cuenta que las
coordenadas que se le pasarán a move, pertenecen a la esquina superior derecha de la ventana.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 55
CENEAC - Programación con Python Nivel 2.
Ejemplo 23: Cargar un archivo de texto desde el disco y mostrarlo. El archivo debe
seleccionarlo el usuario con un cuadro de diálogo.
class VentanaPrincipal(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("Ejemplo23.ui", self)
for i, j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
mi_ventana = VentanaPrincipal()
mi_ventana.show()
sys.exit(app.exec())
Otra clase importante: QFileDialog. Esta clase muestra en pantalla un diálogo para abrir o cerrar archivos.
El método que utilizamos es getOpenFileName. Éste muestra un diálogo para abrir archivos y podemos
personalizar el filtro del archivo y el título del diálogo desde sus parámetros.
El método nos devuelve una tupla con dos elementos. El primero es el archivo seleccionado con su
respectiva extensión y el segundo es solo la extensión del mismo. Se abre el archivo con el método open y
luego con read leemos el contenido entero, para posteriormente, guardarlo en un QPlainText.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 56
CENEAC - Programación con Python Nivel 2.
class VentanaPrincipal(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
uic.loadUi("Ejemplo24.ui", self)
self.layout = QVBoxLayout(self)
for i, j in vars(self).items():
if isinstance(j, QWidget):
j.installEventFilter(self)
self.lista.itemClicked.connect(self.ItemClick)
if __name__ == "__main__":
app = QApplication(sys.argv)
mi_ventana = VentanaPrincipal()
mi_ventana.show()
sys.exit(app.exec())
Nota: Este ejercicio no solo demuestra el uso de un control de lista. También ilustra cómo asociar un
evento de una lista a través del método connect. Cuando se hace esto, el método suministrado a connect
es llamado cada vez que ocurra el evento; en este caso, cuando se haga clic en un ítem.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 57
CENEAC - Programación con Python Nivel 2.
1. Realice una calculadora con las funciones matemáticas básicas y algunas otras de interés: Suma,
resta, multiplicación, división, módulo, potencia, raíz cuadrada y cúbica.
2. Haga un sistema de ingreso que permita acceder a las funciones del programa, solo cuando el
usuario se haya autenticado correctamente
3. Realice un programa que permita obtener la matriz inversa de una matriz NxM suministrada por el
usuario a través de cualquier método conocido.
4. Programe un editor de texto. Si utiliza QsciScintilla, puede tener resaltado de sintaxis.
5. Cree un programa de gestión de inscripciones. Éste debe tener ingreso de datos de nuevos
estudiantes, consulta de datos almacenados, modificación, eliminación y actualización de notas.
6. Realice un sistema de gestión de bases de datos, que permita acceder a las tablas de una base en
concreto y realizar consultas y cambios a petición del usuario
7. A cualquiera de los programas anteriores, agregue un sistema que permita almacenar las
configuraciones del mismo y que éstas persistan luego de cada ejecución.
8. Diseñe una interfaz sin barra de título, con algún diseño propio que la simule, y que, al arrastrar el
cursor sobre ella, se pueda desplazar la ventana, tal cual como si la barra de título existiera.
9. Lea a través de dos cuadros de texto, las coordenadas de una casilla de un tablero de ajedrez en la
que se encuentra un caballo y muestre en una lista, las coordenadas de las casillas a las que ese
caballo podría desplazarse en un turno. Puede utilizar varios QCheckBox para simular las casillas.
10. Simule un sistema de ventas de lotería. Genere un reporte en un archivo de texto, sobre todos los
números vendidos, día y fecha de la venta.
Material elaborado por CENEAC Producciones, C.A. Prohibida su reproducción total o parcial sin autorización del Autor. 58