Saltar al contenido

Curso de creación de GUIs con Qt. Capítulo 01: Qt, versiones y bindings

En el anterior capítulo preparamos las maletas (instalación de nuestras herramientas) para nuestro viaje por el mundo de las aplicaciones de escritorio usando Python y Qt. En este capítulo voy a intentar desenmarañar un poco lo que es Qt, PyQt, PySide, versiones,….

Índice:

[Los materiales para este capítulo los podéis descargar de aquí]

[INSTALACIÓN] Si todavía no has pasado por el inicio del curso, donde explico cómo poner a punto todo, ahora es un buen momento para hacerlo y después podrás seguir con esta nueva receta.

¿Hola, Mundo?

No, todavía no. Antes me voy a detener un momento a explicar una serie de cosas acerca de Qt, PyQt4, PyQt5, PySide y PySide2 y sus principales diferencias.

¿Qué es Qt y por qué hay tantas formas de acceder a Qt desde Python?

Qt

En la página oficial de Qt podemos leer el siguiente párrafo:

Qt is much more than just a cross-platform SDK – it’s a technology strategy that lets you quickly and cost-effectively design, develop, deploy, and maintain software while delivering a seamless user experience across all devices.

Cómo párrafo vendemotos está bien pero no nos dice mucho. Algo un poco más sustancial sería:

Qt es un marco de trabajo multiplataforma y escrito en C++ para hacer aplicaciones gráficas.

Es decir, es un framework para hacer GUIs (por las siglas en inglés de Graphical User Interfaces o Interfaces Gráficas de Usuario) que nos permite disponer de un montón de cosas útiles para crear GUIs sin mucho esfuerzo y que soporta las plataformas más extendidas (Windows, Linux, MacOS,…).

Qt está escrito en C++ y, por ello, necesitamos acceder al mismo usando unos bindings o puentes (no he encontrado mejor palabra para bindings) que nos permite comunicar nuestro código Python con el código de Qt escrito en C++.

Versiones de Qt

Ahora mismo existen versiones de Qt4.x y de Qt5.x. Qt4.x ya no se desarrolla más y todo el desarrollo va a la última versión de Qt5.x. Si decidiera comenzar una nueva herramienta usando Qt4.x estaría condicionado puesto que no obtendría nuevas funcionalidades, parches de seguridad,… La última versión de Qt4 es la 4.8 y salió en el 2011. Eso son unos cuantos siglos en el mundo tecnológico.

Mi recomendación sería que usárais las versiones de Qt5.x puesto que incluye muchas mejoras y cosas más modernas que no se pueden encontrar en Qt4.x.

Por otro lado, parece que Qt6 está a la vuelta de la esquina y el desarrollo de Qt for Python (PySide2) va a la par que el código en C++.

PyQt4, PySide, PyQt5, PySide2

Los puentes o bindings de los que he hablado más arriba no son únicos y hay varias formas de poder acceder a Qt desde Python.

Como habéis visto, también hay varias versiones de Qt. Vamos a ver en una tabla un resumen no muy riguroso de versiones, licencias,…:

BindingPythonQt¿En desarrollo?LicenciaComentarios
PyQt4CPython2 ≥ 2.7, CPython3 ≥ 3.5Qt = 4.x, Qt = 5.xNoGPLv3 o comercialAbandonado en favor de PyQt5. La última versión es la 4.12.3 lanzada el 31 de agosto de 2018. La última versión de Qt4 salió en 2011. Es más complejo de encontrar determinadas combinaciones.
PySideCPython2 ≥ 2.6, 3.2 ≤ CPython3 ≤ 3.4Qt ≤ 4.8.xNoLGPLAbandonado en favor de PySide2. La última versión de Qt4 salió en 2011.
PyQt5CPython ≥ 3.5Qt ≥ 5.6GPLv3 o comercialLos desarrolladores intentan que las versiones de PyQt5 vayan en sintonía con las de Qt. Si, por ejemplo, instalamos PyQt5 5.6.x, teóricamente, soportará versiones de Qt iguales o inferiores a 5.6.x.
PySide2CPython2 ≥ 2.7, CPython3 ≥ 3.5Qt ≥ 5.6GPL, LGPL o comercialEl proyecto también se conoce como “Qt for Python”. Las versiones de PySide2 van a la par que las versiones de Qt5. La mejor forma de estar actualizado es seguir su blog.

Muchas versiones, un poco lioso todo. Me surge la pregunta:

Ok, muy bien, ¿qué elijo?

