Matrix program, using binding in python to stop/start
Question:
I am trying to write a piece of code that will run a simple matrix replica, where it just randomly generate characters and prints them to a screen.
Writing the actual matrix part has been no problem and I am happy with the way I have done it, although I will welcome any suggestions to that part.
But the part I am stuck on is getting it to stop, once it has started.
Basically in pseudocode this is what I’m trying to do
IF PRESS == s:
matrix()
check press
IF PRESS == q:
END matrix()
The main difficulty I am getting is checking the key press while running the matrix code.
This is my code at the moment:
import tkinter as tk
from random import randint
global event
event=""
box = tk.Tk()
def matrix():
line = chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
print (line)
key(event)
def key(event):
box.focus_set()
while event.char == "s":
print("Matrix starting")
matrix()
if event.char == "q":
#stops matrix
print("Matrix stopped")
box.bind("<Key>", key)
box.mainloop()
Hopefully, someone will be able to help me, I have looked on the internet but I can not find what I am looking for.
Also when I have tried changing my code, the GUI has frozen and I am unable to do anything.
Answers:
Your key
function is called once for each key press event, but inside you have a while loop that never terminates:
while event.char == "s": # program gets stuck in this loop as event.char is
# always "s" for this function call
print("Matrix starting")
matrix()
An if
statement should suffice to fix the problem:
if event.char == "s":
print("Matrix starting")
matrix()
if event.char == "q":
#stops matrix
print("Matrix stopped")
In order to print multiple lines, you should modify your matrix function to use a for
loop:
def matrix():
for i in range(10):
line = chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
print (line)
You probably don’t want matrix to call key(event)
as this could also get you into an infinite loop
You can create the logic based on Tkinter strengths
Added a repeating delay, as you asked in a comment below.
Added a Stateful Control ( { nil->[S]tartedSTATE->[Q]uit->nil }
) to block/avoid nonsense sequences
Added a few Tkinter details.
You might want to limit the scope of chr()
as not all characters in the original range are "printable" and you bear a risk of unwanted side-effects.
try:
import Tkinter as tk
import tkMessageBox
except:
import tkinter as tk
import tkinter.messagebox as tkMessageBox
from random import randint
global event # global is possible, designing a Class is better though
event = "" # no need to assign <event>
global box
box = tk.Tk() # Tkinter top-level instance
box.aDelayInMSEC = 30000 # .SET an attribute, repeat each 30 sec
box.inStartedSTATE = False # .SET an attribute, a stateful control
box.title( "MATRIX Reloaded ... " ) # Tkinter beautifier
box.protocol( 'WM_DELETE_WINDOW', ExitPROCESS ) # [X]-overide ------------------------
box.lift() # GUI make visible
def matrix():
line = chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
print (line)
box.after( box.aDelayInMSEC, matrix ) # re-schedule a next round .after()
def StartMATRIX( anEvent ):
if not box.inStartedSTATE: # .IF( not STARTED-already )
print( "Matrix starting" ) # .UI
box.inStartedSTATE = True # .SET state
matrix() # .CALL
pass
def StopMATRIX( anEvent ):
if box.inStartedSTATE: # .IF( was STARTED-before )
print( "Matrix stopped" ) # .UI
box.inStartedSTATE = False # .SET state
ExitPROCESS() # .CALL
pass
def ExitPROCESS(): # MVC-Controller-Part ..
if tkMessageBox.askokcancel( "Quit GUI", "Do you really wish to quit?" ):
box.destroy()
pass
box.bind( "<KeyPress-s>", StartMATRIX ) # .BIND StartMATRIX()-HANDLER
box.bind( "<Shift-KeyPress-s>", StartMATRIX ) # .BIND StartMATRIX()-HANDLER
box.bind( "<KeyPress-q>", StopMATRIX ) # .BIND StopMATRIX()-HANDLER
box.bind( "<Shift-KeyPress-q>", StopMATRIX ) # .BIND StopMATRIX()-HANDLER
box.mainloop()
I am trying to write a piece of code that will run a simple matrix replica, where it just randomly generate characters and prints them to a screen.
Writing the actual matrix part has been no problem and I am happy with the way I have done it, although I will welcome any suggestions to that part.
But the part I am stuck on is getting it to stop, once it has started.
Basically in pseudocode this is what I’m trying to do
IF PRESS == s:
matrix()
check press
IF PRESS == q:
END matrix()
The main difficulty I am getting is checking the key press while running the matrix code.
This is my code at the moment:
import tkinter as tk
from random import randint
global event
event=""
box = tk.Tk()
def matrix():
line = chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
print (line)
key(event)
def key(event):
box.focus_set()
while event.char == "s":
print("Matrix starting")
matrix()
if event.char == "q":
#stops matrix
print("Matrix stopped")
box.bind("<Key>", key)
box.mainloop()
Hopefully, someone will be able to help me, I have looked on the internet but I can not find what I am looking for.
Also when I have tried changing my code, the GUI has frozen and I am unable to do anything.
Your key
function is called once for each key press event, but inside you have a while loop that never terminates:
while event.char == "s": # program gets stuck in this loop as event.char is
# always "s" for this function call
print("Matrix starting")
matrix()
An if
statement should suffice to fix the problem:
if event.char == "s":
print("Matrix starting")
matrix()
if event.char == "q":
#stops matrix
print("Matrix stopped")
In order to print multiple lines, you should modify your matrix function to use a for
loop:
def matrix():
for i in range(10):
line = chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
print (line)
You probably don’t want matrix to call key(event)
as this could also get you into an infinite loop
You can create the logic based on Tkinter strengths
Added a repeating delay, as you asked in a comment below.
Added a Stateful Control ( { nil->[S]tartedSTATE->[Q]uit->nil }
) to block/avoid nonsense sequences
Added a few Tkinter details.
You might want to limit the scope of chr()
as not all characters in the original range are "printable" and you bear a risk of unwanted side-effects.
try:
import Tkinter as tk
import tkMessageBox
except:
import tkinter as tk
import tkinter.messagebox as tkMessageBox
from random import randint
global event # global is possible, designing a Class is better though
event = "" # no need to assign <event>
global box
box = tk.Tk() # Tkinter top-level instance
box.aDelayInMSEC = 30000 # .SET an attribute, repeat each 30 sec
box.inStartedSTATE = False # .SET an attribute, a stateful control
box.title( "MATRIX Reloaded ... " ) # Tkinter beautifier
box.protocol( 'WM_DELETE_WINDOW', ExitPROCESS ) # [X]-overide ------------------------
box.lift() # GUI make visible
def matrix():
line = chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
+ chr(randint(0,127)) + "t" + chr(randint(0,127)) + "t"
print (line)
box.after( box.aDelayInMSEC, matrix ) # re-schedule a next round .after()
def StartMATRIX( anEvent ):
if not box.inStartedSTATE: # .IF( not STARTED-already )
print( "Matrix starting" ) # .UI
box.inStartedSTATE = True # .SET state
matrix() # .CALL
pass
def StopMATRIX( anEvent ):
if box.inStartedSTATE: # .IF( was STARTED-before )
print( "Matrix stopped" ) # .UI
box.inStartedSTATE = False # .SET state
ExitPROCESS() # .CALL
pass
def ExitPROCESS(): # MVC-Controller-Part ..
if tkMessageBox.askokcancel( "Quit GUI", "Do you really wish to quit?" ):
box.destroy()
pass
box.bind( "<KeyPress-s>", StartMATRIX ) # .BIND StartMATRIX()-HANDLER
box.bind( "<Shift-KeyPress-s>", StartMATRIX ) # .BIND StartMATRIX()-HANDLER
box.bind( "<KeyPress-q>", StopMATRIX ) # .BIND StopMATRIX()-HANDLER
box.bind( "<Shift-KeyPress-q>", StopMATRIX ) # .BIND StopMATRIX()-HANDLER
box.mainloop()