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.

Asked By: george

||

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

Answered By: Peter Gibson

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()
Answered By: user3666197
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.