Interfaces gráficas III

Desarrollo de una simple calculadora

En este apartado vamos a usar lo explicado hasta los momentos del uso de la libreria TKINTER para desarrollar una calculadora similar a la del sistema de Windows. Para ello vamos directamente al código y explicaremos alguno que otro aspecto:

from tkinter import *
import os

#Funciones
def Pulsacion(sValor):
    global sOperacion
    global bNuevoMonto

    if bNuevoMonto:
        sNumeroPantalla.set(0)

    if bNuevoMonto and sNumeroPantalla.get() != '0' or bNuevoMonto and sNumeroPantalla.get() == '0' and sValor != '0' or not bNuevoMonto:
        if sNumeroPantalla.get() != '0':
            sNumeroPantalla.set(sNumeroPantalla.get()+sValor)
        else:
            sNumeroPantalla.set(sValor)
        bNuevoMonto=False

def Suma(sValorPantalla):
    global bNuevoMonto
    global sOperacion
    global subTotal
    if not bNuevoMonto:
        if sOperacion=='Suma' or sOperacion =='':
            subTotal+=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion=='Resta':
            subTotal-=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion=='Multiplica':            
            subTotal*=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion =='Divide':
            subTotal/=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)  
    sOperacion='Suma'
    bNuevoMonto=True

def Resta(sValorPantalla):
    global sOperacion
    global subTotal
    global bNuevoMonto

    if not bNuevoMonto:
        if sOperacion=='Suma':
            subTotal+=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion=='Resta' or sOperacion =='':
            subTotal-=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion=='Multiplica':            
            subTotal*=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion =='Divide':
            subTotal/=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)

    sOperacion='Resta'
    bNuevoMonto=True

def Multiplica(sValorPantalla):
    global sOperacion
    global subTotal
    global bNuevoMonto
    global bNuevaOperacion

    if not bNuevoMonto:
        if bNuevaOperacion and subTotal==0:
            subTotal=1
        if sOperacion=='Suma':
            subTotal+=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion=='Resta':
            subTotal-=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion=='Multiplica' or sOperacion =='':            
            subTotal*=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion =='Divide':
            subTotal/=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)    
    sOperacion='Multiplica'
    bNuevoMonto=True
    bNuevaOperacion=False

def Divide(sValorPantalla):
    global sOperacion
    global subTotal
    global bNuevoMonto
    global bNuevaOperacion

    if not bNuevoMonto:
        if bNuevaOperacion and subTotal==0:
            subTotal=int(sValorPantalla)*int(sValorPantalla)
        if sOperacion=='Suma':
            subTotal+=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion=='Resta':
            subTotal-=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion=='Multiplica':            
            subTotal*=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
        elif sOperacion =='Divide' or sOperacion == '':
            subTotal/=int(sValorPantalla)
            sNumeroPantalla.set(subTotal)
    sOperacion='Divide'
    bNuevoMonto=True
    bNuevaOperacion=False

def Resultado(sValorPantalla):
    global subTotal
    global sOperacion
    if sOperacion == 'Suma' and not bNuevoMonto:
        subTotal +=int(sValorPantalla)
    elif sOperacion == 'Resta' and not bNuevoMonto:
        subTotal-=int(sValorPantalla)
    elif sOperacion == 'Multiplica' and not bNuevoMonto:
        subTotal*=int(sValorPantalla)
    elif sOperacion == 'Divide' and not bNuevoMonto:
        subTotal/=int(sValorPantalla)
    sNumeroPantalla.set(subTotal)
    subTotal=0
    sOperacion='Resultado'    

def LimpiarTodo():
    global subTotal
    global sOperacion
    global bNuevoMonto
    global bNuevaOperacion
    subTotal=0
    sNumeroPantalla.set(0)
    bNuevoMonto=True
    bNuevaOperacion=True
    sOperacion=''
    os.system('cls')


#Inicialización de variables globales
sOperacion = ''
subTotal=0
bNuevoMonto=True
bNuevaOperacion=True

#Ventana principal
winPrincipal=Tk()
winPrincipal.title('*** Calculadora ***')
frmPrincipal=Frame(winPrincipal)
frmPrincipal.pack()

#Pantala de datos
sNumeroPantalla=StringVar()
tbPantalla=Entry(frmPrincipal,textvariable=sNumeroPantalla)
tbPantalla.grid(row=0,column=0,padx=0,pady=2,columnspan=4)
tbPantalla.config(bg='black',fg='#3FF400',justify='right')

