I am new to Python. I'm having trouble executing an IF with a function inside. I enclose the code, including the graphic interface in Tkinter. In the same algorithm, I was wrong and i have difficulty in 2 things: write the correct IF conditions, and correctly call the Function inside IF, that is:
if categorias == "Phrase of love" and sottocategorias == "Short sentences":
phrase_example
(it's written with errors, I know)
I would like to do that: if in the combobox1 (Categorys) I select the "Phrase of love" item, and then in the combobox2 (Subcategorias) I select the "Short sentences" item (selected both, at the same time, from the two comboboxes) ... then I click on the button and the Function is called (the code has already been written). The task of the Function, as you can see, is to print sentences (from the database) in the multiline textbox.
I looked for other similar questions to avoid asking questions, but didn't understand much considering I just got started with Python. Can you show me where I'm wrong by showing me the correct IF code and Function code? Thank you
from tkinter import *
from tkinter import ttk
import tkinter as tk
import sqlite3
window=Tk()
window.title("Test")
window.geometry("700x700")
window.configure(bg='#78c030')
### BUTTON ###
def phrase_example(): # setting this to button 2
cursor.execute('SELECT phrase2, phrase3 FROM allphrase ORDER BY RANDOM() LIMIT
1')
word2,word3 = cursor.fetchone()
text.delete(1.0,END)
text.insert(tk.END,f"{word2} {word3}")
if categorias == "Phrase of love" and sottocategorias == "Short sentences":
phrase_example
button2 = Button(window, text="Button2", bg='white', command = phrase_example)
button2.pack()
button2.place(x=5, y=330)
### TEXTBOX MULTILINE ###
text = Text(window,width=63,height=38)
text.pack()
text.place(x=180, y=24)
### CATEGORIA E SOTTOCATEGORIA ###
cat=StringVar()
sub_cat=StringVar()
def change_val(*args):
if cat.get() == "Phrase of love":
sottocategorias = ["Short sentences", "Long sentences", "Medium sentences"]
sottocategoria.config(values=sottocategorias)
else:
sottocategorias = ["aaaa"]
sottocategoria.config(values=sottocategorias)
categorias=["Phrase of love", "Phrase of life", "Phrase of spiritual"]
categoria=ttk.Combobox(window,value=categorias,textvariable=cat,width=16)
categoria.place(x=5, y=25)
cat.set("Scegliere categoria")
sottocategorias=["aaaa"]
sottocategoria=ttk.Combobox(window,textvariable=sub_cat,value=sottocategorias,
width=16)
sottocategoria.place(x=5, y=55)
cat.trace("w",change_val)
con = sqlite3.connect('/home/mypc/Scrivania/Test/Database.db')
cursor = con.cursor()
window.mainloop()
You can do the IF checking inside phrase_example().
Also you need to use categoria.get() == ... and sottocategoria.get() == ... instead of categorias == ... and sottocategorias == ...:
def phrase_example():
if categoria.get() == "Phrase of love" and sottocategoria.get() == "Short sentences":
cursor.execute('SELECT phrase2, phrase3 FROM allphrase ORDER BY RANDOM() LIMIT 1')
word2,word3 = cursor.fetchone()
text.delete(1.0,END)
text.insert(tk.END,f"{word2} {word3}")
Related
This question already has answers here:
How can I schedule updates (f/e, to update a clock) in tkinter?
(8 answers)
Closed 1 year ago.
I am making a responce bot in python with tkinter. For that when user inputs something I will give answer.
I have not yet completed it. I wanted that the bot should answer after some-time so it looks very nice.
My code:-
import tkinter
from tkinter import Message, messagebox
from tkinter import font
from tkinter.constants import CENTER, LEFT, RIGHT, BOTTOM, TOP
from tkinter import scrolledtext
from typing import Sized
import time
window = tkinter.Tk()
window.geometry("370x500")
window.configure(bg="orange")
#variables
running = True
verdana_12 = ('Verdana', '12')
verdana_10 = ('Verdana', '10')
verdana_9 = ('Verdana', '9')
msg=tkinter.StringVar()
#messages
greetings = ["hi", "hello", "hey", "what's up!"]
questions = [
' 1. What is python?',
' 2. Where to ask questions if I get stuck?',
' 3. How can I get example questions and quizes related to python?'
]
#items inb gui
info_text = tkinter.Label(window, text="Chat", bg="orange", font=verdana_12)
info_text.pack(padx=20, pady=5)
text_1 = tkinter.Label(window, text="Type your message: ", font=verdana_9, bg="orange")
text_1.place(x=0, y=476)
input_area = tkinter.Entry(window, justify=LEFT, textvariable=msg, font=verdana_12, width=16)
input_area.focus_force()
input_area.place(x=135, y=476)
chat_area = scrolledtext.ScrolledText(window)
chat_area.pack(padx=20, pady=5)
chat_area.config(state = "disabled")
#define message
message = f"You: {input_area.get()}\n"
#functions
#def afterwards():
# mine_msg = message.lower().strip().split()[1]
# if 1 == mine_msg:
# reply("Bot: Python is an interpreted high-level general-purpose programming language. Python's design philosophy emphasizes code readability with its notable use of significant indentation. More info at https://en.wikipedia.org/wiki/Python_(programming_language)")
#
# elif 2 == mine_msg:
# reply("Bot: If you get stuck in python programming, go to stackoverflow.com where you can ask questions related to any programming language!")
#
# elif 3 == mine_msg:
# reply("Bot: You can get quizes related to python in w3schools.org and example questions in w3resource.org.")
def reply(reply_msg):
str(reply_msg)
the_reply = f"{reply_msg}\n" #input_area = where person types.
chat_area.config(state='normal')
chat_area.insert(tkinter.INSERT, the_reply)
chat_area.yview('end')
chat_area.config(state='disabled')
input_area.delete(0, 'end')
def check_msg():
global message
print('Message =', message.strip())
try:
mine_msg = message.lower().strip().split()[1]
if greetings[0] == mine_msg or greetings[1] == mine_msg or greetings[2] == mine_msg or greetings[3] == mine_msg:
reply("Bot: Hello, here's how I can help you")
for i in questions:
reply(i)
#afterwards()
else:
reply("Bot: Couldn't understand your message, please type 'hi', 'hello', 'hey' or 'what's up!' to get responce.")
except IndexError:
pass
def write():
global message
if len(input_area.get().split()) > 0:
message = f"You: {input_area.get()}\n" #input_area = where person types.
chat_area.config(state='normal')
chat_area.insert(tkinter.INSERT, message)
chat_area.yview('end')
chat_area.config(state='disabled')
input_area.delete(0, 'end')
check_msg()
else:
reply('Please type something.')
def print_it():
message = f"You: {input_area.get()}"
print(message)
#button_send
send_button = tkinter.Button(window, text="Send", command=write, font=verdana_10, bg="gray", fg="white", width=26, height=1)
send_button.pack(padx=20, pady=5)
window.mainloop()
It freezes everything for 0.5 instead I want it to freeze only the write() function. Any help please.
Thank you!
One way to achieve this would be to use the .after method from tkinter to delay the message from being replied to for a period of time.
i = "My Message"
window.after(1000,lambda i=i: reply(i))
This would call the reply function with the message "My Message" after 1000ms or 1 second.
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()```
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.
I've made a simple GUI in Tkinter.(Code is below)
When I press the "Fetch" botton than I get the text input from the GUI in a Command line.
Let's say that in this example the "user" is putting 0.5 in the "Service Points Won" field and 0.7 in the " Return Points Won" field as input.
When I press the "Fetch" botton I get the following results displayed in command prompt
0.5
0.7
What I would like to achieve is that next to the displayed result in command prompt the matching "Label" is also displayed.
So to return to my example with 0.5 and 0.7 as input. I want to get a result in command prompt as followed.
"Service Points Won" 0.5
"Return Points Won" 0.7
GUI Script
from Tkinter import *
fields = 'Service Points Won', 'Return Points Won'
def fetch(variables):
for variable in variables:
print "%s" % variable.get()
def makeform(root, fields):
lab1= Label(text="Stats", font="Verdana 10 bold")
form = Frame(root)
left = Frame(form)
rite = Frame(form)
lab1.pack(side=TOP)
form.pack(fill=X)
left.pack(side=LEFT)
rite.pack(side=RIGHT)
variables = []
for field in fields:
lab1= Label()
lab = Label(left, text=field)
ent = Entry(rite)
lab.pack(anchor='w')
ent.pack(fill=X)
var = StringVar()
ent.config(textvariable=var)
var.set('0.5')
variables.append(var)
return variables
if __name__ == '__main__':
root = Tk()
vars = makeform(root, fields)
Button(root, text='Fetch',
command=(lambda v=vars: fetch(v))).pack()
root.bind('<Return>', (lambda event, v=vars: fetch(v)))
root.mainloop()
Any suggestions?
Since you want to map some fields to others, using a dictionary is a better choice than using a list.
def fetch(variables):
for key, val in variables.items():
print key, val.get()
def makeform(root, fields):
...
variables = {}
for field in fields:
...
variables[field] = var #associate a field with its variable
return variables
Which will print out
Service Points Won 0.5
Return Points Won 0.7
Note that you can format your print as you wish in your fetch function.
This is my code for trying to get the price of a venue:
# number of people
header = "Number of People"
people = ["10-25", "26-50", "51-100", "101-500", "501-1000", "1000+"]
button = buttonbox("around how many people will attend",title= header,choices=people)
# choosing the venue
if button == people[0]:
button = "you chose '10-25'"
header = "Recommended Venues"
venueZero = ["your home, $0.00", "small garden, $20.00", "planetarium, $30.00"]
button = buttonbox("Choose a venue",title= header,choices=venueZero)
and this is the code I'm using to try to assign a value to venuePrice:
if button == people[0] and button == venueZero[0]:
venuePrice=4444
print venuePrice
However, when I print venuePrice, it says that it is not defined.
button can't equal both people[0] and venueZero[0] at the same time, therefore the condition in the if statement will never be met so venuePrice won't be set.
You could use a different variable name for the second choice:
# number of people
header = "Number of People"
people = ["10-25", "26-50", "51-100", "101-500", "501-1000", "1000+"]
button = buttonbox("around how many people will attend",title= header,choices=people)
# choosing the venue
if button == people[0]:
button = "you chose '10-25'" # I don't understand the purpose of this statement but I'm not sure if you need it for anything so I'll leave it here.
header = "Recommended Venues"
venueZero = ["your home, $0.00", "small garden, $20.00", "planetarium, $30.00"]
button2 = buttonbox("Choose a venue",title= header,choices=venueZero) # Changed from button to button2
Then change the if statement:
if button == people[0] and button2 == venueZero[0]:
venuePrice=4444
print venuePrice
I am new to Python and I am writing a program just for fun. My program consists of three .py files (let's say a.py, b.py, c.py). a will either call on the functions within either b or c, depending on the user's option. After it completes its first round it asks if the user would like to continue or simply exit the program. If they chose continue it asks again whether it should run b or c.
The problem I ran into is that the first time around, a will call the functions in either perfectly fine, it runs smoothly, and then when I select to continue it again calls either function perfectly fine, it will go into the function, but then the function gets stuck in its first step.
The program is not terminating, not giving an error. It accepts the raw_input variable but it will not continue. I was wondering if there was some way to force it to accept the variable and then continue the process (getting it 'unstuck'). I already tried putting pass on the next line. That didn't work.
Here are the steps it takes starting from the request to continue:
Continue = tkMessageBox.askyesno('Cypher Program', 'I have completed the task'
+ '\nWould you like to do anything else?')
## This is in a.py;
if Continue == True:
cyp()
def cyp():
global root
root = Tk()
root.title("Cypher Program")
root['padx'] = 40
root['pady'] = 20
textFrame = Frame(root)
Label(root, text = 'What would you like to do?').pack(side = TOP)
widget1 = Button(root, text = 'Encrypt a file', command = encrypt)
widget1.pack(side = LEFT)
widget2 = Button(root, text = 'Decrypt a file', command = decrypt)
widget2.pack(side = RIGHT)
widget3 = Button(root, text = 'Quit', command = quitr)
widget3.pack(side = BOTTOM)
root.mainloop()
def encrypt():
root.destroy()
encrypt3.crypt()
##Then from there it goes to b.py;
def crypt():
entry('Enter a file to encrypt:', selectFile)
def entry(msg1, cmd):
global top
top = Toplevel() ##changed it to Toplevel
top.title("File Encrypion")
top['padx'] = 40
top['pady'] = 20
textFrame = Frame(top)
entryLabel = Label(textFrame)
entryLabel['text'] = msg1
entryLabel.pack(side = LEFT)
global entryWidget
entryWidget = Entry(textFrame)
entryWidget['width'] = 50
entryWidget.pack(side = LEFT)
textFrame.pack()
button = Button(top, text = "Submit", command = cmd)
button.pack()
button.bind('<Return>', cmd)
top.mainloop()
def selectFile():
if entryWidget.get().strip() == "":
tkMessageBox.showerror("File Encryption", "Enter a file!!")
else:
global enc
enc = entryWidget.get().strip() + '.txt'
top.destroy() ##gets stuck here
##This is the rest of crypt(). It never returns to the try statement
try:
view = open(enc)
except:
import sys
sys.exit(badfile())
text = ''
You need to restructure your code to only create the root window once, and only call mainloop once. Tkinter is not designed to be able to create and destroy the root multiple times in a single process.
If you need multiple windows, create additional windows with the Toplevel command.