#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Calculadora.py
#
__license__ = "GPL"
import sys
import math
import wx
class Calculator(object):
"""Clase para realizar operaciones aritmeticas.
"""
def __init__(self):
self.operators = {"+": self.Sum,
"-": self.Rest,
"*": self.Mult,
"/": self.Div,
u"±": self.Negative,
u"x²": self.Square,
u"¹/x": self.OneInX,
u"√": self.Squareroot,
u"%": self.Percent,
u"C": self.Clear
}
self.arith_operators = {"+": self.Sum,
"-": self.Rest,
"*": self.Mult,
"/": self.Div
}
self.espec_operators = {u"±": self.Negative,
u"x²": self.Square,
u"¹/x": self.OneInX,
u"√": self.Squareroot,
u"%": self.Percent,
u"C": self.Clear}
self.expression = []
self.expression_string = u""
self.result = 0.0
def IsNumber(self, string):
try:
float(string)
except ValueError:
return False
return True
def Sum(self, num_1, num_2):
"""
Sumar: num_1 + num_2
"""
return num_1 + num_2
def Rest(self, num_1, num_2):
"""
Restar: num_1 - num_2
"""
return num_1 - num_2
def Mult(self, num_1, num_2):
"""
Multiplicar: num_1 * num_2
"""
return num_1 * num_2
def Div(self, num_1, num_2):
"""
Dividir: num_1 / num_2
"""
return num_1 / num_2
def Negative(self, num):
"""
Convirte el numero positivo en negativo y viceversa.
"""
return -num
def Square(self, num):
"""
Retorna el cuadrado del numero indicado.
"""
return num * num
def Squareroot(self, num):
"""
Retorna la raiz cuadrada del numero indicado.
Para tal fin utilizamos la funcion sqrt del modulo math.
"""
return math.sqrt(num)
def OneInX(self, num):
"""
Dividimos el numero 1 entre el numero indicado.
"""
return 1.0 / num
def Percent(self, num, percent=100):
"""
Calculamos el porcentaje indicado al numero.
"""
return (num / 100.0) * percent
def Clear(self):
"""
Limpia los datos introduccidos.
"""
self.expression = []
def Calculate(self, num_1, num_2, operator):
"""
Calcula num_1 y num_2 segun el operador indicado.
"""
expression = "%s %s %s" % (num_1, operator, num_2)
exec "out = %s" % expression
return out
def Reduce(self, choice):
"""
Resuelve las operaciones de lista hasta
que no quede mas elementos. Retorna el resultado.
"""
out = 0.0
result = float(choice[0])
for n in range(0, len(choice), 2):
number_1 = result
try:
operator = choice[n+1]
except IndexError:
break
try:
number_2 = float(choice[n+2])
except (IndexError, ValueError):
number_2 = number_1
try:
if choice[n+3] == "%":
number_2 = self.Percent(num_1, num2)
except IndexError:
pass
# si es un operador especial
if operator in self.espec_operators.keys():
result = self.operators[operator](number_1)
else:
result = self.Calculate(number_1, number_2, operator)
out += result
return out
def Solve(self):
"""
Resuelve la expression.
"""
self.expression_string = unicode.join(u" ", self.expression)
try:
exec("self.result = %s" % self.expression_string)
except SyntaxError as e:
print(e)
return self.result
#-------------------------------------------------------------------
# Intefaz gráfica
#-------------------------------------------------------------------
class DlgCalculator(wx.Dialog, Calculator):
"""Interfaz grafica de una calculadora simple.
"""
def __init__(self, parent, *args, **kwargs):
wx.Dialog.__init__(self, parent, *args, **kwargs)
Calculator.__init__(self)
# definimos los controles
self.textctrl_1 = wx.TextCtrl(self, -1, style=wx.TE_READONLY|wx.NO_BORDER|wx.TE_RIGHT)
self.textctrl_2 = wx.TextCtrl(self, -1, style=wx.TE_READONLY|wx.NO_BORDER|wx.TE_RIGHT)
self.button_0 = wx.Button(self, 0, u"0")
self.button_1 = wx.Button(self, 1, u"1")
self.button_2 = wx.Button(self, 2, u"2")
self.button_3 = wx.Button(self, 3, u"3")
self.button_4 = wx.Button(self, 4, u"4")
self.button_5 = wx.Button(self, 5, u"5")
self.button_6 = wx.Button(self, 6, u"6")
self.button_7 = wx.Button(self, 7, u"7")
self.button_8 = wx.Button(self, 8, u"8")
self.button_9 = wx.Button(self, 9, u"9")
self.button_10 = wx.Button(self, 10, u".")
self.button_11 = wx.Button(self, 11, u"+")
self.button_12 = wx.Button(self, 12, u"-")
self.button_13 = wx.Button(self, 13, u"x")
self.button_14 = wx.Button(self, 14, u"÷")
self.button_15 = wx.Button(self, 15, u"±")
self.button_16 = wx.Button(self, 16, u"x²")
self.button_17 = wx.Button(self, 17, u"¹/x")
self.button_18 = wx.Button(self, 18, u"√")
self.button_19 = wx.Button(self, 19, u"%")
self.button_20 = wx.Button(self, 20, u"C")
self.button_21 = wx.Button(self, 21, u"=")
# variables
self.numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
self.expression = []
self.expression_string = u""
self.result = 0.0
self.__do_layout()
self.__set_prop()
self.__set_event()
def __do_layout(self):
"""
Establecemos los sizer y
organizamos los controles en ellos.
"""
s1 = wx.BoxSizer(wx.VERTICAL)
s2 = wx.BoxSizer(wx.VERTICAL)
s2.Add(self.textctrl_1, 0, wx.EXPAND|wx.DOWN, 5)
s2.Add(self.textctrl_2, 1, wx.EXPAND)
s1.Add(s2, 1, wx.EXPAND|wx.ALL, 5)
s1.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
s3 = wx.GridSizer(6, 4, 0, 0) # 6 filas, 4 columnas
# botones fila 1
s3.Add(self.button_16, 0, wx.EXPAND)
s3.Add(self.button_20, 0, wx.EXPAND)
s3.AddSpacer(1)
s3.AddSpacer(1)
# botones fila 2
s3.Add(self.button_19, 0, wx.EXPAND)
s3.Add(self.button_18, 0, wx.EXPAND)
s3.Add(self.button_17, 0, wx.EXPAND)
s3.Add(self.button_14, 0, wx.EXPAND)
# botones fila 3
s3.Add(self.button_7, 0, wx.EXPAND)
s3.Add(self.button_8, 0, wx.EXPAND)
s3.Add(self.button_9, 0, wx.EXPAND)
s3.Add(self.button_13, 0, wx.EXPAND)
# botones fila 4
s3.Add(self.button_4, 0, wx.EXPAND)
s3.Add(self.button_5, 0, wx.EXPAND)
s3.Add(self.button_6, 0, wx.EXPAND)
s3.Add(self.button_12, 0, wx.EXPAND)
# botones fila 5
s3.Add(self.button_1, 0, wx.EXPAND)
s3.Add(self.button_2, 0, wx.EXPAND)
s3.Add(self.button_3, 0, wx.EXPAND)
s3.Add(self.button_11, 0, wx.EXPAND)
# botones fila 6
s3.Add(self.button_15, 0, wx.EXPAND)
s3.Add(self.button_0, 0, wx.EXPAND)
s3.Add(self.button_10, 0, wx.EXPAND)
s3.Add(self.button_21, 0, wx.EXPAND)
s1.Add(s3, 3, wx.EXPAND|wx.ALL, 5)
self.SetSizer(s1)
s1.Fit(self)
self.Layout()
def __set_prop(self):
"""
Establecemos algunas propiedades extras a los controles.
"""
self.SetSize((400, 400))
self.textctrl_2.SetFont(wx.Font(20, wx.DEFAULT, wx.NORMAL, wx.BOLD))
# color y fuente de los botones
for id in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9):
button = self.FindWindowById(id)
button.SetBackgroundColour(wx.Colour(255, 255, 200))
button.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.BOLD))
for id in (11, 12, 13, 14):
button = self.FindWindowById(id)
button.SetBackgroundColour(wx.Colour(200, 255, 200))
button.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
for id in (15, 16, 17, 18, 19):
button = self.FindWindowById(id)
button.SetBackgroundColour(wx.Colour(200, 200, 255))
button.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
for id in (20,):
button = self.FindWindowById(id)
button.SetBackgroundColour(wx.Colour(255, 200, 200))
button.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
def __set_event(self):
"""
Establecemos los eventos a los controles.
"""
for bid in range(22):
self.Bind(wx.EVT_BUTTON, self.OnClick, id=bid)
def OnClick(self, event):
"""
Al presionar uno de los botones.
"""
character = event.GetEventObject().GetLabel()
if character == u"x":
character = u"*"
elif character == u"÷":
character = u"/"
if not self.expression:
if character in self.numbers:
self.expression.append(character)
elif character == u"=":
self.Solve()
elif character == u"C":
self.expression = []
self.result = 0.0
elif self.expression[-1] in self.numbers:
if character == u"±":
self.expression[-1] = u"%s" % -float(self.expression[-1])
elif character == u"x²":
self.expression[-1] = u"%s" % (float(self.expression[-1]) * float(self.expression[-1]))
elif character == u"¹/x":
self.expression[-1] = u"%s" % (1 / float(self.expression[-1]))
elif character == u"√":
self.expression[-1] = u"%s" % math.sqrt( float(self.expression[-1]) )
elif character == u"%":
n1 = float(self.expression[-3])
self.expression[-1] = u"%s" % ((n1 / 100) * float(self.expression[-1]))
elif character in ("*", "/", "-", "+"):
self.expression.append(character)
self.Solve()
elif character in self.numbers:
self.expression[-1] += character
else:
if character in self.numbers:
self.expression.append(character)
elif character in ("*", "/", "-", "+"):
self.expression[-1] = character
self.expression_string = unicode.join(u" ", self.expression)
self.textctrl_1.SetValue(self.expression_string)
self.textctrl_2.SetValue(str(self.result))
event.Skip()
def Solve(self):
try:
exec("self.result = %s" % self.expression_string)
except SyntaxError:
pass
return self.result
def main(args):
app = wx.App(0)
dlg = DlgCalculator(None, id=-1, title=u"Calculadora")
dlg.Show()
app.MainLoop()
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))
Calculadora simple escrita en Python
Ahora les dejo el código fuente de una calculadora simple escrita en Python con wxPython. El objetivo principal de este artículo es mostrar nuevamente la simplicidad de Python en el desarrollo de aplicaciones inclusive con interfaz gráfica. La aplicación tiene fallas pero puedes tomar el código y modificarlo como gustes.