What I want the frame to do is that when I click on the 'clear' button, the frame is cleaned but it does not and when I enter a string that is not valid and then a valid one, it shows traces of the past and past action. I already tried changing the Label.grid () by a Label.pack (), but it is worse since the 'animation' looks like a stack without removing any element when the 'clear' button is pressed
This is basically what would make it change
from tkinter import *
import tkinter.ttk as ttk
def clear():
area.delete(0,END)
frame.config(bd=1, relief=SUNKEN)
frame.update()
status = Label(frame)
status.grid(row=0, column=0, sticky=NSEW)
def statusVal(value):
if not value == 0:
status = Label(frame, background="#ff4242", fg="#262626", text="Cadena invalida", anchor="center")
status.grid(row=0, column=0)
frame.config(bd=1, relief=SUNKEN, background="#ff4242")
frame.update()
else:
status = Label(frame, background="#56ed42", fg="#262626", text="Cadena valida", anchor="center")
status.grid(row=0, column=0)
frame.config(bd=1, relief=SUNKEN, background="#56ed42")
frame.update()
#Test
def validation():
capture = area.get()
if capture == '1':
return statusVal(0)
else:
return statusVal(1)
root = Tk()
root.geometry("300x150+300+300")
area = Entry(root)
area.grid(row=1, column=0, columnspan=2, sticky=E+W+S+N, padx=5)
frame = Frame(root, bd=1, relief=SUNKEN)
frame.grid(row=2, column=0, padx=5, pady=5, columnspan=2, sticky=W+E+S+N)
frame.columnconfigure(0,weight=5)
frame.rowconfigure(0,weight=5)
abtn = Button(root, text="Validate", command=validation)
abtn.grid(row=1, column=3)
cbtn = Button(root, text="Clear", command=clear)
cbtn.grid(row=2, column=3, pady=5)
root.mainloop()
See if this works better. The main change was to have the status Label always exist and hide or unhide it as desired — instead of creating a new one every time the validation() function was called. I also removed the code that was explicitly updating the frame which isn't necessary.
from tkinter import *
import tkinter.ttk as ttk
def clear():
area.delete(0,END)
status.grid_remove() # Hide. but remember grid options.
def statusVal(value):
if not value == 0:
status.config(background="#ff4242", fg="#262626", text="Cadena invalida",
anchor="center")
status.grid() # Unhide
else:
status.config(background="#56ed42", fg="#262626", text="Cadena valida",
anchor="center")
status.grid() # Unhide
#Test
def validation():
capture = area.get()
if capture == '1':
statusVal(0)
else:
statusVal(1)
# Main
root = Tk()
root.geometry("300x150+300+300")
area = Entry(root)
area.grid(row=1, column=0, columnspan=2, sticky=E+W+S+N, padx=5)
frame = Frame(root, bd=1, relief=SUNKEN)
frame.grid(row=2, column=0, padx=5, pady=5, columnspan=2, sticky=W+E+S+N)
frame.columnconfigure(0,weight=5)
frame.rowconfigure(0,weight=5)
# Initialize status Label.
status = Label(frame, anchor="center")
status.grid(row=0, column=0)
status.grid_remove() # Hide it.
abtn = Button(root, text="Validate", command=validation)
abtn.grid(row=1, column=3)
cbtn = Button(root, text="Clear", command=clear)
cbtn.grid(row=2, column=3, pady=5)
root.mainloop()
Related
Can someone help, i need to generate 10 buttons and then when i click it must change the text on the unnamed button.
trying to get the event.widget but with no successes
from tkinter import ttk
root = ttk()
def gonow(e):
e.config(text="clicked")
for x in range(0, 10):
ttk.Button(root, name="but"+x,width="30", height=3, text=x).grid( column=0,
r.ow=0, padx=10, pady=5)
butok=ttk.Button(root, width="30", height=3, text=x, command=lambda var="but"+x:
gonow(var)).grid( column=0, row=0, padx=10, pady=5)
if __name__ == "__main__":
root.mainloop()
New update
b = tk.Button(frm_txt_json_case_btn, width="30", height=3, text=str(titulo+" "+cherep), fg=fcolor,relief=relifst, borderwidth=4,command=lambda titulo=titulo,wrd2srch=words2search,assumirrow=assumirrow,hiden_row=assumirrowr,resp_kib=resp_kiblog,repkib=repkib,urrrl=url_conf, jsump=jsonreq, explis=expectresq, frm_txt_json_case_tit=frm_txt_json_case_tit, inp_cond_protocol=inp_cond_protocol, resp_json=resp_json_input,lblexp=lblexpect, reqtxt=reqst_input,frm_txt_json_case_btn=frm_txt_json_case_btn: ChangConfWI(reqtxt, lblexp, frm_txt_json_case_tit, resp_json, inp_cond_protocol,urrrl, jsump, explis,frm_txt_json_case_btn,repkib,resp_kib,wrd2srch,hiden_row,assumirrow,titulo))
b.grid(column=colcount, row=rowcount, padx=10, pady=5)
buttonslst.append(b)
valbut=int(assumirrowr)-8
print(valbut)
print(buttonslst[valbut])
fvarbut=buttonslst[valbut]
print(fvarbut)
ttk.Button(frm_but_oknot, width="15", text="OK", image=photoOK, command=lambda assumirrow=assumirrow,filename=filename_report,exp=lblexpect,obs=resp_kiblog,urrrl=url_conf,tipo_de_conf=tipo_de_conf, resp_json_input=resp_json_input, reqst_input=reqst_input: savetoxls("geradorteste",resp_json_input,reqst_input, "OK",tipo_de_conf,urrrl,obs,exp,filename,assumirrow,fvarbut)).grid( column=0, row=0, padx=1, pady=15)
When you pass x to gonow, it is the index of the button, not the button itself. You could store the buttons in a list (note: the buttons, not the result of grid!), and then use the index:
buttons = []
for x in range(0, 3):
b = tk.Button(root, width=30, height=3, text=x, command=lambda x=x: gonow(buttons[x]))
b.grid(column=0, row=x, padx=10, pady=5)
buttons.append(b)
Or postpone the command creation after the button is created and pass the button itself:
for x in range(0, 3):
b = tk.Button(root, width=30, height=3, text=x)
b.config(command=lambda b=b: gonow(b))
b.grid(column=0, row=x, padx=10, pady=5)
(Note: There are a few more unrelated (syntax) errors throughout your code that you should fix.)
I want to code a searchable ttk.Treeview; however, my code does not behave properly. When I type in and click search nothing happens. What should be improved so the searched items are highlighted when I type in?
from tkinter import *
from tkinter import ttk
root = Tk()
root.title("Medicine database")
def add():
tree.insert("",END,values=("",e1.get()))
def search(item=''):
children = tree.get_children(item)
for child in children:
text = tree.item(child, 'text')
if text.startswith(e1.get()):
tree.selection_set(child)
return True
else:
res = search(child)
if res:
return True
lb1 = Label(root,text="Search:")
lb1.grid(row =0,column=0,padx=10,pady=10,sticky=W)
e1=Entry(root,width=15)
e1.grid(row=0,column=1,padx=10,pady=10,sticky=E,rowspan=1)
btn = Button(root,text="search",width=10,command=search)
btn.grid(row =0,column=0,padx=10,pady=10,rowspan=2)
btn1 = Button(root,text="add",width=10,command=add)
btn1.grid(row =1,column=0,padx=10,pady=10,rowspan=2)
#treeview
tree = ttk.Treeview(root,height=25)
tree["columns"]=("one","two","three","four")
tree.column("one",width=120)
tree.column("two",width=160)
tree.column("three",width=130)
tree.column("four",width=160)
tree.heading("one", text="Numer seryjny leku")
tree.heading("two", text="Nazwa Leku")
tree.heading("three", text="Ampułki/Tabletki")
tree.heading("four",text="Data ważności")
tree["show"]="headings"
tree.grid(row=0,column=2,rowspan=6,pady=20)
root.geometry("840x580")
root.mainloop()
As it was, your search method did nothing.
First, you probably need to have an entry for adding items and another for searching them.
Then, in the search method, you must retrieve the query from the search entry, match it with then tree children values, and return (here we will print) the values if you find a match, and highlight them in the Treeview.
import tkinter as tk
from tkinter import ttk
def add():
value = add_entry.get()
values.append(value)
tree.insert("", tk.END, values=(f'#{len(values)}', value, 'more', 'moar'))
def search():
query = search_entry.get()
selections = []
for child in tree.get_children():
if query in tree.item(child)['values']:
print(tree.item(child)['values'])
selections.append(child)
print('search completed')
tree.selection_set(selections)
values = []
root = tk.Tk()
root.title("Medicine database")
lb1 = tk.Label(root, text="Search:")
lb1.grid(row=0, column=0, padx=10, pady=10, sticky=tk.W)
search_entry = tk.Entry(root, width=15)
search_entry.grid(row=0, column=1, padx=10, pady=10, sticky=tk.E, rowspan=1)
btn = tk.Button(root, text="search", width=10, command=search)
btn.grid(row=0, column=0, padx=10, pady=10, rowspan=2)
add_lb = tk.Label(root, text="add:")
add_lb.grid(row=1, column=0, padx=10, pady=10, sticky=tk.W)
add_entry = tk.Entry(root, width=15)
add_entry.grid(row=1, column=1, padx=10, pady=10, sticky=tk.E, rowspan=1)
btn1 = tk.Button(root, text="add", width=10, command=add)
btn1.grid(row=1, column=0, padx=10, pady=10, rowspan=2)
# treeview
tree = ttk.Treeview(root, height=25)
tree["columns"] = ("one", "two", "three", "four")
tree.column("one", width=120)
tree.column("two", width=160)
tree.column("three", width=130)
tree.column("four", width=160)
tree.heading("one", text="Numer seryjny leku")
tree.heading("two", text="Nazwa Leku")
tree.heading("three", text="Ampułki/Tabletki")
tree.heading("four", text="Data ważności")
tree["show"]="headings"
tree.grid(row=0, column=2, rowspan=6, pady=20)
root.geometry("840x580")
if __name__ == '__main__':
root.mainloop()
I'm new to tkinter and i've built this so far:
import tkinter as tk
import subprocess
import os
def maingui():
window = tk.Tk()
window.title("My first GUI")
#window.state('zoomed')
window.geometry("700x205")
window.configure(bg="black")
frame1 = tk.Frame(window, width=90, bg="orange")
# frame1.pack(fill=tk.Y, side=tk.LEFT)
frame1.grid(row=0, column=0)
frame2 = tk.Frame(window, width=1890, bg="black")
# frame2.pack(fill=tk.Y, side=tk.RIGHT)
frame2.grid(row=0, column=1)
lotomat = tk.Button(frame1, text=" Start\n Lotomat", padx=10, pady=5, bg="orange", fg="black",
relief=tk.GROOVE, command=lambda : startLotomat())
# lotomat.pack()
lotomat.grid(row=1, column=0)
convert = tk.Button(frame1, text=" URL2IP \n on \n Desktop", padx=10, pady=5, bg="orange", fg="black",
relief=tk.GROOVE, command=lambda : startURL2IP())
# convert.pack()
convert.grid(row=2, column=0)
startRps = tk.Button(frame1, text=" Start \nR.P.S", padx=12, pady=5, bg="orange", fg="black",
relief=tk.GROOVE, command=lambda : startRPS())
# startRps.pack()
startRps.grid(row=3, column=0)
endRun = tk.Button(frame1, text="Quit", padx=12, pady=10, bg="orange", fg="black",
relief=tk.RIDGE, command=lambda : ending())
# endRun.pack()
endRun.grid(row=4, column=0)
def startLotomat():
os.system('python lotomat.py')
def startURL2IP():
os.system('python urltoipondesktop.py')
def startRPS():
os.system('python rockpaperscissors.py')
def ending():
exit()
window.mainloop()
maingui()
each button runs a different .py file.
how can I use frames to split the window so the program runs on the right side?
Thanks!
Edit:
I've added a pic of the GUI, the goal is to run the left menu buttons on the black frame.
Following acw1668's comment and alot of thread researching here's the thread solution. so elegant, so simple! I love python!
def thread_handler(self, host):
wt = threading.Thread(target=self.write_to_file, args=(host,))
pt = threading.Thread(target=self.print_to_box, args=(host,))
dt = threading.Thread(target=self.delete_default_lines, args=())
wt.start()
pt.start()
dt.start()
I have a window with two parts. One part is to do some settings. I want to hide it until the user press a setting button. is it possible to hide a part of the frame that contains many widgets?
I have seen many examples to hide a widget in tkinter (eg. pack_forget and grid_forget). In my case, I am trying to hide a part of the frame through a button press (that contains more than one widgets). Any suggestions please
I can't use more than one frames because of some issues.
import tkinter as tk
def startFn():
pass
#fn body
def stopFn():
pass
#fn body
def FnToShow():
pass
#fn body ???
def FnToHide():
pass
#fn body ???
root = tk.Tk()
root.geometry('600x400')
#two containers like this.
#trying to hide container_2 untill the user press settingBtn
container_1 = tk.Frame(root, borderwidth=2, relief="solid")
container_2 = tk.Frame(root, borderwidth=2, relief="solid")
startBtn = tk.Button(container_1, text = "Start", command =startFn)
startBtn.grid(row=4, column=4)
stopBtn = tk.Button(container_1, text = "Stop", command= stopFn)
stopBtn.grid(row=5, column=4)
settingBtn = tk.Button(container_1, text = "Settings", command= FnToShow)
settingBtn.grid(row=6, column=4)
setting_1 = tk.Label(container_2, text = "Setting-1", fg='#000000')
setting_1.grid(row=3, column=10)
setting_2 = tk.Label(container_2, text = "Setting-2", fg='#000000')
setting_2.grid(row=4, column=10)
closeSettingBtn = tk.Button(container_2, text = "close Settings", command= FnToHide)
closeSettingBtn.grid(row=5, column=10)
container_1.pack(side="left", expand=True, fill="x", padx=1, pady=1)
container_2.pack(side="right",expand=True, fill="x", padx=1, pady=1)
root.mainloop()
You could show/hide the entire container_2 using the functions FnToShow and FnToHide:
something like this:
import tkinter as tk
def startFn():
pass
def stopFn():
pass
def FnToShow():
container_2.pack(side="right",expand=True, fill="x", padx=1, pady=1)
def FnToHide():
container_2.pack_forget()
root = tk.Tk()
root.geometry('600x400')
container_1 = tk.Frame(root, borderwidth=2, relief="solid")
container_2 = tk.Frame(root, borderwidth=2, relief="solid")
startBtn = tk.Button(container_1, text="Start", command =startFn)
startBtn.grid(row=4, column=4)
stopBtn = tk.Button(container_1, text="Stop", command= stopFn)
stopBtn.grid(row=5, column=4)
settingBtn = tk.Button(container_1, text="Settings", command= FnToShow)
settingBtn.grid(row=6, column=4)
setting_1 = tk.Label(container_2, text="Setting-1", fg='#000000')
setting_1.grid(row=3, column=10)
setting_2 = tk.Label(container_2, text="Setting-2", fg='#000000')
setting_2.grid(row=4, column=10)
closeSettingBtn = tk.Button(container_2, text="close Settings", command= FnToHide)
closeSettingBtn.grid(row=5, column=10)
container_1.pack(side="left", expand=True, fill="x", padx=1, pady=1)
root.mainloop()
Please Help! I'm at my wits end over here... I am new to learning Python and tkinter and I have not found anyone trying to do what I am, so I keep trying different people's answers and nothing is working. I can't understand the docs, and every tutorial I find is not quite exactly what I need to do, so I end up with irrelevant code bits that just lead to more problems.
I want to build a GUI for a touchscreen program for a Raspberry Pi that will allow me to program a relay to turn on for "x" seconds, then turn off for "y" seconds, then repeat forever until I stop it. The touchscreen needs to have large buttons for each of the numbers 0 - 9, a button to clear the values, buttons to confirm each value once it has been input in the entry box, a button to start the cycle, and a button to exit. There also needs to be 2 entry boxes, one for "On", and one for "Off", so that the user can see the numbers they have entered for each value. This is what is messing me up. I can get it to work for one entry box, but not two.
Please someone tell me what is wrong. I don't know how to tell each button to place its value only in the entry field that has focus. I can only figure out how to tell it to input in one entry or the other, regardless of which has focus.
I also need the numbers to appear in the entry boxes in the correct sequence, so that when you type a "3" and then a "0", the program reads "30". Right now it is producing "03".
Here's the code. I have some things commented out currently, and yes, I know it's ugly:
#!/usr/bin/env python
try:
# for Python 2
from Tkinter import *
except ImportError:
# for Python 3
from tkinter import *
import ttk as ttk
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(4, GPIO.LOW)
running = True
def water():
go.grid(column=4, row=3, rowspan=6, columnspan=6, sticky=W)
def go():
running = True
x = on.get()
y = off.get()
y = float(y)
x = float(x)
if running:
GPIO.output(4, False)
print("Off")
time.sleep(y)
GPIO.output(4, True)
print("On")
time.sleep(x)
root.after(10, go)
def clear():
on.set('')
off.set('')
global running
running = False
go.grid_forget()
on_entry.focus()
def select(value):
if on_entry.focus():
on_entry.set(value)
elif off_entry.focus():
off_entry.set(value)
def geton():
on_entry.get()
off_entry.focus()
def getoff():
off_entry.get()
water()
#this is the PROBLEM!!!!
def set_text(text):
on_entry.insert(0,text)
#buttons = ['1','2','3','4','5','6','7','8','9','0']
#varRow = 5
#varColumn = 0
root = Tk()
root.geometry("740x480+0+0")
root.title("Waterboy")
#need to make this fullscreen
mainframe = Frame(root)
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
go = Button(mainframe, text="GO", command=go, bg="green", width=6, height=11)
#seconds on and off
on = StringVar()
off = StringVar()
on_entry = Entry(mainframe, width=8, textvariable=on)
on_entry.grid(column=2, row=1, sticky=(W, E))
off_entry = Entry(mainframe, width=8, textvariable=off)
off_entry.grid(column=2, row=2, sticky=(W, E))
on_entry.focus_set()
onok = Button(mainframe, text="OK", command=geton, bg="white", width=6, height=1)
onok.grid(column=4, row=1, sticky=W)
offok = Button(mainframe, text="OK", command=getoff, bg="white", width=6, height=1)
offok.grid(column=4, row=2, sticky=W)
reset = Button(mainframe, text="Reset Values", command=clear, bg='yellow', width=16, height=2)
reset.grid(column=0, row=7, sticky=W)
adios = Button(mainframe, text="EXIT", command=exit, bg="red", width=16, height=2)
adios.grid(column=2, row=7, sticky=W)
secon = ttk.Label(mainframe, text="Input # Seconds Water ON and press 'OK' -->", width=36)
secon.grid(column=0, row=1, columnspan=2)
secoff = ttk.Label(mainframe, text="Input # Seconds Water OFF and press 'OK' -->", width=36)
secoff.grid(column=0, row=2, columnspan=2)
one = Button(mainframe, text="1", width=16, height=2, command=lambda:set_text("1")
one.grid(column=0, row=4, sticky=W)
two = Button(mainframe, text="2", width=16, height=2, command=lambda:set_text("2")
two.grid(column=1, row=4, sticky=W)
three = Button(mainframe, text="3", width=16, height=2, command=lambda:set_text("3")
three.grid(column=2, row=4, sticky=W)
four = Button(mainframe, text="4", width=16, height=2, command=lambda:set_text("4")
four.grid(column=0, row=5, sticky=W)
five = Button(mainframe, text="5", width=16, height=2, command=lambda:set_text("5")
five.grid(column=1, row=5, sticky=W)
six = Button(mainframe, text="6", width=16, height=2, command=lambda:set_text("6")
six.grid(column=2, row=5, sticky=W)
seven = Button(mainframe, text="7", width=16, height=2, command=lambda:set_text("7")
seven.grid(column=0, row=6, sticky=W)
eight = Button(mainframe, text="8", width=16, height=2, command=lambda:set_text("8")
eight.grid(column=1, row=6, sticky=W)
nine = Button(mainframe, text="9", width=16, height=2, command=lambda:set_text("9")
nine.grid(column=2, row=6, sticky=W)
zero = Button(mainframe, text="0", width=16, height=2, command=lambda:set_text("0")
zero.grid(column=1, row=7, sticky=W)
#for child in mainframe.winfo_children(): child.grid_configure(padx=4, pady=4)
#root.bind('<Return>', go)
#for button in buttons:
# command = lambda x=button: select(x)
# Button(mainframe, text=button, width=5, bg="white", command = command).grid(row = varRow, column=varColumn)
# varColumn += 1
# if varColumn > 2 and varRow == 4:
# varColumn = 0
# varRow += 1
# if varColumn > 2 and varRow == 5:
# varColumn = 0
# varRow += 1
# if varColumn > 2 and varRow == 6:
# varColumn = 0
# varRow += 1
root.mainloop()
You can use the method focus_get on the root window to get the widget that has focus. You can then insert text using that widget. You can specify the special index of "end" to have the text inserted at the end of the widget.
For example:
def set_text(text)
widget = root.focus_get()
widget.insert("end", text)
Of course, you'll want to do some validation to make sure that the widget is a text or entry widget.
Also, be careful with using ttk -- the default behavior of ttk button widgets is to steal the keyboard focus.