Pues depende… Según mi opinión (sin entrar mucho en el tema de licencias, que es un poco más complejo que lo que comento en los siguientes puntos):

  • ¿Tienes código antiguo que mantener que dependía de Qt4.x, PyQt4/PySide? Mi opción sería ir con PyQt4 a no ser que tengas un problema de licencia y te convenga más usar PySide. Estás destinado a morir dando soporte a versiones antiguas que no recibirán mejoras y que pueden tener errores. Lo suyo sería que empezaras a portar el código a nuevas versiones de Qt, PyQt5/PySide2 y Python. El cambio no es tan drástico y se puede hacer de forma rápida.
  • ¿No tienes código antiguo que mantener y la GPLv3 o la licencia comercial no son problema? Sin duda usaría PyQt5 o PySide2. El segundo ya es estable a día de hoy.
  • ¿No tienes código antiguo que mantener, la GPLv3 es un problema y no tienes dinero para una licencia comercial? PySide2.

Uso de código Python compatible con PyQt4, PySide, PyQt5, PySide2

Gracias a gente maravillosa e inteligente existen bibliotecas que nos permiten trabajar con Qt olvidándonos un poco de tanto problema de versiones de bindings pythónicos de Qt. Estas bibliotecas nos permiten importar las cosas que necesitamos usando una API (Application Programming Interface) común.

En la siguiente tabla (prestada del README de Qt.py) tenéis algo de información sobre las diferentes bibliotecas de las que podríais hacer uso:

ProjectAudienceReference bindingLicensePEP8StandalonePyPICo-existence
Qt.pyFilmPySide2MITYesYesYesYes
jupyterScientificN/AN/AYesNoNoNo
QtPyScientificN/AMITNoYesYesNo
pyqode.qtScientificPyQt5MITYesNoYesNo
QtExtFilmN/AN/ANoYesNoNo

En este curso voy a usar QtPy, desarrollada por la gente de Spyder-IDE. Por tanto, cualquier versión de PyQt5 o de PySide2 os debería funcionar sin problemas. En el capítulo anterior instalamos un entorno virtual donde estaban tanto la biblioteca PyQt5 como la biblioteca PySide2 instaladas.

Si tenemos instalado QtPy y PyQt5 y PySide2, como es nuestro caso, QtPy seleccona PyQt5 por defecto a no ser que le digamos otra cosa usando la variable de entorno QT_API. QT_API puede usar cualquiera de estos valores:

  • pyqt5 (para usar PyQt5).
  • pyqt o pyqt4 (para usar PyQt4).
  • pyside2 (para usar PySide2)
  • pyside (para usar PySide).

Pequeño ejemplo de uso de QtPy

Si usamos PyQt5 los módulos los importariamos así:

import sys
from PyQt5.QtWidgets import QApplication, QLabel
#...

Para el caso de PySide2 hemos de cambiar, básicamente, PyQt5 por PySide2:

import sys
from PySide2.QtWidgets import QApplication, QLabel
#...

Con QtPy no hemos de hacer cosas como lo siguiente para saber si tenemos instalado PyQt5 o PySide2:

import sys
try:
    from PySide2.QtWidgets import QApplication, QLabel
except ImportError:
    from PyQt5.QtWidgets import QApplication, QLabel
#...

Ya que podríamos hacer, simplemente:

import sys
import qtpy
from qtpy.QtWidgets import QApplication, QLabel

print(qtpy.API_NAME, qtpy.QT_VERSION, sep='; ')
#...

En el caso anterior estaría usando PyQt5 puesto que si tenemos varias bibliotecas de bindings instaladas, PyQt5 y PySide2 en nuestro caso, por defecto usa PyQt5, como he comentado más arriba. Los prints nos darían PyQt5; 5.12.3 (o la versión que tengáis instalada).

Si quisiera usar PySide2 he de establecer la variable de entorno QT_API, como he comentado más arriba:

import sys
import os
os.environ['QT_API'] = 'pyside2'
import qtpy
from qtpy.QtWidgets import QApplication, QLabel

print(qtpy.API_NAME, qtpy.QT_VERSION, sep='; ')
#...

En el caso anterior estaría usando PySide2 puesto que he establecido la variable de entorno de tal forma que use PySide2. Los prints nos darían PySide2; 5.13.1 (o la versión que tengáis instalada).

En mi caso voy a intentar usar PySide2 todo el rato por lo que incluiré las dos líneas siguientes al principio de los programas que lo requieran:

import os
os.environ['QT_API'] = 'pyside2'

Si, por la razón que sea, queréis usar PyQt5 eliminad esas dos líneas siempre que las veáis o importad las cosas usando PyQt5 en lugar de qtpy.

Terminando

Bueno, ahora parece que ya tenemos todo en orden para pasar a nuestro ‘Hola, Mundo’ donde crearemos nuestro primer GUI totalmente inútil pero que nos ayudará a empezar a ver una serie de conceptos.

Nos vemos en el siguiente capítulo.

P.D.: Si os surgen dudas, por favor, usad los comentarios.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

two + eight =

Pybonacci