All pastes #948559 Raw Edit

Mine

public python v1 · immutable
·published 2008-03-19 06:53 UTC
rendered paste body
#!/usr/bin/python#Libraries to importimport wximport timeimport threading#This is the data for numbers in the 7-segment display.#The item is a list, so segment[0] = "1110111". Each char in this string is whether that particular segment should be on or off.segments = ("1110111","0010010","1011101","0111010","1101011","1101111","1010010","1111111","1111101")#Various IDs for use with wxpython (elements require IDs and IDs are used for setting up event handlers and the like)ident = {"buttonSet":1,"buttonZeroPump":2,"buttonZeroTotals":3,"buttonNozzle1":4,"buttonNozzle2":5,"txtSet":6,"spinSet":7,"txtStatus":8,"txtConsolePetrol":9,"txtConsolePrice":10,"txtConsoletotalPetrolDispensed":11,"txtConsoleTotalTakings":12,"txtPumpPetrol":13,"txtPumpPrice":14,"txtPencePerLitre":15,"menuQuit":16,"menuAlwaysOnTop":17}#Button settings: label and enabled.button = {ident["buttonSet"]:{"enable":False,"text":"set"},ident["buttonZeroPump"]:{"enable":False,"text":"Zero Pump"},ident["buttonZeroTotals"]:{"enable":False,"text":"Zero Totals"},ident["buttonNozzle1"]:{"enable":True,"text":"Take Nozzle"},ident["buttonNozzle2"]:{"enable":False,"text":"Squeese"}}#Config to be used throughoutconfig = {"fillrate":0.1,"spinrate":0.1,"runthread":0,"titlestart":"Peter's Petrol Pumps","windowstyles":0,"segw":8,"segh":1}#The main variables that are used a lot.uiControls = {}pencePerLitre = 95.0pencePerLitreBox = 95.0pencePerLitreQueue = 0petrolDispensed=0totalTakings=0totalPetrolDispensed=0status = 'Ready'#Threading is required to make the UI still usable while the pump is filling up.#Essentially, the pump-filling routine needs to loop until the "Unsqueeze pump" button is pressed#This looping would freeze the UI (as you would expect), so had to make made asyncronous.class Filler(threading.Thread):	def run(self):		global config, petrolDispensed, status    		while config["runthread"]: #runthread is set from the main class asyncronously.    			petrolDispensed = petrolDispensed + 0.1 #Increment the petrol    			if(petrolDispensed >= 100): #We can't fill above 100 litres					petrolDispensed = 100					#Disable stuff:					status = "Out Of Use"					button[ident["buttonNozzle1"]]["enable"] = False					button[ident["buttonNozzle2"]]["enable"] = False					button[ident["buttonNozzle1"]]["text"] = "Take nozzle"					button[ident["buttonNozzle2"]]["text"] = "Squeese"					config["runthread"] = 0 #Stop loop.    			frame.UpdateUI()    			time.sleep(config["fillrate"]) #Slow down the filling-up#This is the main class. __init__ is called when the app startsclass MainControl(wx.Frame):	def __init__(self, parent, id, title):		self.MakeUI(parent, id, title);		self.MakeEventHandlers();		self.UpdateUI();	def MakeUI(self, parent, id, title):		#This function is called only once, on startup. It uses the wxwidgets toolkit to set up the GUI		wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, (600, 400)) #Create the frame		uiControls["panel"] = wx.Panel(self, -1, style=wx.EXPAND) #Create the panel		#Menu setup:		menubar = wx.MenuBar()		options = wx.Menu()		uiControls["menuAlwaysOnTop"] = options.Append(ident["menuAlwaysOnTop"], '&Always On Top', 'The window will always show above other windows', kind=wx.ITEM_CHECK)		options.Append(ident["menuQuit"], '&Quit', 'Exit the application')		menubar.Append(options, '&Options')		self.SetMenuBar(menubar)		#End menu setup.				heading = wx.Font(9, wx.NORMAL, wx.NORMAL, wx.BOLD) # This will be reused for subtitles.				#--- TOP LEFT CONTENT ---------------------------------------------------						uiControls["txtStatus"] = wx.StaticText(uiControls["panel"], ident["txtStatus"], "Ready");		uiControls["txtConsolePetrol"] = wx.StaticText(uiControls["panel"], ident["txtConsolePetrol"] , "0.0 litres")		uiControls["txtConsolePrice"]  = wx.StaticText(uiControls["panel"], ident["txtConsolePrice"] , "0.00")		uiControls["txtConsoletotalPetrolDispensed"]  = wx.StaticText(uiControls["panel"], ident["txtConsoletotalPetrolDispensed"] , "0.0 litres")		uiControls["txtConsoleTotalTakings"] = wx.StaticText(uiControls["panel"], ident["txtConsoleTotalTakings"] , "0.00")		sizera1cont = [		wx.StaticText(uiControls["panel"], -1, "Pump details"),wx.StaticText(uiControls["panel"], -1, ""),		wx.StaticText(uiControls["panel"], -1, "  Status:"),uiControls["txtStatus"],		wx.StaticText(uiControls["panel"], -1, "  Petrol dispensed:"),uiControls["txtConsolePetrol"],		wx.StaticText(uiControls["panel"], -1, "  Price:"),uiControls["txtConsolePrice"],		wx.StaticText(uiControls["panel"], -1, "Today's totals"),wx.StaticText(uiControls["panel"], -1, ""),		wx.StaticText(uiControls["panel"], -1, "  Petrol:"),uiControls["txtConsoletotalPetrolDispensed"],		wx.StaticText(uiControls["panel"], -1, "  Takings:"),uiControls["txtConsoleTotalTakings"]		]		#--- BOTTOM LEFT CONTENT ------------------------------------------------		uiControls["buttonSet"] = wx.Button(uiControls["panel"], ident["buttonSet"], "set",style=wx.EXPAND)		uiControls["buttonSet"].SetMinSize((40, 26))		uiControls["txtSet"] = wx.TextCtrl(uiControls["panel"], ident["txtSet"], "%.1f" % pencePerLitre,style=wx.EXPAND) 		sizerb1acont = [		wx.StaticText(uiControls["panel"], -1, "Pence per litre:",style=wx.EXPAND),		uiControls["txtSet"],		wx.SpinButton(uiControls["panel"], ident["spinSet"],style=wx.EXPAND),		uiControls["buttonSet"]		]		sizerb1bcont = [		wx.Button(uiControls["panel"], ident["buttonZeroPump"], "Zero pump",style=wx.EXPAND),		wx.Button(uiControls["panel"], ident["buttonZeroTotals"], "Zero today's totals",style=wx.EXPAND)		]				#--- TOP RIGHT CONTENT --------------------------------------------------		uiControls["txtPumpPrice"] = self.MakeLCD(5,3,"7sPumpPrice")		uiControls["txtPumpPetrol"] = self.MakeLCD(3,2,"7sPumpPetrol")		uiControls["txtPencePerLitre"] = self.MakeLCD(4,3,"7sPencePerLitre")		sizerc1cont = [		wx.StaticText(uiControls["panel"], -1, "  Amount to pay:"), (uiControls["txtPumpPrice"], 1, wx.SHAPED, 0),		wx.StaticText(uiControls["panel"], -1, "  Petrol"),         uiControls["txtPumpPetrol"],		wx.StaticText(uiControls["panel"], -1, "  Pence per litre"),uiControls["txtPencePerLitre"]		]				#--- BOTTOM RIGHT CONTENT -----------------------------------------------				uiControls["buttonNozzle1"] = wx.ToggleButton(uiControls["panel"], ident["buttonNozzle1"], 'Take Nozzle',style=wx.EXPAND)		uiControls["buttonNozzle1"].SetMinSize((128,32))		uiControls["buttonNozzle2"] = wx.ToggleButton(uiControls["panel"], ident["buttonNozzle2"], "Squeese",style=wx.EXPAND)		uiControls["buttonNozzle2"].SetMinSize((128,32)) 		uiControls["buttonNozzle2"].Enable(False)		sizerd1cont = [uiControls["buttonNozzle1"],uiControls["buttonNozzle2"]]				#--- MAIN LAYOUT --------------------------------------------------------		#This is where all the pieces created above are put together				# Set up root sizer		sizer0 = wx.GridSizer(2, 2, 0, 8)				# Set up quadrants		temp = wx.StaticBox( uiControls["panel"], id, "Console display" )		temp.SetFont(heading)		sizera = wx.StaticBoxSizer( temp, wx.VERTICAL )				temp = wx.StaticBox( uiControls["panel"], id, "Console controls" )		temp.SetFont(heading)		sizerb = wx.StaticBoxSizer( temp, wx.VERTICAL )				temp = wx.StaticBox( uiControls["panel"], id, "Pump display" )		temp.SetFont(heading)		sizerc = wx.StaticBoxSizer( temp, wx.VERTICAL )				temp = wx.StaticBox( uiControls["panel"], id, "Pump controls" )		temp.SetFont(heading)		sizerd = wx.StaticBoxSizer( temp, wx.VERTICAL )						#Set up lower-level sizers		sizera1 = wx.GridSizer(9, 2, 3, 3)		sizerb1 = wx.BoxSizer(wx.VERTICAL)		sizerb1a = wx.BoxSizer(wx.HORIZONTAL)		sizerb1b = wx.BoxSizer(wx.HORIZONTAL)		sizerc1 = wx.GridSizer(3, 2, 3, 3)		sizerd1 = wx.BoxSizer(wx.HORIZONTAL)				#Add content to lower-level sizers		sizera1.AddMany(sizera1cont)		sizerb1.AddMany([sizerb1a, (sizerb1b,0,wx.ALIGN_CENTER_HORIZONTAL)])		sizerb1a.AddMany(sizerb1acont)		sizerb1b.AddMany(sizerb1bcont)		sizerc1.AddMany(sizerc1cont)		sizerd1.AddMany(sizerd1cont)				#Add lower-level sizers to quadrants		sizera.Add(sizera1)		sizerb.Add(sizerb1, flag=wx.EXPAND)		sizerc.Add(sizerc1, 1, wx.EXPAND, 0)		sizerd.Add(sizerd1, flag=wx.ALIGN_CENTER_HORIZONTAL)				#Add quadrants to root sizer		sizer0.Add(sizera, flag=wx.EXPAND)		sizer0.Add(sizerc, flag=wx.EXPAND)		sizer0.Add(sizerb, flag=wx.EXPAND)		sizer0.Add(sizerd, flag=wx.EXPAND)		#Setup main frame		#uiControls["panel"].SetSize(uiControls["panel"].GetEffectiveMinSize())		uiControls["panel"].SetSizer(sizer0)		self.Centre()		config["windowstyles"] = self.GetWindowStyleFlag()		self.MakeLCD(3,2,"lol")	def UpdateLCD(self, value, key):		value=str(value)		#Formatting!		lhs=uiControls[key][point] #number of digits left of the decimal point		rhs=lhs-uiControls[key][digits]		split = value.split(".")		split[0] = split[0].rjust(lhs,"0")		split[0] = split[0][-lhs:]		split[1] = split[1].ljust(rhs,"0")		split[1] = split[1][:rhs]		value = split[0] + split[1]		for y in range(0,value.len()-1): #Loop through each character			for z in range(0,6): #Loop through each segment				if (segments[int(value[y])][z]==1): 					uiControls[key][y][z].SetBackgroundColour(wx.BLACK) #Black the segment				else:					uiControls[key][y][z].SetBackgroundColour(wx.DEFAULT) #Make it transparent again	def MakeLCD(self, digits, point, key):		width=(digits*4)+2 #This is the number of columns in the gridsizer		uiControls[key] = {"ref":wx.GridSizer(5, width, 5, 5),0:{},1:{},2:{},3:{},4:{},"digits":digits,"point":point} #Basic setup for the gridsizer		for x in range(0,5): #Loop through rows			switch = x % 2 # Are we on an odd or an even row?			#Each sement is given a key, 0 through 6. These references below calculate this reference based on the row.			ref1 = (3/2)*x       #segments 0, 3, 6			ref2 = (3/2)*x-(1/2) #segments 1, 4			ref3 = (3/2)*x+(1/2) #segments 2, 5						for y in range(0,digits): #Loop through each digit				if(y==point): #Should we insert a decimal point?					if(x<4):						uiControls[key]["ref"].Add(wx.Panel(uiControls["panel"], -1))	#space						uiControls[key]["ref"].Add(wx.Panel(uiControls["panel"], -1))	#space					else:						uiControls[key]["point"] = wx.Panel(uiControls["panel"], -1, size=(config["segh"],config["segh"]))						uiControls[key]["point"] .SetBackgroundColour(wx.BLACK)						uiControls[key]["ref"].Add(uiControls[key]["point"] )	#point						uiControls[key]["ref"].Add(wx.Panel(uiControls["panel"], -1))	#space				if(switch==0): #An even row (meaning space|segment|space|space|)					uiControls[key]["ref"].Add(wx.Panel(uiControls["panel"], -1, size=(config["segh"],config["segh"]), style=wx.EXPAND))	#blank					uiControls[key][y][ref1] = wx.Panel(uiControls["panel"], -1, size=(config["segw"],config["segh"]), style=wx.EXPAND)					uiControls[key][y][ref1].SetBackgroundColour(wx.BLACK)					uiControls[key]["ref"].Add(uiControls[key][y][ref1])		#seg					uiControls[key]["ref"].Add(wx.Panel(uiControls["panel"], -1, size=(config["segh"],config["segh"]), style=wx.EXPAND))	#blank					uiControls[key]["ref"].Add(wx.Panel(uiControls["panel"], -1, size=(config["segh"],config["segh"]), style=wx.EXPAND))	#space				else: #An odd row (meaning segment|space|segment|space|)					uiControls[key][y][ref2] = wx.Panel(uiControls["panel"], -1, size=(config["segh"],config["segw"]), style=wx.EXPAND)					uiControls[key][y][ref2].SetBackgroundColour(wx.BLACK)					uiControls[key]["ref"].Add(uiControls[key][y][ref2])		#seg					uiControls[key]["ref"].Add(wx.Panel(uiControls["panel"], -1, size=(config["segw"],config["segw"]), style=wx.EXPAND))	#blank					uiControls[key][y][ref3] = wx.Panel(uiControls["panel"], -1, size=(config["segh"],config["segw"]), style=wx.EXPAND)					uiControls[key][y][ref3].SetBackgroundColour(wx.BLACK)					uiControls[key]["ref"].Add(uiControls[key][y][ref3])		#seg					uiControls[key]["ref"].Add(wx.Panel(uiControls["panel"], -1, size=(config["segh"],config["segw"]), style=wx.EXPAND))	#space		return uiControls[key]["ref"] #return the created ui object'''	def MakeEventHandlers(self):		#This sets up the event handlers for various UI elements		self.Bind(wx.EVT_BUTTON, self.OnSet, id=ident["buttonSet"])		self.Bind(wx.EVT_SPIN_UP, self.OnSetSpinUp, id=ident["spinSet"])		self.Bind(wx.EVT_SPIN_DOWN, self.OnSetSpinDown, id=ident["spinSet"])		self.Bind(wx.EVT_BUTTON, self.OnZeroPump, id=ident["buttonZeroPump"])		self.Bind(wx.EVT_BUTTON, self.OnZeroTotals, id=ident["buttonZeroTotals"])		self.Bind(wx.EVT_TOGGLEBUTTON, self.OnNozzle1, id=ident["buttonNozzle1"])		self.Bind(wx.EVT_TOGGLEBUTTON, self.OnNozzle2, id=ident["buttonNozzle2"])		self.Bind(wx.EVT_MENU, self.OnQuit, id=ident["menuQuit"])		self.Bind(wx.EVT_MENU, self.OnAlwaysOnTop, id=ident["menuAlwaysOnTop"])		def UpdateUI(self):		#As suggested by the title, this function updates things in the UI (text contents, button labels, etc)		temp_price = petrolDispensed * pencePerLitre / 100		if(petrolDispensed < 0.5 and config["runthread"]):			temp_price = 0.5 * pencePerLitre / 100		#--- Console Display ---#		uiControls["txtStatus"].SetLabel(status)		uiControls["txtConsolePetrol"].SetLabel("%.1f litres" % petrolDispensed)		uiControls["txtConsolePrice"].SetLabel("%.2f" % temp_price)		uiControls["txtConsoletotalPetrolDispensed"].SetLabel("%.1f litres" % totalPetrolDispensed)		uiControls["txtConsoleTotalTakings"].SetLabel("%.2f" % totalTakings)		#--- Console Controls ---#		uiControls["txtSet"].SetValue(str(pencePerLitreBox))		#--- Pump Display ---#		UpdateLCD("%.2f" % temp_price, "7sPumpPrice");		UpdateLCD("%.1f" % petrolDispensed, "7sPumpPetrol")		UpdateLCD("%.1f" % pencePerLitre, "7sPencePerLitre")		#--- Pump Controls ---#		uiControls['buttonNozzle1'].Enable(button[ident["buttonNozzle1"]]["enable"])		uiControls['buttonNozzle2'].Enable(button[ident["buttonNozzle2"]]["enable"])		uiControls['buttonNozzle1'].SetLabel(button[ident["buttonNozzle1"]]["text"])		uiControls['buttonNozzle2'].SetLabel(button[ident["buttonNozzle2"]]["text"])		#---- Title ---#		self.SetTitle(config["titlestart"]+" :: "+status)	def OnQuit(self, event):		self.Close()	def OnAlwaysOnTop(self,event):		#"Always On Top" was checked or unchecked on the menu. Act accordingly.		if uiControls["menuAlwaysOnTop"].IsChecked():			self.SetWindowStyleFlag(config["windowstyles"]|wx.STAY_ON_TOP)		else:			self.SetWindowStyleFlag(config["windowstyles"])	def OnSet(self, event):		#The "set" button was clicked to set the pence-per-litre		global pencePerLitre, pencePerLitreQueue, pencePerLitreBox		pencePerLitreBox = float(uiControls["txtSet"].GetValue()) #First get the float value of the input box		if(pencePerLitreBox >= 0 and pencePerLitreBox < 199.9): #Is it in range?			if status == "Ready": #PPL can only be changed if the pump is ready (to avoid ripping people off)				pencePerLitre = float("%.1f" % float(pencePerLitreBox)) # Change it! (be sure to format it too)			else:				pencePerLitreQueue = "%.1f" % float(pencePerLitreBox) # Add the new value to the queue				#Display a handy dialog box notifying pete of his incompetence.				d = wx.MessageDialog(self, "As the pump isn't ready, the change in pence-per-litre will take effect when you next zero the pump", "Notice", wx.OK)				d.ShowModal()				d.Destroy()		else:			pencePerLitreBox = pencePerLitre #Revert input box value			#Display a handy dialog box notifying pete of his incompetence.			d = wx.MessageDialog(self, "Pence Per Litre can only be set to values between 0 and 199.9", "Notice", wx.OK)			d.ShowModal()			d.Destroy()		self.UpdateUI();		def OnSetSpinUp(self, event):		#Increment the PPL input box value		global pencePerLitreBox		pencePerLitreBox = pencePerLitreBox+config["spinrate"]		self.UpdateUI();	def OnSetSpinDown(self, event):		#Decrement the PPL input box value		global pencePerLitreBox		pencePerLitreBox = pencePerLitreBox-config["spinrate"]		self.UpdateUI();	def OnZeroPump(self, event):		#Zero the amount of petrol dispensed and add it to today's total		global petrolDispensed, pencePerLitre, pencePerLitreQueue, totalPetrolDispensed, totalTakings, status		if status == "In Use":			d = wx.MessageDialog(self, "Pump cannot be zeroed until Nozzle is replaced", "Error", wx.OK | wx.ICON_ERROR)			d.ShowModal()			d.Destroy()		else:			button[ident["buttonNozzle1"]]["enable"] = True #Re-enable use of the pump			totalPetrolDispensed = totalPetrolDispensed + petrolDispensed #Add petrol to total			totalTakings = petrolDispensed * pencePerLitre / 100 #Add moneyz to total			petrolDispensed = 0	#Reset pump petrol			status = "Ready" #Reset status			if pencePerLitreQueue: #Adjust PPL if queued.				pencePerLitre = pencePerLitreQueue				pencePerLitreQueue = 0;		self.UpdateUI()	def OnZeroTotals(self, event):		#Zero today's totals		#Really we should have a confirmation here.		global totalPetrolDispensed, totalTakings		totalPetrolDispensed = 0		totalTakings = 0		self.UpdateUI()	def OnNozzle1(self, event):		#Handler for the "take nozel" / "replace nozel" button		global status		if status == "In Use": #Nozel is being replaced			button[ident["buttonNozzle2"]]["enable"] = False #Disallow squeesing			button[ident["buttonNozzle1"]]["text"] = "Take Nozzle" #Set label accordingly			if petrolDispensed == 0:				status = "Ready"			else:				status = "Out of Use"				button[ident["buttonNozzle1"]]["enable"] = False #As petrol has been dispensed, the pump can no longer be used						else: #Nozel is being taken			button[ident["buttonNozzle1"]]["text"] = "Replace Nozzle"			button[ident["buttonNozzle2"]]["enable"] = True			status = "In Use"		self.UpdateUI()					def OnNozzle2(self, event):		global config		if config["runthread"]: # Is the pump already being filled?			config["runthread"]=0 # Stop the filling			button[ident["buttonNozzle2"]]["text"] = "Squeese"			button[ident["buttonNozzle1"]]["enable"] = True		else:			#Start up the pumping class			config["runthread"]=1			thread = Filler()			thread.start()			button[ident["buttonNozzle2"]]["text"] = "Unsqueese"			button[ident["buttonNozzle1"]]["enable"] = False		self.UpdateUI()#Run the app!app = wx.App(0) frame = MainControl(None, -1, config["titlestart"])frame.Show(True)app.MainLoop()