PyQt5 proporciona un conjunto robusto de herramientas para el desarrollo de interfaces gráficas de usuario (GUI) en Python. Este framework, basado en la biblioteca Qt, facilita la creación de aplicaciones multiplataforma con un aspecto profesional. A contiunación, se describe el proceso para implementar una calculadora funcional.
Configuración del Entorno
Para iniciar, se requiere la instalación de PyQt5. Utilice el gestor de paquetes pip:
pip install PyQt5
Estructura de la Aplicación
La calculadora se compone de una ventana principal con un campo de entrada para la expresión y botones para los dígitos y operaciones. La lógica principal reside en una clase que hereda de QMainWindow.
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget,
QVBoxLayout, QGridLayout, QLineEdit, QPushButton)
class CalculadoraApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Calculadora PyQt5")
self.setFixedSize(300, 400)
# Widget central y layout
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout_principal = QVBoxLayout(central_widget)
# Campo de visualización
self.display = QLineEdit()
self.display.setReadOnly(True)
self.display.setStyleSheet("font-size: 24px; padding: 10px;")
layout_principal.addWidget(self.display)
# Diseño de los botones
layout_botones = QGridLayout()
botones = [
('7', 0, 0), ('8', 0, 1), ('9', 0, 2), ('/', 0, 3),
('4', 1, 0), ('5', 1, 1), ('6', 1, 2), ('*', 1, 3),
('1', 2, 0), ('2', 2, 1), ('3', 2, 2), ('-', 2, 3),
('0', 3, 0), ('.', 3, 1), ('=', 3, 2), ('+', 3, 3),
('C', 4, 0, 1, 4) # Botón 'C' ocupa 1 fila y 4 columnas
]
for datos in botones:
texto = datos[0]
fila = datos[1]
columna = datos[2]
rowspan = datos[3] if len(datos) > 3 else 1
colspan = datos[4] if len(datos) > 4 else 1
boton = QPushButton(texto)
boton.setStyleSheet("font-size: 18px; padding: 15px;")
if texto == 'C':
boton.clicked.connect(self.limpiar_display)
elif texto == '=':
boton.clicked.connect(self.evaluar_expresion)
else:
# Usamos una lambda con un argumento predeterminado para capturar el valor
boton.clicked.connect(lambda checked, t=texto: self.agregar_caracter(t))
layout_botones.addWidget(boton, fila, columna, rowspan, colspan)
layout_principal.addLayout(layout_botones)
def agregar_caracter(self, caracter):
texto_actual = self.display.text()
self.display.setText(texto_actual + caracter)
def limpiar_display(self):
self.display.clear()
def evaluar_expresion(self):
expresion = self.display.text()
try:
# Se utiliza 'eval' con precaución; en producción, un parser seguro es preferible
resultado = str(eval(expresion))
self.display.setText(resultado)
except (SyntaxError, NameError, ZeroDivisionError):
self.display.setText("Error")
if __name__ == "__main__":
app = QApplication(sys.argv)
ventana = CalculadoraApp()
ventana.show()
sys.exit(app.exec_())
Consideraciones de Seguridad y Mejoras
El uso directo de eval() puede presentar riesgos de seguridad si la entrada del usuario no está controlada. En un entorno de producción, se recomienda implemnetar un parser matemático seguro. Asimismo, la interfaz puede enriquecerse añadiendo soporte para operaciones avanzadas como raíces cuadradas, exponentes o el historial de cálculos.