1

I'm trying to be able to move a dot around the matplotlib plot using the w, a, s, and d keys without having to hit enter each time after I type the letter. This works using readchar.readchar(), but then the plot does not show up. What am I doing wrong?

""" Moving dot """
import matplotlib.pyplot as plt
import time
import readchar

x = 0
y = 0
q = 0
e = 0
counter = 0
while 1 :
    #arrow_key = input()
    arrow_key = readchar.readchar()
    print(x,y)
    if arrow_key == "d" :
        q = x + 1
    elif arrow_key == "a" :
        q = x - 1
    elif arrow_key == "w" :
        e = y + 1
    elif arrow_key == "s" :
        e = y - 1
    plt.ion()   
    plt.plot(x,y, "wo", markersize = 10)
    plt.plot(q,e, "bo")
    plt.xlim(-10,10)
    plt.ylim(-10,10)
    x = q
    y = e

1 Answer 1

1

The first problem in your code is that the readchar.readchar() returns binary strings. You need to decode it to utf-8: arrow_key = readchar.readchar().lower().decode("utf-8")

I'd say it's best that you do the plt.xlim() and plt.ylim() limitations before the while loop.

My plt froze if I wasn't using plt.pause(). I added multiple plt.pause(0.0001) to get the code working. reference: Matplotlib ion() function fails to be interactive

Also, you required user input in your code before showing the plot. I changed it to the plot showing before user input.

Changing x to be q and y to be e is best done before input. It being after the input caused the previous plots to show for me.

EDIT: as FriendFX suggested below, it's good to define the plots as variables (pl1 = plt.plot(x,y, "wo", markersize = 10) and pl2 = plt.plot(q,e, "bo")) and delete them after use to not fill the memory. pl1.pop(0).remove() and pl2.pop(0).remove()

Full repaired code below. Note that in startup you may lose terminal window focus, which is critical for the input.

import matplotlib.pyplot as plt
import time # you didn't use this, do you need it?
import readchar

x = 0
y = 0
q = 0
e = 0
plt.xlim(-10,10)
plt.ylim(-10,10)

counter = 0 # you didn't use this, do you need it?
while(1):
    plt.ion()
    plt.pause(0.0001)
    pl1 = plt.plot(x,y, "wo", markersize = 10)
    pl2 = plt.plot(q,e, "bo")
    plt.pause(0.0001)
    plt.draw()
    plt.pause(0.0001)
    x = q
    y = e

    arrow_key = readchar.readchar().lower().decode("utf-8")
    print(arrow_key)

    if arrow_key == "d" :
        q = x + 1
    elif arrow_key == "a" :
        q = x - 1
    elif arrow_key == "w" :
        e = y + 1
    elif arrow_key == 's' :
        e = y - 1
    print(q, e, x, y)
    pl1.pop(0).remove()
    pl2.pop(0).remove()
Sign up to request clarification or add additional context in comments.

2 Comments

Nice one. Depending on what the OP needs, it may also be helpful to delete existing plot points with lines.pop(0).remove() as stated in this answer, where lines is a variable storing the output of one (or both) of the plt.plot() calls, e.g. line = plot.plot(q,e, "bo"). Also, I don't think the show() call is required in the loop.
@FriendFX You're right. Added your suggestions and deleted the plt.show()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.