Laura
Laura

Reputation: 13

How to allow user input on tkinter?

Hi I'm a beginner in Python and I'm working on a chatbot interface using tkinter. The problem i'm having is that I can't seem to type in the window after asking “Hi there, what’s your name?”. Instead, the conversation continues to the next line, stating Hi (the first entry stated) would you like to purchase a ticket?

Is there a way to allow user to enter their name, then after that, state the entry?

For example:

User: Hi

Bot: Hi there, what’s your name?

User: Tom

Bot: Hi Tom, would you like to purchase a ticket?

At the moment the program goes like this:

User: hi

Bot: Hi there, what’s your name?

Bot: Hi hi would you like to purchase a ticket?

I'm not sure what is causing the Bot to state another statement, before allowing user input, I've thought of storing name in name_var using StringVar(), then use that variable in the next line, but that didn't work.. any ideas how to fix this?

This is the code I have so far:


# Representing the parent window
root = Tk() 

#Title of window
root.title('Chatbot') 

#Function to send the message 
def send(): 
send = "You =>" + entry.get() 
text.insert(END, "\n" + send) if(entry.get()=="Hi" or entry.get()=="hi" or entry.get()=="Hi there" or entry.get()=="hi there" or entry.get()=="Hello" or entry.get()== "hello"):
text.insert(END, "\n" + "Bot => Hi there, whats your name ?") 
name_var = str(StringVar()) 
text.insert(END, "\n" + "Bot => Hi " + name_var + " would you like to purchase a ticket?") 
else: 
text.insert(END, "\n" + "Bot => Sorry, I have no answer") 
entry.delete(0, END) text = Text(root) 

# Adding dimensions and send button of window 
text.grid(row=0, column=0, columnspan=2) 
entry = Entry(root, width=100) 
send = Button(root, text="Send", command=send).grid(row=1, column=1) entry.grid(row=1, column=0)
root.mainloop()```

Upvotes: 1

Views: 344

Answers (1)

tobias_k
tobias_k

Reputation: 82889

In your send callback, you just add the two messages right after another, without waiting for user input in between. Instead, you could split that in two: A generator function, yielding the next line in a complex conversation tree, and the send message just caring about putting that next message into the text field:

from tkinter import *

def message_generator():
    if entry.get().lower() in ("hi", "hi there", "hello"):
        # ask for name
        yield "Hi there, whats your name ?"
        # greeting with name
        name_var = entry.get()
        yield "Hi " + name_var + " would you like to purchase a ticket?" 
        # more conversation, possibly with diverging branches
        # if entry.get() == "yes": ...
    else: 
        yield "Sorry, I have no answer"

def send(): 
    text.insert(END, "\nYou =>" + entry.get())
    text.insert(END, "\nBot =>" + next(msg_gen))
    entry.delete(0, END)

msg_gen = message_generator()
    
root = Tk() 
root.title('Chatbot') 
text = Text(root) 
text.grid(row=0, column=0, columnspan=2) 
entry = Entry(root, width=100) 
entry.grid(row=1, column=0)
Button(root, text="Send", command=send).grid(row=1, column=1)
root.mainloop()

The main point here is that the message_generator will not be executed fully. When you first call the function, it just creates a generator instance; then when you call next in send, it executes the generator function up to the next yield statement and pauses there, picking up execution from that same point the next time next is called, thus providing a nice way to keep track of the current state of the conversation.

Upvotes: 1

Related Questions