Building a built-in text field for turtle, while statement doesn't work

你离开我真会死。 提交于 2020-02-05 09:54:46

问题


I have built a text field module that has one problem: why does Python IDLE not work for while...break statements?

Originally I didn't have a break statement and this didn't work so I added the break statement and the same problems persisted.

This is a long script. You will need everything in it. Do not run in repl.it, as it will not run. However it does run on IDLE.

https://repl.it/@SUPERMECHM500/TextField

As commented in the script, the while statement at line 610 doesn't load on IDLE, and the break doesn't work as expected: Continue the code if the TextField.FullOutput object has text.

None of my problems relate to repl.it so don't mention it in your answers. Run and debug this script as a Text file from python IDLE.


回答1:


First, a few minor issues:

def listenforkeys(bool):

bool is a Python keyword, choose a different variable name. (E.g. flag.) This or doesn't work the way you think:

if TextField.FullOutput and TextField.inp != "" or []:

Reread about or. Don't use the same turtle for TextField implementation that you use for TextField utilization as this statement:

t.clear()

wipes out all the actions done with t by user of TextField. Use a different turtle. Finally, your call to mainloop() is in the wrong place. Once you invoke it, your code stops and the tkinker event handler takes over. It generally should be the last thing your code des.

Now the main issue, this utilization code:

while TextField.FullOutput == "": #Hope this works with Windows IDLE...
  tm.sleep(0.1)
  print("Waiting for input...")
  if TextField.FullOutput != "":
    print('Data sent to RAM.')
    break

Don't loop waiting on the buffer to fill. This really should be an event, but at least a callback. I've rewritten your code below to make this a callback, see the Enter() function and example usage code. It now works for me in IDLE and at the command prompt. I've also made lots of other little changes to try to clean it up a bit -- some of these may need further testing...

# Text field that can be used universally.
# Created by SUPERMECHM500 @ repl.it
# Full functionallity can only be achieved by using IDLE on Windows.

from turtle import Screen, Turtle, mainloop

class TextField:
    TextFieldBorderColor = '#0019fc'
    TextFieldBGColor = '#000000'
    TextFieldTextColor = '#ffffff'

    ShiftedDigits = {'1':'!', '2':'@', '3':'#', '4':'$', '5':'%', '6':'^', '7':'&', '8':'*', '9':'(', '0':')'}

    def __init__(self, callBack=None):
        self.callBack = callBack
        self.turtle = Turtle(visible=False)
        self.turtle.speed('fastest')
        self.inp = []
        self.FullOutput = ""
        self.TextSeparation = 7
        self.s = self.TextSeparation
        self.key_shiftL = False

    def DrawTextField(self, Title):
        t = self.turtle
        t.pensize(1)
        t.color(TextField.TextFieldBorderColor)
        t.pu()
        t.goto(-200, -190)
        t.write(Title)
        t.goto(-200, -200)
        t.pd()
        t.goto(200, -200)
        t.goto(200, -250)
        t.goto(-200, -250)
        t.goto(-200, -200)
        t.pu()
        t.goto(-200, -225)
        t.color(TextField.TextFieldBGColor)
        t.pensize(48)
        t.pd()
        t.forward(400)
        t.pu()
        t.goto(-190, -220)
        t.color(TextField.TextFieldTextColor)

    # Defines the function for each defined key.
    def ShiftLON(self):
        print("Capslock toggled.")
        self.key_shiftL = not self.key_shiftL

    def Space(self):
        self.turtle.write(' ')
        self.inp.append(' ')
        self.turtle.forward(self.s)

    def Backspace(self):
        try:
            self.inp.pop(-1)
        except IndexError:
            print("Cannot backspace!")
        else:
            t = self.turtle
            t.pensize(15)
            t.color(TextField.TextFieldBGColor)
            t.forward(10)
            t.backward(self.TextSeparation)
            t.shape('square')
            t.pd()
            t.turtlesize(1.3)  # <<< Doesn't work on repl.it
            t.stamp()
            t.pu()
            t.color(TextField.TextFieldTextColor)
            t.shape('classic')
            t.backward(10)

    def Period(self):
        if self.key_shiftL:
            self.turtle.write('>')
            self.inp.append('>')
            self.turtle.forward(self.s)
        else:
            self.turtle.write('.')
            self.inp.append('.')
            self.turtle.forward(self.s)

    def Comma(self):
        if self.key_shiftL:
            self.turtle.write('<')
            self.inp.append('<')
            self.turtle.forward(self.s)
        else:
            self.turtle.write(',')
            self.inp.append(',')
            self.turtle.forward(self.s)

    def Enter(self):
        if self.inp != []:
            print("Joining input log...")
            self.turtle.pu()
            self.FullOutput = ''.join(self.inp)
            print('joined.')
            print(self.FullOutput)
            print("Output printed.")

            try:
                self.callBack(self.FullOutput)
                print("Data sent to callback.")
            except NameError:
                print("No callback defined.")

            self.turtle.clear()
            print("Display cleared.")

    def digit(self, d):
        if self.key_shiftL:
            d = TextField.ShiftedDigits[d]

        self.turtle.write(d)
        self.inp.append(d)
        self.turtle.forward(self.s)

    def letter(self, abc):
        if self.key_shiftL:
            abc = abc.upper()

        self.turtle.write(abc)
        self.inp.append(abc)
        self.turtle.forward(self.s)

    def listenforkeys(self, flag):  # Whether or not keys are being used for text field.
        s = Screen()

        if not flag:
            for character in 'abcdefghijklmnopqrstuvwxyz':
                s.onkey(None, character)

            for digit in '0123456789':
                s.onkey(None, digit)

            s.onkey(None, 'period')
            s.onkey(None, 'comma')
            s.onkey(None, 'Shift_L')

            # s.onkeyrelease(None, 'Shift_L')

            s.onkey(None, 'space')
            s.onkey(None, 'BackSpace')
            s.onkey(None, 'Return')

            if self.FullOutput or self.inp:
                self.FullOutput = ""  # Reset the text field content
            self.inp = []  # Reset input log

            print("Stopped listening.")

        if flag:
            for character in 'abcdefghijklmnopqrstuvwxyz':
                s.onkey(lambda abc=character: self.letter(abc), character)

            for character in '1234567890':
                s.onkey(lambda d=character: self.digit(d), character)

            s.onkey(self.Period, 'period')
            s.onkey(self.Comma, 'comma')
            s.onkey(self.ShiftLON, 'Shift_L')

            # s.onkeyrelease(self.ShiftLON, 'Shift_L')

            s.onkey(self.Space, 'space')
            s.onkey(self.Backspace, 'BackSpace')
            s.onkey(self.Enter, 'Return')

            s.listen()

            print("Listening.")

if __name__ == "__main__":

    def text_callback(text):
        print("Data received by callback.")
        textField.listenforkeys(False)
        turtle.pu()
        print("Pen up.")
        turtle.write(text, align='center', font=('Arial', 30, 'normal'))
        print("Text written.")

    screen = Screen()
    screen.setup(500, 500)

    textField = TextField(text_callback)
    textField.DrawTextField("Enter Text. Note: Shift is capslock. Capslock disables your keys.")
    print("Text field drawn.")

    textField.listenforkeys(True)
    print("Can type.")

    turtle = Turtle(visible=False)

    mainloop()


来源:https://stackoverflow.com/questions/54634919/building-a-built-in-text-field-for-turtle-while-statement-doesnt-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!