TrafficLightAll.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. from Tkinter import *
  2. class TrafficLightGUI(Frame):
  3. def __init__(self, behaviour, master=None, title="TrafficLight"):
  4. self.behaviour=behaviour
  5. # Initialize superclass
  6. Frame.__init__(self, master)
  7. # parent frame, destruction protocol
  8. self.root=master
  9. self.root.protocol("WM_DELETE_WINDOW", self.wmQuit)
  10. # Initialize packer
  11. self.pack(fill=BOTH, expand=1)
  12. # Create all widgets in the Frame
  13. self.__createWidgets()
  14. def __createWidgets(self):
  15. self.root.configure(bg="black")
  16. # self.root.pack(side=LEFT, fill=BOTH, expand=1)
  17. Label(self.root, text="", bg="black",
  18. height=2, width=10).pack(side=TOP, padx = 2, pady=2)
  19. self.redLight=Label(self.root, text="", bg="red",
  20. relief=GROOVE, height=5, width=10)
  21. self.redLight.pack(side=TOP, padx = 2, pady=4)
  22. self.yellowLight=Label(self.root, text="", bg="black",
  23. relief=GROOVE, height=5, width=10)
  24. self.yellowLight.pack(side=TOP, padx = 2, pady=4)
  25. self.greenLight=Label(self.root, text="", bg="black",
  26. relief=GROOVE, height=5, width=10)
  27. self.greenLight.pack(side=TOP, padx = 2, pady=4)
  28. Label(self.root, text="",bg="black",
  29. height=5, width=10).pack(side=TOP,padx=2,pady=2)
  30. # Begin generated code
  31. Button(self.root, text="PoliceInterrupt",
  32. command=self.PoliceInterruptPressed, width=10, wraplength=70).pack(side=TOP, fill=Y, padx=5, pady=2)
  33. Button(self.root, text="Quit",
  34. command=self.QuitPressed, width=10, wraplength=70).pack(side=TOP, fill=Y, padx = 5, pady = 2)
  35. # End generated code
  36. # binding with behaviour
  37. # Begin generated code
  38. def PoliceInterruptPressed(self):
  39. self.behaviour.event("PoliceInterrupt")
  40. def QuitPressed(self):
  41. self.behaviour.event("Quit")
  42. # End generated code
  43. def wmQuit(self):
  44. self.root.destroy()
  45. # the behaviour can call these methods to change the GUI
  46. def setGreenOn(self):
  47. self.greenLight["bg"] = "green"
  48. def setGreenOff(self):
  49. self.greenLight["bg"] = "black"
  50. def setRedOn(self):
  51. self.redLight["bg"] = "red"
  52. def setRedOff(self):
  53. self.redLight["bg"] = "black"
  54. def setYellowOn(self):
  55. self.yellowLight["bg"] = "yellow"
  56. def setYellowOff(self):
  57. self.yellowLight["bg"] = "black"
  58. import sys
  59. class TrafficLightBehaviour:
  60. def __init__(self, scale=1):
  61. self.scale = scale
  62. self.currentState = None
  63. self.scheduledTIMEOUT = None
  64. def initModel(self, gui):
  65. self.gui = gui
  66. # Begin generated code
  67. self.initState = "red"
  68. self.gui.setYellowOff()
  69. self.gui.setGreenOff()
  70. self.gui.setRedOn()
  71. # If the target state has an outgoing timed transition,
  72. # upon entering that target state, a timeout needs to be scheduled.
  73. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  74. # before the timeout expires
  75. self.scheduledTIMEOUT = self.gui.after(self.scale*3000, self.eventTIMEOUT)
  76. # End generated code
  77. self.currentState = self.initState
  78. def eventTIMEOUT(self):
  79. self.event("TIMEOUT")
  80. def event(self, eventName):
  81. # Note that below, setting coloured lights can be optimized by checking source
  82. # and target light settings and only updating those lights that changed.
  83. # In the following, the more naieve approach of re-setting all lights is taken.
  84. # Remove a scheduled timeout, if any,
  85. # to ensure that if we interrupted a transition scheduled in the future
  86. # that scheduled transition is removed
  87. if self.scheduledTIMEOUT is not None:
  88. self.gui.after_cancel(self.scheduledTIMEOUT)
  89. self.scheduledTIMEOUT = None
  90. # Switch based on all states
  91. if False:
  92. pass
  93. # for all states in the automaton
  94. # Begin generated code
  95. elif self.currentState == "blinkYellow":
  96. if False:
  97. pass
  98. # For all transitions from this state
  99. elif eventName == "Quit":
  100. self.currentState = "quit" # target of the transition
  101. # The visual representation associated with the target state
  102. self.gui.setYellowOff()
  103. self.gui.setGreenOff()
  104. self.gui.setRedOff()
  105. elif eventName == "PoliceInterrupt":
  106. self.currentState = "red" # target of the transition
  107. # The visual representation associated with the target state
  108. self.gui.setYellowOff()
  109. self.gui.setGreenOff()
  110. self.gui.setRedOn()
  111. # If the target state has an outgoing timed transition,
  112. # upon entering that target state, a timeout needs to be scheduled.
  113. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  114. # before the timeout expires
  115. self.scheduledTIMEOUT = self.gui.after(self.scale*3000, self.eventTIMEOUT)
  116. elif eventName == "TIMEOUT":
  117. self.currentState = "blinkBlack" # target of the transition
  118. # The visual representation associated with the target state
  119. self.gui.setYellowOff()
  120. self.gui.setGreenOff()
  121. self.gui.setRedOff()
  122. # If the target state has an outgoing timed transition,
  123. # upon entering that target state, a timeout needs to be scheduled.
  124. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  125. # before the timeout expires
  126. self.scheduledTIMEOUT = self.gui.after(self.scale*500, self.eventTIMEOUT)
  127. else:
  128. print("ERROR: unexpected event %s received\n" % eventName)
  129. sys.exit(1)
  130. elif self.currentState == "blinkBlack":
  131. if False:
  132. pass
  133. # For all transitions from this state
  134. elif eventName == "Quit":
  135. self.currentState = "quit" # target of the transition
  136. # The visual representation associated with the target state
  137. self.gui.setYellowOff()
  138. self.gui.setGreenOff()
  139. self.gui.setRedOff()
  140. elif eventName == "PoliceInterrupt":
  141. self.currentState = "red" # target of the transition
  142. # The visual representation associated with the target state
  143. self.gui.setYellowOff()
  144. self.gui.setGreenOff()
  145. self.gui.setRedOn()
  146. # If the target state has an outgoing timed transition,
  147. # upon entering that target state, a timeout needs to be scheduled.
  148. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  149. # before the timeout expires
  150. self.scheduledTIMEOUT = self.gui.after(self.scale*3000, self.eventTIMEOUT)
  151. elif eventName == "TIMEOUT":
  152. self.currentState = "blinkYellow" # target of the transition
  153. # The visual representation associated with the target state
  154. self.gui.setYellowOn()
  155. self.gui.setGreenOff()
  156. self.gui.setRedOff()
  157. # If the target state has an outgoing timed transition,
  158. # upon entering that target state, a timeout needs to be scheduled.
  159. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  160. # before the timeout expires
  161. self.scheduledTIMEOUT = self.gui.after(self.scale*500, self.eventTIMEOUT)
  162. else:
  163. print("ERROR: unexpected event %s received\n" % eventName)
  164. sys.exit(1)
  165. elif self.currentState == "red":
  166. if False:
  167. pass
  168. # For all transitions from this state
  169. elif eventName == "Quit":
  170. self.currentState = "quit" # target of the transition
  171. # The visual representation associated with the target state
  172. self.gui.setYellowOff()
  173. self.gui.setGreenOff()
  174. self.gui.setRedOff()
  175. elif eventName == "PoliceInterrupt":
  176. self.currentState = "blinkYellow" # target of the transition
  177. # The visual representation associated with the target state
  178. self.gui.setYellowOn()
  179. self.gui.setGreenOff()
  180. self.gui.setRedOff()
  181. # If the target state has an outgoing timed transition,
  182. # upon entering that target state, a timeout needs to be scheduled.
  183. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  184. # before the timeout expires
  185. self.scheduledTIMEOUT = self.gui.after(self.scale*500, self.eventTIMEOUT)
  186. elif eventName == "TIMEOUT":
  187. self.currentState = "green" # target of the transition
  188. # The visual representation associated with the target state
  189. self.gui.setYellowOff()
  190. self.gui.setGreenOn()
  191. self.gui.setRedOff()
  192. # If the target state has an outgoing timed transition,
  193. # upon entering that target state, a timeout needs to be scheduled.
  194. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  195. # before the timeout expires
  196. self.scheduledTIMEOUT = self.gui.after(self.scale*2000, self.eventTIMEOUT)
  197. else:
  198. print("ERROR: unexpected event %s received\n" % eventName)
  199. sys.exit(1)
  200. elif self.currentState == "green":
  201. if False:
  202. pass
  203. # For all transitions from this state
  204. elif eventName == "Quit":
  205. self.currentState = "quit" # target of the transition
  206. # The visual representation associated with the target state
  207. self.gui.setYellowOff()
  208. self.gui.setGreenOff()
  209. self.gui.setRedOff()
  210. elif eventName == "PoliceInterrupt":
  211. self.currentState = "blinkYellow" # target of the transition
  212. # The visual representation associated with the target state
  213. self.gui.setYellowOn()
  214. self.gui.setGreenOff()
  215. self.gui.setRedOff()
  216. # If the target state has an outgoing timed transition,
  217. # upon entering that target state, a timeout needs to be scheduled.
  218. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  219. # before the timeout expires
  220. self.scheduledTIMEOUT = self.gui.after(self.scale*500, self.eventTIMEOUT)
  221. elif eventName == "TIMEOUT":
  222. self.currentState = "yellow" # target of the transition
  223. # The visual representation associated with the target state
  224. self.gui.setYellowOn()
  225. self.gui.setGreenOff()
  226. self.gui.setRedOff()
  227. # If the target state has an outgoing timed transition,
  228. # upon entering that target state, a timeout needs to be scheduled.
  229. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  230. # before the timeout expires
  231. self.scheduledTIMEOUT = self.gui.after(self.scale*1000, self.eventTIMEOUT)
  232. else:
  233. print("ERROR: unexpected event %s received\n" % eventName)
  234. sys.exit(1)
  235. elif self.currentState == "yellow":
  236. if False:
  237. pass
  238. # For all transitions from this state
  239. elif eventName == "Quit":
  240. self.currentState = "quit" # target of the transition
  241. # The visual representation associated with the target state
  242. self.gui.setYellowOff()
  243. self.gui.setGreenOff()
  244. self.gui.setRedOff()
  245. elif eventName == "PoliceInterrupt":
  246. self.currentState = "blinkYellow" # target of the transition
  247. # The visual representation associated with the target state
  248. self.gui.setYellowOn()
  249. self.gui.setGreenOff()
  250. self.gui.setRedOff()
  251. # If the target state has an outgoing timed transition,
  252. # upon entering that target state, a timeout needs to be scheduled.
  253. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  254. # before the timeout expires
  255. self.scheduledTIMEOUT = self.gui.after(self.scale*500, self.eventTIMEOUT)
  256. elif eventName == "TIMEOUT":
  257. self.currentState = "red" # target of the transition
  258. # The visual representation associated with the target state
  259. self.gui.setYellowOff()
  260. self.gui.setGreenOff()
  261. self.gui.setRedOn()
  262. # If the target state has an outgoing timed transition,
  263. # upon entering that target state, a timeout needs to be scheduled.
  264. # Keep track of scheduledTIMEOUT to be able to cancel it later if interrupted
  265. # before the timeout expires
  266. self.scheduledTIMEOUT = self.gui.after(self.scale*3000, self.eventTIMEOUT)
  267. else:
  268. print("ERROR: unexpected event %s received\n" % eventName)
  269. sys.exit(1)
  270. elif self.currentState == "quit":
  271. # if no outgoing transitions: no code generated
  272. pass
  273. # End generated code
  274. else:
  275. print("ERROR: unexpected currentState %s\n" % self.currentState)
  276. sys.exit(1)
  277. if __name__=="__main__":
  278. behaviour=TrafficLightBehaviour()
  279. root=Tk()
  280. # Initialize the GUI with the behaviour model as a parameter
  281. gui=TrafficLightGUI(behaviour, root)
  282. # Be sure to initialize the behaviour model after the GUI is created
  283. behaviour.initModel(gui)
  284. # The Tkinter main event loop
  285. root.mainloop()