10/12/2023
En el vasto universo de la programación, la capacidad de crear interfaces gráficas de usuario (GUI) intuitivas y funcionales es fundamental para el éxito de cualquier aplicación. Si eres un desarrollador Python y buscas construir herramientas de escritorio potentes y visualmente atractivas, PyQt es, sin duda, una de las opciones más destacadas. PyQt es un kit de herramientas de widgets GUI que actúa como una interfaz de Python para Qt, una de las bibliotecas GUI multiplataforma más robustas y populares del mundo. Desarrollado por RiverBank Computing Ltd., PyQt permite a los desarrolladores aprovechar toda la potencia de Qt directamente desde sus scripts de Python.

Este artículo te guiará a través de los aspectos esenciales de PyQt, desde su instalación hasta la creación de aplicaciones complejas, pasando por la gestión de eventos, el uso de herramientas de diseño y la integración con bases de datos. Prepárate para transformar tus ideas en programas de escritorio con una interfaz de usuario profesional.
- ¿Cómo Instalar PyQt?
- Explorando la API de PyQt: Módulos Esenciales
- Creando Tu Primera Aplicación GUI en PyQt: "Hola Mundo"
- Herramientas de Desarrollo PyQt5
- Jerarquía de Clases y Widgets Comúnmente Usados
- El Marco QMainWindow
- Diseñando GUIs con Qt Designer
- Manejo de Eventos: Señales y Slots
- Posicionamiento de Widgets y Gestión de Diseños
- Clases de Diálogo: QDialog y QMessageBox
- Interfaces de Documento Múltiple (MDI)
- Funcionalidad de Arrastrar y Soltar (Drag and Drop)
- Integración de Bases de Datos con QtSql
- Pintura y Gráficos con QPainter
- Funcionalidad del Portapapeles con QClipboard
- Manejo de Imágenes con QPixmap
- Personalizando la Apariencia: Cambiando el Color de la Ventana
- ¿Cómo Combinar Funciones Relacionadas con Python y PyQt?
- Preguntas Frecuentes sobre PyQt
¿Cómo Instalar PyQt?
La instalación de PyQt es un proceso sencillo, especialmente para los usuarios de Windows que utilizan Python 3.5 o posterior. La forma más recomendada y eficiente es a través del gestor de paquetes PIP (Python Package Installer).
Instalación en Windows
Para instalar la última versión estable de PyQt5, abre tu terminal o línea de comandos y ejecuta el siguiente comando:
pip3 install PyQt5Este comando descargará e instalará los paquetes necesarios para PyQt5, compatibles con arquitecturas de 32 o 64 bits. Para aquellos que deseen utilizar herramientas de desarrollo adicionales como Qt Designer (una herramienta visual para diseñar interfaces de usuario), se recomienda instalar también el paquete pyqt5-tools:
pip3 install pyqt5-toolsInstalación en Linux / macOS
Aunque PIP es la forma preferida para Windows, en sistemas operativos como Linux o macOS, también tienes la opción de compilar PyQt5 desde el código fuente. Esta opción, aunque más compleja, ofrece mayor flexibilidad y control sobre la instalación. Puedes encontrar los archivos fuente y las instrucciones detalladas en el sitio web oficial de RiverBank Computing.
Explorando la API de PyQt: Módulos Esenciales
La API de PyQt es una vasta colección de módulos, clases y funciones que proporcionan una amplia gama de funcionalidades. Cada módulo está diseñado para un propósito específico, lo que permite una organización y una gestión eficientes de las distintas características de la aplicación. A continuación, se detallan algunos de los módulos más utilizados:
| No. | Módulo | Descripción |
|---|---|---|
| 1 | QtCore | Clases principales no GUI utilizadas por otros módulos para funcionalidad básica. |
| 2 | QtGui | Componentes de la interfaz gráfica de usuario, incluyendo clases para dibujar, fuentes e imágenes. |
| 3 | QtWidgets | Clases para crear interfaces de usuario clásicas de escritorio, incluyendo la mayoría de los widgets. |
| 4 | QtMultimedia | Clases de programación multimedia de bajo nivel. |
| 5 | QtNetwork | Clases para programación en red. |
| 6 | QtOpenGL | Clases de soporte para OpenGL. |
| 7 | QtScript | Clases para evaluar scripts de Qt. |
| 8 | QtSql | Clases para integración de bases de datos usando SQL. |
| 9 | QtSvg | Clases para mostrar el contenido de archivos SVG. |
| 10 | QtWebKit | Clases para renderizar y editar HTML (en PyQt5, esto se ha movido a QtWebEngine). |
| 11 | QtXml | Clases para el manejo de XML. |
| 12 | QtDesigner | Clases para extender Qt Designer. |
| 13 | QtAssistant | Soporte para ayuda en línea. |
Principales Diferencias entre PyQt4 y PyQt5
Es importante señalar que la API de PyQt5 no es automáticamente compatible con versiones anteriores de PyQt4. Si estás migrando código, deberás realizar cambios manuales. Aquí te presentamos algunas de las diferencias más significativas:
- PyQt5 no es compatible con versiones de Python anteriores a la v2.6.
- El método
connect()de la claseQObjectpara la conexión entre señal y slot ha cambiado. La sintaxis anteriorQObject.connect(widget, QtCore.SIGNAL('signalname'), slot_function)ya no se utiliza. La nueva sintaxis eswidget.signal.connect(slot_function). - Las clases definidas previamente en el módulo
QtGuise han redistribuido entreQtGui,QtPrintSupportyQtWidgets. Esto significa que muchos widgets que antes importabas deQtGui, ahora los importarás deQtWidgets. - En la clase
QFileDialog, los métodosgetOpenFileNameAndFilter(),getOpenFileNamesAndFilter()ygetSaveFileNameAndFilter()han sido reemplazados porgetOpenFileName(),getOpenFileNames()ygetSaveFileName(), respectivamente. - PyQt5 no tiene disposición para definir una clase que sea subclase de más de una clase Qt.
- Las utilidades
pyuic5ypyrcc5han simplificado sus opciones, eliminando flags específicos de versiones de Python. - PyQt5 invoca automáticamente
sip.setdestroyonexit(), asegurando que los destructores C++ de las instancias envueltas se llamen al salir.
Creando Tu Primera Aplicación GUI en PyQt: "Hola Mundo"
Crear una aplicación GUI simple en PyQt es un excelente punto de partida para entender su funcionamiento. Aquí te mostramos cómo hacerlo con un ejemplo clásico de "Hola Mundo", tanto en un estilo procedural como en uno orientado a objetos.
Enfoque Procedural
Los pasos básicos para una aplicación simple son:
- Importar los módulos necesarios de PyQt5 (
QtCore,QtGui,QtWidgets). - Crear una instancia de
QApplication, que gestiona el bucle de eventos de la aplicación. - Crear un objeto
QWidget, que servirá como la ventana principal. - Añadir un widget como
QLabelpara mostrar texto. - Establecer el texto de la etiqueta y configurar la geometría (posición y tamaño) de la ventana.
- Mostrar la ventana.
- Entrar en el bucle principal de la aplicación con
app.exec_()para que la aplicación responda a los eventos.
Aquí tienes el código:
import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel def window(): app = QApplication(sys.argv) w = QWidget() b = QLabel(w) b.setText("Hello World!") w.setGeometry(100,100,200,50) b.move(50,20) w.setWindowTitle("PyQt5") w.show() sys.exit(app.exec_()) if __name__ == '__main__': window()Enfoque Orientado a Objetos
El enfoque orientado a objetos es el más recomendado para aplicaciones GUI, ya que permite una mejor organización y escalabilidad del código. Aquí, la ventana principal se define como una clase que hereda de QWidget.
import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel from PyQt5.QtGui import QFont class Window(QWidget): def __init__(self, parent = None): super(Window, self).__init__(parent) self.resize(200,50) self.setWindowTitle("PyQt5") self.label = QLabel(self) self.label.setText("Hello World") font = QFont() font.setFamily("Arial") font.setPointSize(16) self.label.setFont(font) self.label.move(50,20) def main(): app = QApplication(sys.argv) ex = Window() ex.show() sys.exit(app.exec_()) if __name__ == '__main__': main()Ambos códigos producirán una pequeña ventana con el texto "Hello World!" centrado.
Herramientas de Desarrollo PyQt5
PyQt5 no solo proporciona la biblioteca en sí, sino también un conjunto de utilidades que facilitan enormemente el proceso de desarrollo. Estas herramientas son esenciales para diseñar, traducir y compilar recursos de tu aplicación.
| No. | Herramienta | Descripción |
|---|---|---|
| 1 | assistant | Herramienta de documentación Qt Assistant, útil para consultar la API. |
| 2 | pyqt5designer | La herramienta de diseño de GUI de Qt Designer, una interfaz visual de arrastrar y soltar. |
| 3 | linguist | Herramienta de traducción Qt Linguist, para localizar tu aplicación. |
| 4 | lrelease | Compila archivos .ts (traducción) en archivos .qm (ejecutables). |
| 5 | pylupdate5 | Extrae cadenas de traducción y genera o actualiza archivos .ts. |
| 6 | qmake | Herramienta de construcción de software Qt. |
| 7 | pyqt5qmlscene | Visor de archivos QML. |
| 8 | pyqmlviewer | Otro visor de archivos QML. |
| 9 | pyrcc5 | Compilador de archivos de recursos Qt, para incrustar recursos como imágenes. |
| 10 | pyuic5 | Compilador de interfaz de usuario Qt para generar código Python a partir de archivos .ui. |
| 11 | pyqmltestrunner | Ejecuta pruebas unitarias en código QML. |
| 12 | qdbus | Herramienta de línea de comandos para enumerar servicios D-Bus. |
| 13 | QDoc | Generador de documentación para proyectos de software. |
| 14 | Qhelpgenerator | Genera y visualiza archivos de ayuda de Qt. |
| 15 | qmlimportscanner | Analiza e informa sobre importaciones QML. |
Jerarquía de Clases y Widgets Comúnmente Usados
La API de PyQt se construye sobre una jerarquía de clases bien definida, siendo QObject la clase base para todos los objetos Qt. QPaintDevice es la clase base para cualquier objeto que pueda ser pintado. La clase QApplication es el corazón de cualquier aplicación GUI, gestionando la configuración principal y el bucle de eventos.
La clase QWidget, derivada de QObject y QPaintDevice, es la clase base para todos los objetos de la interfaz de usuario. A partir de QWidget, se derivan otras clases fundamentales como QDialog y QMainWindow, que forman la base de las ventanas de tu aplicación.
Widgets de Uso Frecuente
PyQt ofrece una rica colección de widgets, cada uno con una funcionalidad específica. Aquí una lista selecta de los más utilizados:
| No. | Widget | Descripción |
|---|---|---|
| 1 | QLabel | Se usa para mostrar texto no editable o imágenes. |
| 2 | QLineEdit | Permite al usuario ingresar una línea de texto. |
| 3 | QTextEdit | Permite al usuario ingresar texto de varias líneas. |
| 4 | QPushButton | Un botón de comando para invocar una acción. |
| 5 | QRadioButton | Permite elegir una opción entre varias. |
| 6 | QCheckBox | Permite elegir entre una o más opciones. |
| 7 | QSpinBox | Permite aumentar/disminuir un valor entero. |
| 8 | QScrollBar | Permite acceder al contenido de un widget más allá de la pantalla visible. |
| 9 | QSlider | Permite cambiar un valor límite linealmente. |
| 10 | QComboBox | Proporciona una lista desplegable de elementos para seleccionar. |
| 11 | QMenuBar | Barra horizontal que contiene objetos QMenu. |
| 12 | QStatusBar | Generalmente en la parte inferior de QMainWindow, proporciona información de estado. |
| 13 | QToolBar | Generalmente en la parte superior de QMainWindow o flotante, contiene botones de acción. |
| 14 | QListView | Proporciona una lista seleccionable de elementos en modo Lista o Icono. |
| 15 | QPixmap | Representación de imágenes fuera de pantalla para mostrarlas en QLabel o QPushButton. |
| 16 | QDialog | Ventana modal o no modal que puede devolver información a la ventana principal. |
El Marco QMainWindow
La ventana de nivel superior de una aplicación GUI típica se crea con el objeto QMainWindow. Esta clase proporciona un marco de aplicación que tiene su propia barra de menú, barra de herramientas, barra de estado y un área central de widgets. Algunos widgets ocupan lugares designados en esta ventana principal, mientras que otros se colocan en el área central de widgets utilizando varios administradores de diseño.