#Fila 1
btBoton7=Button(frmPrincipal, text='7',width=3,command=lambda:Pulsacion('7'))
btBoton8=Button(frmPrincipal, text='8',width=3,command=lambda:Pulsacion('8'))
btBoton9=Button(frmPrincipal, text='9',width=3,command=lambda:Pulsacion('9'))
btDivide=Button(frmPrincipal,text='/',width=3,command=lambda:Divide(tbPantalla.get()))
btBoton7.grid(row=1,column=0,padx=2,pady=3)
btBoton8.grid(row=1,column=1,padx=2,pady=3)
btBoton9.grid(row=1,column=2,padx=2,pady=3)
btDivide.grid(row=1,column=3,padx=2,pady=3)

#Fila 2
btBoton4=Button(frmPrincipal, text='4',width=3,command=lambda:Pulsacion('4'))
btBoton5=Button(frmPrincipal, text='5',width=3,command=lambda:Pulsacion('5'))
btBoton6=Button(frmPrincipal, text='6',width=3,command=lambda:Pulsacion('6'))
btDivide=Button(frmPrincipal,text='*',width=3,command=lambda:Multiplica(tbPantalla.get()))
btBoton4.grid(row=2,column=0,padx=2,pady=3)
btBoton5.grid(row=2,column=1,padx=2,pady=3)
btBoton6.grid(row=2,column=2,padx=2,pady=3)
btDivide.grid(row=2,column=3,padx=2,pady=3)

#Fila 3
btBoton1=Button(frmPrincipal, text='1',width=3,command=lambda:Pulsacion('1'))
btBoton2=Button(frmPrincipal, text='2',width=3,command=lambda:Pulsacion('2'))
btBoton3=Button(frmPrincipal, text='3',width=3,command=lambda:Pulsacion('3'))
btResta=Button(frmPrincipal,text='-',width=3,command=lambda:Resta(tbPantalla.get()))
btBoton1.grid(row=3,column=0,padx=2,pady=3)
btBoton2.grid(row=3,column=1,padx=2,pady=3)
btBoton3.grid(row=3,column=2,padx=2,pady=3)
btResta.grid(row=3,column=3,padx=2,pady=3)

#Fila 4
btBoton0=Button(frmPrincipal, text='0',width=3,command=lambda:Pulsacion('0'))
btBotonDecimal=Button(frmPrincipal, text='.',width=3,command=lambda:Pulsacion('.'))
btBotonIgual=Button(frmPrincipal,text='=',width=3,command=lambda:Resultado(tbPantalla.get()))
btBotonSuma=Button(frmPrincipal, text='+',width=3,command=lambda:Suma(tbPantalla.get()))
btBoton0.grid(row=4,column=0,padx=0,pady=3)
btBotonDecimal.grid(row=4,column=1,padx=2,pady=3)
btBotonIgual.grid(row=4,column=2,padx=2,pady=3)
btBotonSuma.grid(row=4,column=3,padx=2,pady=3)

#Fila 5
btBotonimpiarTodo=Button(frmPrincipal,text='Limpiar todo',width=18,command=lambda:LimpiarTodo())
btBotonimpiarTodo.grid(row=5,column=0,padx=0,pady=3,columnspan=4)

sNumeroPantalla.set('0')
LimpiarTodo()


winPrincipal.mainloop()

Resultado del ingreso de la secuencia 3+2*2+10-5+15/5=:


Como podemos ver, a pesar que aún faltan mejoras para que se asemeje a la funcionalidad básica de la calculadora de Windows, ya podemos realizar las 4 operaciones básicas de suma, resta, multiplicación y división. No está implementado en este código el uso del decimal ni el ingreso de los mismos, ya que no es el objetivo de este apartado entrar de lleno en programación de la funcionalidad de la calculadora, sino mas bien el diseño de la interfaz y el llamado a funciones desde los botones, asó como la interacción con los widgets de la raíz, cosa que quedó mostrada en el ejemplo anterior.

Es destacable en este código el uso de las funciones lambda y el uso de variables booleanas para determinar el comportamiento del botón pulsado ya que los botones de operación suma, resta, muiltiplicación y división, deben ejecutar la operación anterior a ellos en caso de existir alguna e ir acumulando en una variable para que el próximo botón recuerde el monto y ejecute la operación anterior y vaya mostrando el resultado por pantalla.


Comentarios

Entradas populares