I'm trying to create a chatbot program with CHATTERBOT MODULE and TKINTER.
It's almost ok, in fact my problem is that every button-click, the program creates me new labels, with command risposta.pack().
My intent is creating just one label and update it every other button-click.
How can I do it?
MY CODING:
from chatterbot import ChatBot
from tkinter import *
import time
from chatterbot.trainers import ListTrainer
bot = ChatBot(
"GUI Bot",
storage_adapter="chatterbot.storage.SQLStorageAdapter",
input_adapter='chatterbot.input.VariableInputTypeAdapter',
output_adapter='chatterbot.output.OutputAdapter',
database='../database,db',
logic_adapters=[
{
"import_path": "chatterbot.logic.BestMatch",
"statement_comparison_function": "chatterbot.comparisons.levenshtein_distance",
"response_selection_method": "chatterbot.response_selection.get_first_response"
}
]
)
with open('/home/griguols/Scrivania/chatterbot/istruzioni.txt') as istruzioni:
conversation = istruzioni.readlines()
bot.set_trainer(ListTrainer)
bot.train(conversation)
def command():
global risposta
user_input = input.get()
response = bot.get_response(user_input)
risposta = Label(schermata, text=str(response.text))
risposta.pack()
schermata = Tk()
ment = StringVar()
schermata.geometry('1000x500')
schermata.title('OMERO')
titolo = Label(schermata,text='OMERO')
titolo.pack()
input = Entry(schermata,textvariable=ment)
input.pack()
bottone = Button(schermata,text='PARLA CON OMERO',command=command)
bottone.pack()
schermata.mainloop()
To solve this issue, you can pack the label (only one time) after the button, so the last part of the code would look as follows:
bottone = Button(schermata,text='PARLA CON OMERO',command=command)
bottone.pack()
risposta = Label(schermata, text="")
risposta.pack()
schermata.mainloop()
Then, change the command function so that it only updates the text of the already packed label:
def command():
global risposta
user_input = input.get()
response = bot.get_response(user_input)
risposta['text']=str(response.text)
PS: I could not execute the with scope since you have not provided the .txt file. For you next post, please consider providing an MCVE.
Related
I have this very easy program which I want to display one random line from a file each time I click on the Button.
Problem is a new line is display at startup of the program, but nothing happens when I click the button, can someone explain me why ?
from random import randrange
from tkinter import *
def entree():
n=randrange(251)
fs = open('lexique','r')
liste = fs.readlines()
return liste[n]
fen = Tk()
fen.title("lexique anglais politique")
defi = StringVar()
defi.set(entree())
lab = Label(fen, textvariable=defi).pack()
Button(fen, text='Beste Bat', command=entree).pack()
fen.mainloop()
As stated in one of the comments (by #matszwecja), your entree() function doesn't really do anything appart from returning a value.
Nothing in your code updates the actual label. Try something like this :
from random import randrange
from tkinter import *
def entree():
n=randrange(251)
fs = open('lexique','r')
liste = fs.readlines()
return liste[n]
def update_label():
lab.config(text=entree())
fen = Tk()
fen.title("lexique anglais politique")
lab = Label(fen, text=entree())
lab.pack()
Button(fen, text='Beste Bat', command=update_label).pack()
fen.mainloop()
In this example, the entree() function is used to go get a line from your file, and the update_label() function is used to actually update the label.
Also, if you want to be able to update a label, you'll have to pack it after assigning it to a variable.
On a side note, it could be worth noting that hardcoding values that could change in the future is generally considered bad practice. In that regard, I think coding the entree() function this way might be a better idea :
def entree():
fs = open('lexique','r')
liste = fs.readlines()
n=randrange(len(liste))
return liste[n]
This way, if you ever add or remove lines to your "lexique" file, you will not have to change the code.
I have a problem, the problem is i want to create a post-it tkinter gui app and I want to store all the posts the user create so they can open it when they rerun the app, so i used sqlite 3 module to achieve this, but im stuck at the moment when the user opens the existing post-its bcs it opens the last content of the for loop
In case u dont get it here is the code:
"""
from tkinter import *
import sqlite3
conn = sqlite3.connect("post-it.db")
row = 1
cursor = conn.cursor()
posts = cursor.execute("SELECT rowid, * FROM postits")
postsFetch = posts.fetchall()
print(f"{postsFetch}")
def createPost():
pass
def openPost(name):
print(name)
post = Tk()
text = Label(post,text=name)
text.pack()
post.mainloop()
window = Tk()
window.geometry("400x400")
window.config(bg="blue")
createNew = Button(text="Create new Post-it",command=createPost)
createNew.grid(column=1,row=1)
createName = Entry()
createName.grid(column=1,row=2)
frame = Frame()
frame.grid(column=2)
#the problem is at this for loop it opens the last item text
for postit in postsFetch:
postitBtn = Button(frame,text=postit[1],command=lambda: openPost(postit[2]))
postitBtn.grid(column=8,row=row)
row += 1
conn.commit()
window.mainloop()
conn.close()
"""
if u know the answer please help
Firstly, don't use Tk more than once in a program - it can cause problems later on. For all other windows, use Toplevel. Replace post = Tk() with post = Toplevel().The reason your loop doesn't work is explained here. To fix it, change your lambda function to lambda postit = postit: openPost(postit[2]))
I am currently struggling trying to use the panel library in Python, in order to build an interactive dashboard to analyze and display CSV data. My current goal is to let the user enter an initial and a final date, which will be used to filter a DataFrame once a button is pressed. However, whenever I press the button, the on_click function is not completely executed before the script stops running. The code snippet is the following:
import panel as pn
pn.extension()
def acquire_data(dateBeginning, dateEnd):
eventDF = pd.read_csv('multi.csv')
eventDF['Date']= pd.to_datetime(eventDF['Date'])
dateDF = eventDF[eventDF.upvotes > 8]
print(eventDF)
def register_dates(event, save=True):
dateBeginning = date1Picker.value
dateEnd = date2Picker.value
if dateBeginning < dateEnd:
text = pn.widgets.StaticText(name='Static Text', value='A string')
spinner = pn.indicators.LoadingSpinner(width=50, height=50, value=True, color='info', bgcolor='light')
layout = pn.Column(text, spinner, align='center')
layout.app()
print('getting in')
acquire_data(dateBeginning, dateEnd)
print('getting out')
spinner.value = False
else:
print('Not working')
#pn.pane.Alert('## Alert\nThis is a warning!')
return save
date1Picker = pn.widgets.DatePicker(name='Date Initiale', margin=25)
date2Picker = pn.widgets.DatePicker(name='Date Finale', margin=25)
button = pn.widgets.Button(name="Analyse", button_type='primary', margin=(25, 0, 20, 200), width=200)
button.on_click(register_dates)
dateLayout = pn.Row(date1Picker, date2Picker)
layout = pn.Column(dateLayout, button, width=200, align='center')
layout.app()
I was also aiming at having the first layout be replaced by the one with the spinner and the text once the button is pressed, but I haven't found anything in the doc mentioning how to do so. If anyone could give me a hint regarding these issues, that would really help me!
In def acquire_data(dateBeginning, dateEnd):
pd.read_csv('multi.csv'), pd.to_datetime(eventDF['Date'])
For start, in this function I think you forgot to import panda and your app just crash.
add: import pandas as pd
Ex:
import panel as pn
import pandas as pd
I'm trying to create a GUI that has two buttons: One checks whether the user has provided all the required inputs while the other runs a backend script. My problem is that this GUI will run for as long as the user wants to perform the backend task. The problem is: every time the user clicks on the 'check' button, another 'run' button is created right bellow the one last created. I need the 'run' button to be created at the same position every time the check button is clicked. I'm a newbie in python, btw. I'll appreciate if anyone can tell me if I got it all wrong. Thanks!
def verifica():
fluxo=vfluxo.get()
permissoes=vpermissoes.get()
results = vresults.get()
if fluxo==2:
label4 = Label(setup_window, text='Quantas tentativas (1-20)?')
label4.pack()
tentativas = Entry(setup_window)
tentativas.pack()
else:
label5 = Label(setup_window, text='Ready!')
label5.pack()
def bot_setup():
if fluxo==2:
num_tentativas = tentativas.get()
if num_tentativas == '' or int(num_tentativas) > 20:
num_tentativas=0
messagebox.showerror('ERRO!','Digite um tamanho de lote vĂ¡lido (1 a 20)')
else:
num_tentativas=1
setup = {
'tipo_operacao':fluxo,
'permissoes':permissoes,
'mostrarnofim':results,
'tamanho_lote':int(num_tentativas)
}
return setup
comecar = Button(text='Run', command = bot_setup)
comecar.pack()
verificar = Button(text='Check', command = verifica)
verificar.pack()
I want that when I go to secondpage and back to the mainpage it removes the buttons created in the mainloop. So when I open the second page again, it needs to make the buttons again. with the updated list
Now it shows the buttons 2 times. I know to not add it into a function it will render just 1 time but the point is it will be removed when it is in a function and it need to remaked every time I open the mainpage. So that I can edit for example the list when the application is open and it will be rendered again.
Here is my code:
from tkinter import *
items = ['ijs', 'water', 'lolly', 'laptop']
root = Tk()
def buttonmaker():
for x in items:
button = Button(master=secondpage, text=x ).pack()
def mainpagetosecondpage():
mainpage.pack_forget()
buttonmaker()
secondpage.pack()
def secondpagetomainpage():
secondpage.pack_forget()
mainpage.pack()
#mainpage
mainpage = Frame(master=root)
main_to_second_button = Button(master=mainpage, text='secondpage', command=mainpagetosecondpage).pack()
#scondpage
secondpage = Frame(master=root)
Second_to_main_button = Button(master=secondpage, text='mainpage', command=secondpagetomainpage).pack()
mainpage.pack()
root.mainloop()
If something is unclear, please ask
You need to call buttonmaker only once, during the setup of the second frame:
from tkinter import *
root = Tk()
def buttonmaker():
items = ['ijs', 'water', 'lolly', 'laptop']
for x in items:
button = Button(master=secondpage, text=x )
button.pack()
def mainpagetosecondpage():
mainpage.pack_forget()
secondpage.pack()
def secondpagetomainpage():
secondpage.pack_forget()
mainpage.pack()
#mainpage
mainpage = Frame(master=root)
main_to_second_button = Button(master=mainpage, text='secondpage', command=mainpagetosecondpage)
main_to_second_button.pack()
#scondpage
secondpage = Frame(master=root)
Second_to_main_button = Button(master=secondpage, text='mainpage', command=secondpagetomainpage)
Second_to_main_button.pack()
buttonmaker()
mainpage.pack()
root.mainloop()
Also, you need to avoid putting the layout on the same line as the initialization. Code like variable = Widget(args).pack() will lead to bugs. Use 2 lines like I did above.