Diseñando GUIs con Qt Designer
El instalador de PyQt incluye una herramienta de diseño de GUI llamada Qt Designer. Esta herramienta es invaluable porque permite construir interfaces gráficas de usuario de forma visual, arrastrando y soltando widgets sin necesidad de escribir código a mano. Aunque no es un IDE completo, simplifica enormemente el proceso de diseño.
Proceso de Diseño con Qt Designer
- Inicia Qt Designer (generalmente se encuentra en la carpeta
Scriptsde tu entorno virtual si lo instalaste conpyqt5-tools). - Comienza a diseñar tu interfaz eligiendo Archivo → Nuevo.
- Arrastra y suelta los widgets necesarios desde el cuadro de widgets en el panel izquierdo hacia tu formulario.
- Puedes asignar valores a las propiedades de los widgets directamente en el panel de propiedades.
- Guarda el formulario diseñado como un archivo
.ui(por ejemplo,demo.ui). Este archivo contiene una representación XML de tus widgets y sus propiedades.
Convertir Archivos .ui a Código Python
Una vez que tengas tu archivo .ui, puedes traducirlo a código Python utilizando la utilidad de línea de comandos pyuic5. Esta herramienta es un envoltorio para el módulo uic del kit de herramientas Qt.
pyuic5 -x demo.ui -o demo.pyEl modificador -x añade un pequeño fragmento de código adicional al script Python generado para que se convierta en una aplicación autocontenida y auto-ejecutable. El archivo demo.py resultante contendrá la estructura de tu interfaz de usuario en código Python, lista para ser utilizada en tu aplicación.
Manejo de Eventos: Señales y Slots
A diferencia de las aplicaciones de consola que se ejecutan de forma secuencial, las aplicaciones GUI están impulsadas por eventos. Esto significa que las funciones o métodos se ejecutan en respuesta a las acciones del usuario, como hacer clic en un botón, seleccionar un elemento o mover el ratón. Estas acciones son llamadas eventos.
Los widgets en PyQt actúan como fuentes de eventos. Cada widget de PyQt, que se deriva de la clase QObject, está diseñado para emitir una señal en respuesta a uno o más eventos. Una señal por sí sola no realiza ninguna acción; en cambio, está 'conectada' a un slot. Un slot puede ser cualquier función invocable de Python.
Conexión de Señales y Slots con Qt Designer
Qt Designer facilita la conexión de señales y slots visualmente:
- Diseña un formulario simple con un control
QLineEdity unQPushButton. - Activa el modo de edición de señales/slots (Editar → Editar señales/ranuras o presiona F4).
- Arrastra el cursor desde el botón hacia el cuadro de texto.
- Al soltar el ratón, aparecerá un cuadro de diálogo que muestra las señales del botón y los métodos de slot del cuadro de texto. Selecciona la señal
clicked()del botón y el métodoclear()del cuadro de texto. - Guarda el archivo
.uiy compílalo a Python conpyuic5. El código generado incluirá la conexión:self.pushButton.clicked.connect(self.lineEdit.clear).
Conexión de Señales y Slots por Código
También puedes establecer una conexión de señal/slot directamente en tu código Python utilizando la sintaxis:
widget.signal.connect(slot_function)Por ejemplo, para conectar el clic de un botón a una función:
import sys from PyQt5.QtWidgets import QApplication, QDialog, QPushButton def window(): app = QApplication(sys.argv) win = QDialog() b1 = QPushButton(win) b1.setText("Botón 1") b1.move(50,20) b1.clicked.connect(b1_clicked) b2 = QPushButton(win) b2.setText("Botón 2") b2.move(50,50) b2.clicked.connect(b2_clicked) win.setGeometry(100,100,200,100) win.setWindowTitle("Ejemplo PyQt5") win.show() sys.exit(app.exec_()) def b1_clicked(): print ("Botón 1 clicado") def b2_clicked(): print ("Botón 2 clicado") if __name__ == '__main__': window()Este ejemplo demuestra cómo conectar dos botones a funciones Python separadas, imprimiendo un mensaje en la consola cuando se hace clic en cada uno.
Posicionamiento de Widgets y Gestión de Diseños
Inicialmente, podrías pensar en posicionar widgets usando coordenadas absolutas (píxeles) con métodos como setGeometry(xpos, ypos, width, height). Sin embargo, este enfoque tiene varias desventajas:
- La posición del widget no cambia si se redimensiona la ventana.
- La apariencia puede no ser uniforme en diferentes dispositivos o resoluciones.
- Modificar el diseño es difícil, requiriendo a menudo rediseñar todo el formulario.
Para solucionar estos problemas, PyQt proporciona clases de diseño (Layout Managers) que gestionan el posicionamiento de los widgets de forma dinámica y elegante. Las ventajas de los administradores de diseño son:
- Los widgets dentro de la ventana cambian de tamaño automáticamente al redimensionar la ventana.
- Se garantiza una apariencia uniforme en diferentes resoluciones de pantalla.
- Es posible añadir o eliminar widgets dinámicamente sin necesidad de rediseñar.
Clases de Diseño Comunes
| No. | Clase de Diseño | Descripción |
|---|---|---|
| 1 | QBoxLayout | Alinea los widgets vertical u horizontalmente. Sus clases derivadas son QVBoxLayout (vertical) y QHBoxLayout (horizontal). |
| 2 | QGridLayout | Organiza los widgets en una cuadrícula de celdas dispuestas en filas y columnas. Permite añadir widgets especificando el número de fila y columna. |
| 3 | QFormLayout | Una forma conveniente de crear un formulario de dos columnas, donde cada fila consta de una etiqueta y un campo de entrada asociado. |
Clases de Diálogo: QDialog y QMessageBox
Las aplicaciones GUI a menudo necesitan interactuar con el usuario a través de ventanas de diálogo para recopilar información o mostrar mensajes importantes. PyQt ofrece clases específicas para esto.
La Clase QDialog
Un widget QDialog presenta una ventana de nivel superior utilizada principalmente para recopilar la respuesta del usuario. Puede configurarse para ser Modal (bloquea la interacción con la ventana principal hasta que se cierra) o Modeless (permite la interacción con otras ventanas mientras está abierta).
PyQt tiene varios widgets de diálogo preconfigurados, como InputDialog, FileDialog, FontDialog, etc. Un diálogo no tiene controles para minimizar y maximizar en su barra de título.
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QDialog def window(): app = QApplication(sys.argv) w = QWidget() btn = QPushButton(w) btn.setText("Mostrar Diálogo!") btn.move(100,50) btn.clicked.connect(showdialog) w.setWindowTitle("Demo de Diálogo PyQt") w.show() sys.exit(app.exec_()) def showdialog(): dlg = QDialog() b1 = QPushButton("OK", dlg) b1.move(50,50) dlg.setWindowTitle("Diálogo") dlg.setWindowModality(Qt.ApplicationModal) dlg.exec_() if __name__ == '__main__': window()En este ejemplo, el diálogo es ApplicationModal, lo que significa que el usuario no puede interactuar con la ventana principal hasta que se cierre el diálogo.
La Clase QMessageBox
QMessageBox es un cuadro de diálogo modal de uso común para mostrar mensajes informativos y, opcionalmente, pedir al usuario que responda haciendo clic en cualquiera de los botones estándar. Cada botón estándar tiene un título predefinido, una función y devuelve un número hexadecimal predefinido.

