📄 telephone.py
字号:
#!/usr/bin/env python# -*- tab-width: 4; -*-## The contents of this file are subject to the Mozilla Public# License Version 1.1 (the "License"); you may not use this file# except in compliance with the License. You may obtain a copy of# the License at http://www.mozilla.org/MPL/## Software distributed under the License is distributed on an "AS# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or# implied. See the License for the specific language governing# rights and limitations under the License.## The Original Code is State Machine Compiler (SMC).## The Initial Developer of the Original Code is Charles W. Rapp.# Portions created by Charles W. Rapp are# Copyright (C) 2000 - 2003 Charles W. Rapp.# All Rights Reserved.## Contributor(s):# Port to Python by Francois Perrad, francois.perrad@gadz.org## Name# telephone.py## Description# A simulation of an old fashioned touch-tone telephone.## RCS ID# $Id: telephone.py,v 1.2 2005/06/08 11:09:13 cwrapp Exp $## CHANGE LOG# $Log: telephone.py,v $# Revision 1.2 2005/06/08 11:09:13 cwrapp# + Updated Python code generator to place "pass" in methods with empty# bodies.# + Corrected FSM errors in Python example 7.# + Removed unnecessary includes from C++ examples.# + Corrected errors in top-level makefile's distribution build.## Revision 1.1 2005/05/28 17:48:30 cwrapp# Added Python examples 1 - 4 and 7.##import sys, timefrom Tkinter import *import Telephone_smclass Telephone: LONG_DISTANCE = 1 LOCAL = 2 EMERGENCY = 3 NYC_TEMP = 4 TIME = 5 DEPOSIT_MONEY = 6 LINE_BUSY = 7 INVALID_NUMBER = 8 SEC_PER_MINUTE = 60 def __init__(self, root): self._root = root self._areaCode = "" self._exchange = "" self._local = "" self._display = "" self._receiverButton = None self._timerMap = { 'ClockTimer': -1, 'OffHookTimer': -1, 'LoopTimer': -1, 'RingTimer': -1, } self._timerAudioID = -1 self._loadUI() # Create the state machine to drive this object. self._fsm = Telephone_sm.Telephone_sm(self) # DEBUG #self._fsm.setDebugFlag(True) # Create the user interface but don't display it yet. def _loadUI(self): self._root.title("Telephone demo") frameDisplay = Frame(self._root) frameDisplay.pack( side=TOP, fill=BOTH, ) # Create the read-only phone number display. self._numberDisplay = Label(frameDisplay, width=30, bg='white', relief=SUNKEN, padx=5, pady=5, ) self._numberDisplay.pack( side=TOP, padx=5, pady=5, ) frameHook = Frame(self._root) frameHook.pack( side=TOP, expand=1, ) # Create the off-hook/on-hook button. def onReceiver(): text = self._receiverButton.cget('text') if text == "Pick up receiver": self._fsm.OffHook() elif text == "Put down receiver": self._fsm.OnHook() else: sys.stderr.write("Unknown receiver (%s).\n" % text) self._receiverButton = Button(frameHook, text="Pick up receiver", state=NORMAL, command=onReceiver, padx=10, pady=5, bd=3, ) self._receiverButton.pack( side=TOP, padx= 5, pady= 5, ) frameDial = Frame(self._root) frameDial.pack( side=TOP, fill=BOTH, padx=5, pady=5, ) # Create the dialing buttons. i = 0 for digit in ("123456789*0#"): b = Button(frameDial, text=digit, height=2, width=3, command=lambda digit=digit: self._fsm.Digit(digit), ) b.grid( row=i/3, column=i%3, padx=1, pady=1, ) i += 1 frameStatus = Frame(self._root) frameStatus.pack( side=TOP, fill=BOTH, ) self._soundDisplay = Label(frameStatus, relief=GROOVE, ) self._soundDisplay.pack( side=TOP, fill='x', expand=1, anchor='s', ) # Cntl-C stops the demo as well. self._root.bind('<Control-c>', lambda x: sys.exit(0)) #----------------------------------------------------------- # State Machine Actions. # # Return the current area code. def getAreaCode(self): return self._areaCode # Return the exchange. def getExchange(self): return self._exchange # Return the local number. def getLocal(self): return self._local def routeCall(self, callType, areaCode, exchange, local): if callType == self.EMERGENCY: route = self.EMERGENCY elif (callType == self.LONG_DISTANCE and areaCode == "1212" and exchange == "555" and local == "1234"): route = self.NYC_TEMP elif exchange == "555": if local == "1212": route = self.TIME else: route = self.LINE_BUSY elif callType == self.LOCAL: route = self.DEPOSIT_MONEY else: route = self.INVALID_NUMBER # Call routing needs to be done asynchronouzly in order to # avoid issuing a transition within a transition. self._root.after(50, lambda: self._callRoute(route)) def startTimer(self, name, delay): if name == "ClockTimer": self._timerMap[name] = self._root.after(delay, lambda: self._fsm.ClockTimer()) elif name == "OffHookTimer": self._timerMap[name] = self._root.after(delay, lambda: self._fsm.OffHookTimer()) elif name == "LoopTimer": self._timerMap[name] = self._root.after(delay, lambda: self._fsm.LoopTimer()) elif name == "RingTimer": self._timerMap[name] = self._root.after(delay, lambda: self._fsm.RingTimer()) def resetTimer(self, name, delay): if self._timerMap[name] >= 0: self._root.after_cancel(self._timerMap[name]) self._timerMap[name] = -1; self.startTimer(name, delay) def stopTimer(self, name): if self._timerMap[name] >= 0: self._root.after_cancel(self._timerMap[name]) self._timerMap[name] = -1; def play(self, name, delay): def endPlay(): self._soundDisplay.configure(text="") self._timerAudioID = -1 if self._timerAudioID >= 0: self._root.after_cancel(self._timerAudioID) self._timerAudioID = -1 self._soundDisplay.configure(text=name) self._timerAudioID = self._root.after(delay, endPlay) def playTT(self, name): self.play(name, 400) def loop(self, name): if self._timerAudioID >= 0: self._root.after_cancel(self._timerAudioID) self._timerAudioID = -1 self._soundDisplay.configure(text=name + " ...") def stopLoop(self, name): self._soundDisplay.configure(text="") def stopPlayback(self): if self._timerAudioID >= 0: self._root.after_cancel(self._timerAudioID) self._timerAudioID = -1 self._soundDisplay.configure(text="") def playEmergency(self): self.play("911", 5000) def playNYCTemp(self): self.play("NYC_temp", 2000) def playDepositMoney(self): self.play("50_cents_please", 2000) def playTime(self): self.play("the_time_is ???", 2000) def playInvalidNumber(self): self.play("you_dialed ### could_not_be_completed", 2000) def getType(self): return self._callType def setType(self, type): self._callType = type def saveAreaCode(self, n): self._areaCode += n self.addDisplay(n) def saveExchange(self, n): self._exchange += n self.addDisplay(n) def saveLocal(self, n): self._local += n self.addDisplay(n) def addDisplay(self, character): self._display += character self._numberDisplay.configure(text=self._display) def clearDisplay(self): #Clear the internal data store. self._display = "" self._areaCode = "" self._local = "" self._exchange = "" # Put up the current time and date on the display. self._numberDisplay.configure(text="") def startClockTimer(self): currentTime = int(time.time()) timeRemaining = self.SEC_PER_MINUTE - (currentTime % self.SEC_PER_MINUTE) # Figure out how long until the top of the minute # and set the timer for that amount. self.startTimer("ClockTimer", timeRemaining * 1000) def updateClock(self): text = time.strftime("%H:%M %b %d, %Y", time.localtime(time.time())) self._numberDisplay.configure(text=text) def setReceiver(self, text): self._receiverButton.configure(text=text) def _callRoute(self, route): if route == self.EMERGENCY: self._fsm.Emergency() elif route == self.NYC_TEMP: self._fsm.NYCTemp() elif route == self.TIME: self._fsm.Time() elif route == self.DEPOSIT_MONEY: self._fsm.DepositMoney() elif route == self.LINE_BUSY: self._fsm.LineBusy() elif route == self.INVALID_NUMBER: self._fsm.InvalidNumber()# Display the "telephone" user interface and run until# the user quits the window.root = Tk()tel = Telephone(root)root.mainloop()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -