Python WX – Buttons management

Cet exemple illustre comment gérer les boutons et les fonctions associées, basé sur http://wiki.wxpython.org/AnotherTutorial

calculator

#!/usr/bin/python
# -*- coding: utf-8 -*- 
#
# calculator.py
#
# Based on the wonderfull tutorial 
#  http://wiki.wxpython.org/AnotherTutorial
#
# tested with python 2.7
#
#################################################


# Pour prendre en compte la division d'entiers comme un flotant
from __future__ import division

# Quelques fonctions mathématiques
from math import cos, sin, tan, pi, sqrt, radians

# WX
import wx

# La fenêtre principale		
class MyApp(wx.App):
	def OnInit(self):
		frame = MyFrame(None, -1, 'CalculatOr')
		frame.Show(True)
		self.SetTopWindow(frame)
		return True
		
# Le cadre principal	
class MyFrame(wx.Frame):

	# Constructeur
	def __init__(self, parent, id, title):

		# Initialisation
		wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(400, 400))

		self.SetBackgroundColour( wx.Colour(55, 55, 66) )
		
		self.formula = False

		sizer = wx.BoxSizer(wx.VERTICAL)
		
		# Affichage du texte 
		self.display = wx.TextCtrl(self, -1, '',  style=wx.TE_RIGHT)
		self.display.SetBackgroundColour( wx.Colour(240, 250, 230) )
		
		sizer.Add(self.display, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 4)

		# La grille principale, sur 4 colonnes
		gs = wx.GridSizer(4, 4, 3, 3)
		
		# Mise en place des labels
		buttonsLabels = [   'Cls', 'Bck', '', 'Close', 
							'7', '8', '9', '/', 
							'4', '5', '6', '*', 
							'1', '2', '3', '-', 
							'0', '.', '=', '+', 
							'Pi', '', '(',  ')',
							'Carré', 'Racine', '', '', 
							'Rad', 'Cos', 'Sin', 'Tan', 
							]
							
		# Définition des signes					
		self.signs = ['/', '*', '-', '.', '+', '(',  ')']
		self.signsByEvtId = {}
		
		# Définition des chiffres
		self.numbers = [ str(i) for i in range(10) ] + ["Pi"]
		self.numbersByEvtId = {}
				
		# Assignation des fonctions	particulières				
		specialFunc = { 'Cls' : self.OnClear, 'Bck' : self.OnBackspace, 
						'Close' : self.OnClose, 
						'=' : self.OnEqual, 
						'Rad' : self.OnRad, 'Cos' : self.OnCos, 
						'Sin' : self.OnSin, 'Tan' : self.OnTan, 
						'Carré' : self.OnSq, 'Racine' : self.OnSqrt, 
						}

			
		# Une petite touche de couleurs
		defaultColor = wx.Colour(240, 240, 255)
		numColor = 	wx.Colour(200, 222, 200)
		buttonsColor = {}
		
		for i in range(10):
			buttonsColor[str(i)] = numColor
		buttonsColor['Pi'] = wx.Colour(200, 220, 255)
		
		for b in ['(',  ')']:
			buttonsColor[b] = wx.Colour(250, 250, 200)
		buttonsColor['='] = wx.Colour(250, 200, 200)
		
		# Création des boutons et correspondances d'avec les fonctions	
		
		# Identifiant WX	
		buttonId = 10
		
		# Liste des boutons
		buttons = []
		
		# Boucle sur les labels
		for buttonLabel in buttonsLabels :

			# Si le label correspond à un chiffre, fonction OnNumber(),
			if buttonLabel in self.numbers:
			
				# Attribution d'une valeur à l'id du bouton ( id de l'évènement )
				if buttonLabel == "Pi" : 
					val = str(pi)
				else : 
					val = buttonLabel
				self.numbersByEvtId[buttonId] = val
				
				# Création du bouton
				button = wx.Button(self, buttonId, buttonLabel)
				
				# Assignation à la fonction
				self.Bind(wx.EVT_BUTTON, self.OnNumber, id=buttonId)
				
			# si non, si le label correspond à un signe, fonction OnSign(),
			elif buttonLabel in self.signs:
				self.signsByEvtId[buttonId] = buttonLabel
				button = wx.Button(self, buttonId, buttonLabel)
				self.Bind(wx.EVT_BUTTON, self.OnSign, id=buttonId)
				
			# si non, si le label correspond à une fonction particulière,
			elif buttonLabel in specialFunc:  
				button = wx.Button(self, buttonId, buttonLabel)
				self.Bind(wx.EVT_BUTTON, specialFunc[ buttonLabel ], id=buttonId)
			
			# si non, on affiche le texte .
			else:
				button = wx.StaticText(self, -1, buttonLabel)
				
			# Assignation des couleurs
			if buttonLabel in buttonsColor : 
				button.SetBackgroundColour( buttonsColor[ buttonLabel ] )
			else:
				button.SetBackgroundColour( defaultColor )
				
			# Ajout du bouton dans la liste
			buttons.append( button )
			
			# Incrémenter l'id du boutton
			buttonId += 1
		
		# On laisse WX placer nos bouton par ligne de 4 suivant notre liste
		gs.AddMany( buttons )

		sizer.Add(gs, 1, wx.EXPAND)

		self.SetSizer(sizer)
		self.Centre()
		
		# Fin Constructeur
	 
	# Traitement des signes
	def OnSign(self, event):
		if self.formula: 
			return
		sign = self.signsByEvtId[ event.GetId() ]
		self.display.AppendText( sign )

	# Traitement des chiffres
	def OnNumber(self, event):
		if self.formula:
			self.display.Clear()
			self.formula = False
		 
		num =  self.numbersByEvtId[ event.GetId() ]  
		self.display.AppendText( num )

	# Traitement particuliers: fonctions mathématiques standards

	# Tangente		
	def OnTan(self, event):
		if self.formula:
			return
		formula = self.display.GetValue()
		self.formula = False
		try:
			self.display.Clear()
			output = tan( float(eval(formula)) )
			self.display.AppendText(str(output))
		except StandardError, e:
			self.display.AppendText("Error : "+str(e))
	
	# Sinus	
	def OnSin(self, event):
		if self.formula:
			return
		formula = self.display.GetValue()
		self.formula = False
		try:
			self.display.Clear()
			output = sin( float(eval(formula)) )
			self.display.AppendText(str(output))
		except StandardError, e:
			self.display.AppendText("Error : "+str(e))
		
	# Cosinus		
	def OnCos(self, event):
		if self.formula:
			return
		formula = self.display.GetValue()
		self.formula = False
		try:
			self.display.Clear()
			output = cos( float(eval(formula)) )
			self.display.AppendText(str(output))
		except StandardError, e:
			self.display.AppendText("Error : "+str(e))
			
	# Racinne carré	  
	def OnSqrt(self, event):
		if self.formula:
			return
		formula = self.display.GetValue()
		self.formula = False
		try:
			self.display.Clear()
			output = sqrt( float(eval(formula)) )
			self.display.AppendText(str(output))
		except StandardError, e:
			self.display.AppendText("Error : "+str(e))
		
	# Carré	
	def OnSq(self, event):
		if self.formula:
			return
		formula = float(eval(self.display.GetValue() ) )
		self.formula = False
		try:
			self.display.Clear()
			output = formula ** 2 
			self.display.AppendText(str(output))
		except StandardError, e:
			self.display.AppendText("Error : "+str(e))

	# Traitements particuliers: fonctions de la calculette 
	
	# Convertir en radians
	def OnRad(self, event):
		if self.formula:
			return
		formula = self.display.GetValue()
		self.formula = False
		try:
			self.display.Clear()
			output = radians( float(eval(formula)) )
			self.display.AppendText(str(output))
		except StandardError, e:
			self.display.AppendText("Error : "+str(e))
			
			
	# Tout effacer
	def OnClear(self, event):
		self.display.Clear()

	# Effacer le dernier caractère
	def OnBackspace(self, event):
		formula = self.display.GetValue()
		self.display.Clear()
		self.display.SetValue(formula[:-1])

	# Calcul du résultat
	def OnEqual(self, event):
		if self.formula:
			return
		formula = self.display.GetValue()
		self.formula = False
		try:
			self.display.Clear()
			output = eval(formula)
			self.display.AppendText(str(output))
			#self.formula = True
		except StandardError, e:
			self.display.AppendText("Error : "+str(e))

	# Fermeture de la fenêtre
	def OnClose(self, event):
		self.Close()
		
# Construction
app = MyApp(0) 
app.MainLoop()