| No. | Método | Descripción |
|---|---|---|
| 1 | setIcon() | Muestra un icono predefinido (Question, Information, Warning, Critical). |
| 2 | setText() | Establece el texto principal del mensaje. |
| 3 | setInformativeText() | Muestra información adicional. |
| 4 | setDetailedText() | El cuadro de diálogo muestra un botón 'Detalles' para este texto. |
| 5 | setTitle() | Muestra el título personalizado del diálogo. |
| 6 | setStandardButtons() | Lista de botones estándar a mostrar (ej. QMessageBox.Ok | QMessageBox.Cancel). |
| 7 | setDefaultButton() | Establece el botón por defecto (se activa con Enter). |
| 8 | setEscapeButton() | Configura el botón que se activa al presionar Escape. |
import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox def window(): app = QApplication(sys.argv) w = QWidget() b = QPushButton(w) b.setText("Mostrar Mensaje!") b.move(100,50) b.clicked.connect(showdialog) w.setWindowTitle("Demo de MessageBox PyQt") w.show() sys.exit(app.exec_()) def showdialog(): msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("Este es un cuadro de mensaje") msg.setInformativeText("Esta es información adicional.") msg.setWindowTitle("Demo de MessageBox") msg.setDetailedText("Los detalles son los siguientes:...") msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) msg.buttonClicked.connect(msgbtn) retval = msg.exec_() def msgbtn(i): print ("Botón presionado es:", i.text()) if __name__ == '__main__': window()Interfaces de Documento Múltiple (MDI)
Mientras que los widgets con pestañas o apilados muestran una ventana a la vez, las aplicaciones MDI (Multiple Document Interface) permiten mostrar varias subventanas simultáneamente dentro de un contenedor principal. Esto es útil para aplicaciones que manejan múltiples documentos o vistas al mismo tiempo, como editores de texto o IDEs. El widget contenedor se llama QMdiArea, y las ventanas secundarias son instancias de QMdiSubWindow.
| No. | Método de QMdiArea/QMdiSubWindow | Descripción |
|---|---|---|
| 1 | addSubWindow() | Añade un widget como una nueva subventana en el área MDI. |
| 2 | removeSubWindow() | Elimina un widget que es un widget interno de una subventana. |
| 3 | setActiveSubWindow() | Activa una subventana. |
| 4 | cascadeSubWindows() | Organiza subventanas en el área MDI en cascada. |
| 5 | tileSubWindows() | Organiza las subventanas en el área MDI en mosaico. |
| 6 | closeActiveSubWindow() | Cierra la subventana activa. |
| 7 | subWindowList() | Devuelve la lista de subventanas en el área MDI. |
| 8 | setWidget() | Establece un QWidget como el widget interno de una instancia de QMdiSubwindow. |
import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import QApplication, QMainWindow, QMdiArea, QMdiSubWindow, QTextEdit, QAction class MainWindow(QMainWindow): count = 0 def __init__(self, parent = None): super(MainWindow, self).__init__(parent) self.mdi = QMdiArea() self.setCentralWidget(self.mdi) bar = self.menuBar() file = bar.addMenu("Archivo") file.addAction("Nuevo") file.addAction("Cascada") file.addAction("Mosaico") file.triggered[QAction].connect(self.windowaction) self.setWindowTitle("Demo MDI") def windowaction(self, q): print ("Acción disparada:", q.text()) if q.text() == "Nuevo": MainWindow.count = MainWindow.count+1 sub = QMdiSubWindow() sub.setWidget(QTextEdit()) sub.setWindowTitle("Subventana " + str(MainWindow.count)) self.mdi.addSubWindow(sub) sub.show() elif q.text() == "Cascada": self.mdi.cascadeSubWindows() elif q.text() == "Mosaico": self.mdi.tileSubWindows() def main(): app = QApplication(sys.argv) ex = MainWindow() ex.show() sys.exit(app.exec_()) if __name__ == '__main__': main()Funcionalidad de Arrastrar y Soltar (Drag and Drop)
La funcionalidad de arrastrar y soltar es muy intuitiva y se encuentra en muchas aplicaciones de escritorio, permitiendo al usuario copiar o mover objetos entre ventanas. La transferencia de datos de arrastrar y soltar basada en MIME se basa en la clase QDrag. Los objetos QMimeData asocian los datos con su tipo MIME correspondiente y se almacenan en el portapapeles para el proceso de arrastrar y soltar.
| Método de QMimeData | Tipo MIME | Descripción |
|---|---|---|
hasText() / text() / setText() | text/plain | Para texto sin formato. |
hasHtml() / html() / setHtml() | text/html | Para contenido HTML. |
hasUrls() / urls() / setUrls() | text/uri-list | Para listas de URLs. |
hasImage() / imageData() / setImageData() | image/* | Para datos de imagen. |
hasColor() / colorData() / setColorData() | application/x-color | Para datos de color. |
Los widgets que permiten que sus datos sean arrastrados deben tener setDragEnabled(True). Por otro lado, los widgets que deben responder a eventos de arrastrar y soltar implementan métodos para manejar DragEnterEvent (cuando un arrastre entra en el widget), DragMoveEvent (durante el arrastre), DragLeaveEvent (cuando el arrastre sale) y DropEvent (cuando se suelta el objeto).
import sys from PyQt5.QtWidgets import QApplication, QWidget, QComboBox, QLineEdit, QLabel, QFormLayout class Combo(QComboBox): def __init__(self, title, parent): super(Combo, self).__init__(parent) self.setAcceptDrops(True) def dragEnterEvent(self, e): if e.mimeData().hasText(): e.accept() else: e.ignore() def dropEvent(self, e): self.addItem(e.mimeData().text()) class Example(QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): lo = QFormLayout() lo.addRow(QLabel("Escriba texto en el cuadro y arrástrelo al combo box")) edit = QLineEdit() edit.setDragEnabled(True) com = Combo("Button", self) lo.addRow(edit, com) self.setLayout(lo) self.setWindowTitle('Arrastrar y Soltar Simple') def main(): app = QApplication(sys.argv) ex = Example() ex.show() app.exec_() if __name__ == '__main__': main()Integración de Bases de Datos con QtSql
La biblioteca PyQt5 incluye el módulo QtSql, un sistema de clases para comunicarse con diversas bases de datos SQL. Su clase QSqlDatabase proporciona acceso a través de un objeto de conexión. Esto permite que tu aplicación interactúe con bases de datos como SQLite, MySQL, PostgreSQL, Oracle y más.
| No. | Método de QSqlDatabase | Descripción |
|---|---|---|
| 1 | setDatabaseName() | Establece el nombre de la base de datos para la conexión. |
| 2 | setHostName() | Establece el nombre del host donde está instalada la base de datos. |
| 3 | setUserName() | Especifica el nombre de usuario para la conexión. |
| 4 | setPassword() | Establece la contraseña del objeto de conexión. |
| 5 | commit() | Confirma las transacciones. |
| 6 | rollback() | Revierte la transacción de la base de datos. |
| 7 | close() | Cierra la conexión. |
La clase QSqlQuery tiene la funcionalidad para ejecutar y manipular comandos SQL (DDL y DML). El método clave es exec_(), que toma una cadena SQL como argumento.
import sys from PyQt5.QtSql import QSqlDatabase, QSqlQuery from PyQt5.QtWidgets import QApplication, QMessageBox def createDB(): db = QSqlDatabase.addDatabase('QSQLITE') db.setDatabaseName('sportsdatabase.db') if not db.open(): msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("Error al crear la base de datos") retval = msg.exec_() return False query = QSqlQuery() query.exec_("create table sportsmen( id int primary key, ""firstname varchar(20), lastname varchar(20))") query.exec_("insert into sportsmen values(101, 'Roger', 'Federer')") query.exec_("insert into sportsmen values(102, 'Christiano', 'Ronaldo')") query.exec_("insert into sportsmen values(103, 'Ussain', 'Bolt')") query.exec_("insert into sportsmen values(104, 'Sachin', 'Tendulkar')") query.exec_("insert into sportsmen values(105, 'Saina', 'Nehwal')") return True if __name__ == '__main__': app = QApplication(sys.argv) createDB()Modelos de Tabla y Vistas (QSqlTableModel y QTableView)
Para mostrar datos de una base de datos en una GUI, PyQt utiliza el marco Modelo/Vista. QSqlTableModel proporciona un modelo de datos editable para leer y escribir registros en una sola tabla, y QTableView es un widget que muestra estos datos en una vista desplazable y editable.
import sys from PyQt5.QtSql import QSqlDatabase, QSqlTableModel from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QTableView, QDialog, QVBoxLayout, QPushButton def initializeModel(model): model.setTable('sportsmen') model.setEditStrategy(QSqlTableModel.OnFieldChange) model.select() model.setHeaderData(0, Qt.Horizontal, "ID") model.setHeaderData(1, Qt.Horizontal, "Nombre") model.setHeaderData(2, Qt.Horizontal, "Apellido") def createView(title, model): view = QTableView() view.setModel(model) view.setWindowTitle(title) return view def addrow(): print (model.rowCount()) ret = model.insertRows(model.rowCount(), 1) print (ret) def findrow(i): global delrow delrow = i.row() if __name__ == '__main__': app = QApplication(sys.argv) db = QSqlDatabase.addDatabase('QSQLITE') db.setDatabaseName('sportsdatabase.db') # Asegúrate de que la base de datos exista y esté creada createDB() # Llama a la función para crear la DB si no existe model = QSqlTableModel() delrow = -1 initializeModel(model) view1 = createView("Modelo de Tabla (Vista 1)", model) view1.clicked.connect(findrow) dlg = QDialog() layout = QVBoxLayout() layout.addWidget(view1) button = QPushButton("Añadir Fila") button.clicked.connect(addrow) layout.addWidget(button) btn1 = QPushButton("Eliminar Fila") btn1.clicked.connect(lambda: model.removeRow(view1.currentIndex().row())) layout.addWidget(btn1) dlg.setLayout(layout) dlg.setWindowTitle("Demo de Base de Datos") dlg.show() sys.exit(app.exec_())Pintura y Gráficos con QPainter
Todas las clases QWidget en PyQt son subclases de QPaintDevice, lo que significa que pueden ser dibujadas. La clase QPainter es la herramienta principal para realizar dibujos de bajo nivel en widgets y otros dispositivos pintables. Se utiliza típicamente dentro del método paintEvent() de un widget, que se invoca cada vez que la apariencia del widget necesita ser actualizada.
| No. | Método de QPainter | Descripción |
|---|---|---|
| 1 | begin() / end() | Inicia/finaliza la pintura en el dispositivo de destino. |
| 2 | drawArc() | Dibuja un arco. |
| 3 | drawEllipse() | Dibuja una elipse. |
| 4 | drawLine() | Dibuja una línea. |
| 5 | drawPixmap() | Dibuja un mapa de píxeles (imagen). |
| 6 | drawPolygon() | Dibuja un polígono. |
| 7 | drawRect() | Dibuja un rectángulo. |
| 8 | drawText() | Muestra texto en coordenadas dadas. |
| 9 | fillRect() | Rellena un rectángulo con un color o patrón. |
| 10 | setBrush() | Establece el estilo de pincel para rellenar formas. |
| 11 | setPen() | Establece el color, tamaño y estilo de la pluma para dibujar contornos. |
PyQt también define constantes para estilos de pincel y colores predefinidos, facilitando la personalización visual.
Constantes de Estilo de Pincel
Qt.NoBrush: Sin patrón de pincel.Qt.SolidPattern: Color uniforme.Qt.Dense1Pattern: Patrón de pincel extremadamente denso.Qt.HorPattern: Líneas horizontales.Qt.VerPattern: Líneas verticales.Qt.CrossPattern: Líneas horizontales y verticales cruzadas.Qt.BDiagPattern: Líneas diagonales hacia atrás.Qt.FDiagPattern: Líneas diagonales hacia adelante.Qt.DiagCrossPattern: Líneas diagonales cruzadas.
Objetos QColor Predefinidos
Qt.white,Qt.black,Qt.red,Qt.darkRed,Qt.green,Qt.darkGreen,Qt.blue,Qt.cyan,Qt.magenta,Qt.yellow,Qt.darkYellow,Qt.gray.
import sys from PyQt5.QtCore import Qt, QPoint from PyQt5.QtGui import QPainter, QColor, QFont, QPixmap, QBrush from PyQt5.QtWidgets import QApplication, QWidget class Example(QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): self.setGeometry(100,100, 400,300) self.setWindowTitle('Demo de Dibujo') self.show() def paintEvent(self, event): qp = QPainter() qp.begin(self) qp.setPen(QColor(Qt.red)) qp.setFont(QFont('Arial', 20)) qp.drawText(10,50, "Hola Python") qp.setPen(QColor(Qt.blue)) qp.drawLine(10,100,100,100) qp.drawRect(10,150,150,100) qp.setPen(QColor(Qt.yellow)) qp.drawEllipse(100,50,100,50) # qp.drawPixmap(220,10,QPixmap("pythonlogo.png")) # Asume que 'pythonlogo.png' existe en el mismo directorio qp.fillRect(20,175,130,70,QBrush(Qt.SolidPattern)) qp.end() def main(): app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_()) if __name__ == '__main__': main()Funcionalidad del Portapapeles con QClipboard
La clase QClipboard proporciona acceso al portapapeles de todo el sistema, lo que permite copiar y pegar datos entre diferentes aplicaciones. Su funcionamiento es similar a la clase QDrag, utilizando tipos de datos MIME.
| No. | Método de QClipboard | Descripción |
|---|---|---|
| 1 | clear() | Borra el contenido del portapapeles. |
| 2 | setImage() | Copia un QImage al portapapeles. |
| 3 | setMimeData() | Establece datos MIME en el portapapeles. |
| 4 | setPixmap() | Copia un objeto QPixmap al portapapeles. |
| 5 | setText() | Copia una cadena de texto al portapapeles. |
| 6 | text() | Recupera texto del portapapeles. |
La señal dataChanged() se emite cada vez que cambian los datos en el portapapeles.
import sys from PyQt5.QtWidgets import QApplication, QWidget, QTextEdit, QPushButton, QVBoxLayout, QMessageBox class Example(QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): hbox = QVBoxLayout() self.edit1 = QTextEdit() hbox.addWidget(self.edit1) self.btn1 = QPushButton("Copiar") hbox.addWidget(self.btn1) self.edit2 = QTextEdit() self.btn2 = QPushButton("Pegar") hbox.addWidget(self.edit2) hbox.addWidget(self.btn2) self.btn1.clicked.connect(self.copytext) self.btn2.clicked.connect(self.pastetext) self.setLayout(hbox) self.setGeometry(300, 300, 300, 200) self.setWindowTitle('Portapapeles') self.show() def copytext(self): clipboard.setText(self.edit1.toPlainText()) msg = QMessageBox() msg.setText(clipboard.text() + " copiado al portapapeles") msg.exec_() def pastetext(self): self.edit2.setText(clipboard.text()) if __name__ == '__main__': app = QApplication(sys.argv) clipboard = app.clipboard() ex = Example() ex.setWindowTitle("Ejemplo de Portapapeles") sys.exit(app.exec_())Manejo de Imágenes con QPixmap
La clase QPixmap proporciona una representación fuera de pantalla de una imagen, optimizada para mostrarse en la pantalla. Se puede utilizar como un dispositivo de pintura o cargarla en otros widgets como etiquetas (QLabel) o botones (QPushButton). PyQt también tiene la clase QImage, optimizada para E/S y manipulaciones de píxeles; ambos formatos son interconvertibles.

Tipos de Archivos de Imagen Soportados
- BMP (Mapa de bits de Windows)
- GIF (Formato de Intercambio Gráfico)
- JPG (Joint Photographic Experts Group)
- PNG (Gráficos de Red Portátiles)
- PBM (Mapa de bits portátil)
- PGM (Mapa de grises portátil)
- PPM (Pixmap portátil)
- XBM (Mapa de bits X11)
- XPM (Mapa de píxeles X11)
| No. | Método de QPixmap | Descripción |
|---|---|---|
| 1 | copy() | Copia datos de mapas de píxeles de un objeto QRect. |
| 2 | fromImage() | Convierte un objeto QImage en QPixmap. |
| 3 | grabWidget() | Crea un mapa de píxeles a partir del widget dado. |
| 4 | grabWindow() | Crea un mapa de píxeles de datos en una ventana. |
| 5 | load() | Carga un archivo de imagen como mapa de píxeles. |
| 6 | save() | Guarda el objeto QPixmap como un archivo. |
| 7 | toImage() | Convierte un QPixmap en QImage. |
import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout from PyQt5.QtGui import QPixmap def window(): app = QApplication(sys.argv) win = QWidget() l1 = QLabel() l1.setPixmap(QPixmap("python.png")) # Asegúrate de que 'python.png' exista en el mismo directorio vbox = QVBoxLayout() vbox.addWidget(l1) win.setLayout(vbox) win.setWindowTitle("Demo de QPixmap") win.show() sys.exit(app.exec_()) if __name__ == '__main__': window()Personalizando la Apariencia: Cambiando el Color de la Ventana
Para cambiar el color de fondo de una ventana o cualquier otro widget en PyQt, puedes utilizar el método setStyleSheet(). Este método permite aplicar estilos CSS (Cascading Style Sheets) directamente a los widgets, ofreciendo una gran flexibilidad para personalizar la apariencia de tu aplicación. Toma una cadena de texto como argumento, donde defines las reglas de estilo.
import sys from PyQt5.QtWidgets import QApplication, QWidget def window(): app = QApplication(sys.argv) w = QWidget() # Cambia el color de fondo de la ventana a un azul claro w.setStyleSheet("background-color: lightblue;") w.setGeometry(100,100,300,200) w.setWindowTitle("Ventana con Color") w.show() sys.exit(app.exec_()) if __name__ == '__main__': window()¿Cómo Combinar Funciones Relacionadas con Python y PyQt?
La verdadera potencia de PyQt reside en su capacidad para combinar las capacidades de la biblioteca Qt con la flexibilidad y simplicidad de Python. Esto se logra mediante la conexión de las señales emitidas por los widgets de PyQt a funciones o métodos Python personalizados (los slots). De esta manera, puedes escribir la lógica de tu aplicación en Python puro y hacer que interactúe directamente con la interfaz gráfica creada con PyQt. Por ejemplo, un clic en un botón (señal) puede disparar una función Python que realiza cálculos, accede a una base de datos o actualiza otro widget.
PyQt no es solo un envoltorio; es una integración profunda que permite a los desarrolladores de Python construir aplicaciones de escritorio complejas y de alto rendimiento que aprovechan al máximo el ecosistema de Qt. Al seguir un enfoque orientado a objetos, puedes encapsular la lógica de tu interfaz de usuario y la lógica de negocio de tu aplicación en clases separadas, lo que resulta en un código más organizado, mantenible y escalable.
Preguntas Frecuentes sobre PyQt
¿Qué es PyQt y para qué se usa?
PyQt es un conjunto de enlaces de Python para el framework de aplicaciones multiplataforma Qt. Se utiliza para crear interfaces gráficas de usuario (GUI) para aplicaciones de escritorio en sistemas operativos como Windows, Linux y macOS. Permite a los desarrolladores de Python construir aplicaciones visualmente ricas y funcionales.
¿Es PyQt gratuito?
PyQt tiene una licencia dual. Está disponible bajo la Licencia Pública General (GPL), lo que significa que es gratuito para proyectos de código abierto. Para proyectos comerciales o propietarios, se requiere una licencia comercial.
¿Cuál es la diferencia principal entre PyQt4 y PyQt5?
La diferencia más notable es la sintaxis de conexión de señales y slots (widget.signal.connect(slot_function) en PyQt5), la redistribución de clases entre módulos (por ejemplo, muchos widgets se movieron de QtGui a QtWidgets), y la eliminación del soporte para versiones muy antiguas de Python.
¿Necesito saber C++ para usar PyQt?
No, no necesitas saber C++ para usar PyQt. PyQt es una interfaz de Python para la biblioteca Qt, lo que significa que puedes usar todas las funcionalidades de Qt directamente desde Python. Sin embargo, tener una comprensión básica de los conceptos de Qt (como señales y slots) puede ser útil.
¿Puedo diseñar mi interfaz gráficamente sin escribir código?
Sí, puedes usar Qt Designer, una herramienta visual que viene con PyQt, para diseñar tu interfaz de usuario arrastrando y soltando widgets. Una vez que el diseño está completo, puedes guardar el archivo .ui y convertirlo a código Python usando la utilidad pyuic5.
¿Cómo manejo eventos de usuario como clics de botón?
En PyQt, los eventos se manejan utilizando el mecanismo de señales y slots. Los widgets emiten 'señales' cuando ocurre un evento (por ejemplo, un botón es clicado), y tú 'conectas' esas señales a funciones o métodos Python (los 'slots') que contienen la lógica que deseas ejecutar en respuesta al evento.
¿PyQt soporta bases de datos?
Sí, PyQt incluye el módulo QtSql, que proporciona clases para interactuar con diversas bases de datos SQL como SQLite, MySQL, PostgreSQL, y otras. Esto permite a tu aplicación PyQt almacenar y recuperar datos de manera eficiente.
Si quieres conocer otros artículos parecidos a PyQt: Creando Aplicaciones de Escritorio con Python puedes visitar la categoría Librerías.
