The buttons, for some reason, seem to be positioned wrong. I checked my code, and it's written to have the correct positioning, but it for some reason is showing all of the buttons except for the "View All" buttons to be too low. The buttons are supposed to be right above each other. Could ya'll help and let me know what the problem is?
from tkinter import *
window = Tk()
#Labels
l1 = Label(window, text="Title")
l1.grid(row=0, column=0)
l2 = Label(window, text="Author")
l2.grid(row=0, column=2)
l3 = Label(window, text="Year")
l3.grid(row=1, column=0)
l4 = Label(window, text="ISBN")
l4 .grid(row=1, column=2)
#Entry boxes
title_text=StringVar()
e1 = Entry(window, textvariable=title_text)
e1.grid(row=0, column=1)
author_text=StringVar()
e2 = Entry(window, textvariable=author_text)
e2.grid(row=0, column=3)
year_text=StringVar()
e3 = Entry(window, textvariable=year_text)
e3.grid(row=1, column=1)
isbn_text=StringVar()
e4 = Entry(window, textvariable=isbn_text)
e4.grid(row=1, column=3)
#listbox
ls1 = Listbox(window, height=6,width=35)
ls1.grid(row=2, column=0)
#Scrollbar
scr1 = Scrollbar(window)
scr1.grid(row=2, column=2, rowspan=6)
#Making the scrolbar scroll down the listbox
ls1.configure(yscrollcommand=scr1.set)
scr1.configure(command=ls1.yview)
#Buttons and stuff
b1 = Button(window, text="View all", width=12)
b1.grid(row=2, column=3)
b2 = Button(window, text="Search Entry", width=12)
b2.grid(row=3, column=3)
b3 = Button(window, text="Add Entry", width=12)
b3.grid(row=4, column=3)
b4 = Button(window, text="Update Selected", width=12)
b4.grid(row=5, column=3)
b5 = Button(window, text="Delete Selected", width=12)
b5.grid(row=6, column=3)
b6 = Button(window, text="Exit", width=12)
b6.grid(row=7, column=3)
window.mainloop()
First, when the number of rectangles is entered less than 24 it works fine. When I put the number of rectangles more than 24, the entry boxes exceed the window height and I cannot see it. I want to use a scroll bar at the right side when the number of entry boxes exceeds the window height. The documentation implies that only the List, Textbox, Canvas and Entry widgets support the scrollbar interface. So, how can I do for gridboxes?
Note : The code is verifiable.
from tkinter import *
temp_recta = []
def save_content(top):
for j in range(0, int(rectangles.get()) * 2):
temp_recta.append(rectangle_values[j].get())
root = Toplevel()
l1 = Label(root, text="Size of Sheet[Height]:")
l1.grid(row=0, column=0)
l2 = Label(root, text="Size of Sheet[Width]:")
l2.grid(row=1, column=0)
height = StringVar()
e1 = Entry(root, textvariable=height)
e1.grid(row=0, column=1)
width = StringVar()
e2 = Entry(root, textvariable=width)
e2.grid(row=1, column=1)
b5 = Button(root, text="Proceed", width=12, command=lambda: save_sheetsize(e1, e2, root))
b5.grid(row=2, column=0)
b6 = Button(root, text="Back", width=12, command=lambda: (root.destroy(), top.deiconify()))
b6.grid(row=2, column=1)
root.title("Sheet Size")
def save_sheetsize(e1, e2, root):
global x
global y
x = float(e2.get())
y = float(e1.get())
root.destroy()
window.destroy()
rectangle_values = []
x = 0
y = 0
k = 0
def open_window():
window.withdraw()
global k
top = Toplevel()
top.title("Rectangles")
for i in range(0, int(rectangles.get()) * 2):
if (i % 2) == 0:
l4 = Label(top, text="Size of rectangle:")
l4.grid(row=i, column=0)
rectangle_values.append(StringVar())
en = Entry(top, textvariable=rectangle_values[i])
en.grid(row=i, column=1)
b3 = Button(top, text="Save", width=12, command=lambda: (top.withdraw(), save_content(top)))
b3.grid(row=int(rectangles.get()) * 2 + 1, column=0)
b4 = Button(top, text="Back", width=12, command=lambda: (top.destroy(), window.deiconify()))
b4.grid(row=int(rectangles.get()) * 2 + 1, column=1)
k = int(rectangles.get())
window = Tk()
l3 = Label(window, text="Number of Rectangles:")
l3.grid(row=0, column=0)
rectangles = StringVar()
e3 = Entry(window, textvariable=rectangles)
e3.grid(row=0, column=1)
b1 = Button(window, text='Submit', width=12, command=open_window)
b1.grid(row=3, column=1)
window.title("Rectangle Configuration")
window.mainloop()
Here is a simple class to do this. Add your text widget and it will give you a scrollbar when your window is full of text.
import tkinter
class Scrollbar:
def __init__(self,text):
self.frame = text.master
self.text = text
self.text.configure(wrap='none')
self.for_x_view()
self.for_y_view()
def for_x_view(self):
# scroll Bar x For width
scroll_x=tkinter.Scrollbar(self.frame, orient='horizontal',command=self.text.xview)
scroll_x.config(command=self.text.xview)
self.text.configure(xscrollcommand=scroll_x.set)
scroll_x.pack(side='bottom', fill='x', anchor='w')
return
def for_y_view(self):
# Scroll Bar y For Height
scroll_y = tkinter.Scrollbar(self.frame)
scroll_y.config(command=self.text.yview)
self.text.configure(yscrollcommand=scroll_y.set)
scroll_y.pack(side='right', fill='y')
return
if __name__ == '__main__':
root = tkinter.Tk()
pad = tkinter.Text(root,wrap='none')
Scrollbar(pad)
pad.pack()
root.mainloop()
from tkinter import *
# global new_width
# global new_height
# global new_rectangles
rectangle_values=[]
x = 0
y = 0
k = 0
def open_window():
global k
top=Toplevel()
top.title("Rectangles")
top.geometry("300x600")
for i in range(0,int(rectangles.get())*2):
if(i % 2) == 0:
l4=Label(top, text="Size of rectangle:")
l4.grid(row=i,column=0)
rectangle_values.append(StringVar())
en=Entry(top, textvariable=rectangle_values[i])
en.grid(row=i,column=1)
b3=Button(top, text="Save", width=12, command=save_content)
b3.grid(row=int(rectangles.get())*2+1,column=0)
b4=Button(top, text="Close", width=12, command=top.destroy)
b4.grid(row=int(rectangles.get())*2+1,column=1)
k = int(rectangles.get())
def save_sheetsize():
global x
global y
x = float(e2.get())
y = float(e1.get())
temp_recta=[]
def save_content():
for j in range(0,int(rectangles.get())*2):
temp_recta.append(rectangle_values[j].get())
window=Tk()
l3=Label(window, text="Number of Rectangles:")
l3.grid(row=0,column=0)
# defining entries
rectangles=StringVar()
e3=Entry(window, textvariable=rectangles)
e3.grid(row=0,column=1)
# Defining buttons
b1=Button(window, text='Submit', width=12, command=lambda:(window.destroy(),open_window()))
b1.grid(row=3,column=1)
window.title("Rectangle Configuration")
window.geometry("300x600")
window.mainloop()
root=Tk()
l1=Label(root, text="Size of Sheet[Height]:")
l1.grid(row=0,column=0)
l2=Label(root, text="Size of Sheet[Width]:")
l2.grid(row=1,column=0)
# defining entries
height=StringVar()
e1=Entry(root, textvariable=height)
e1.grid(row=0,column=1)
width=StringVar()
e2=Entry(root, textvariable=width)
e2.grid(row=1,column=1)
b5=Button(root, text="Save", width=12, command=save_sheetsize)
b5.grid(row=2,column=0)
b6=Button(root, text="Close", width=12, command=root.destroy)
b6.grid(row=2,column=1)
root.title("Sheet Size")
root.geometry("300x600")
root.mainloop()
When I run this code, I input a number at first and press the button which calls the function open_window and destroy, a window named tk pops up along with the window which is in open_window. When I close that tk window, the other window that I want also closes. I couldn't figure it out. How do I avoid that tk window from popping up?
This is just an example you can follow to fix your problem, and modify, update as you need.
from tkinter import *
# global new_width
# global new_height
# global new_rectangles
temp_recta = []
def save_content(top):
top.destroy()
for j in range(0, int(rectangles.get()) * 2):
temp_recta.append(rectangle_values[j].get())
root = Toplevel()
l1 = Label(root, text="Size of Sheet[Height]:")
l1.grid(row=0, column=0)
l2 = Label(root, text="Size of Sheet[Width]:")
l2.grid(row=1, column=0)
# defining entries
height = StringVar()
e1 = Entry(root, textvariable=height)
e1.grid(row=0, column=1)
width = StringVar()
e2 = Entry(root, textvariable=width)
e2.grid(row=1, column=1)
b5 = Button(root, text="Save", width=12, command=lambda: save_sheetsize(e1, e2, root))
b5.grid(row=2, column=0)
b6 = Button(root, text="Close", width=12, command=lambda: (root.destroy(), window.deiconify()))
b6.grid(row=2, column=1)
root.title("Sheet Size")
def save_sheetsize(e1, e2, root):
global x
global y
x = float(e2.get())
y = float(e1.get())
root.destroy()
window.deiconify()
rectangle_values = []
x = 0
y = 0
k = 0
def open_window():
window.withdraw()
global k
top = Toplevel()
top.title("Rectangles")
top.geometry("300x600")
for i in range(0, int(rectangles.get()) * 2):
if (i % 2) == 0:
l4 = Label(top, text="Size of rectangle:")
l4.grid(row=i, column=0)
rectangle_values.append(StringVar())
en = Entry(top, textvariable=rectangle_values[i])
en.grid(row=i, column=1)
b3 = Button(top, text="Save", width=12, command=lambda: save_content(top))
b3.grid(row=int(rectangles.get()) * 2 + 1, column=0)
b4 = Button(top, text="Close", width=12, command=lambda: (top.destroy(), window.deiconify()))
b4.grid(row=int(rectangles.get()) * 2 + 1, column=1)
k = int(rectangles.get())
window = Tk()
l3 = Label(window, text="Number of Rectangles:")
l3.grid(row=0, column=0)
# defining entries
rectangles = StringVar()
e3 = Entry(window, textvariable=rectangles)
e3.grid(row=0, column=1)
# Defining buttons
b1 = Button(window, text='Submit', width=12, command=open_window)
b1.grid(row=3, column=1)
window.title("Rectangle Configuration")
window.geometry("300x600")
window.mainloop()
I've been following this website for a while. It is really helpful. So, thanks for all the useful tips.
I've been searching for this answer for the past two weeks without any success, so now I'm compelled to ask out of total frustration with my current obstacle.
How do you use StringVar as a list?
Basically, I was coding the following program for my wife. The code is pretty messy as it is my first program I've tried to code.
The idea was that I would take 3 variables; password, secret number and website and then do some work on them using if statements and lists to create a unique password.
First problem was that I couldn't restrict the character length of the entry widgets but in the end i solved that but i still want to limit the characters that can be input.
for instance in the website entry box, i want to allow only letters.
If I could convert StringVar to a list, I could do some work with messy if statements to allow only certain characters in each index but everythime i try it says that stringvars cant be used as a list.
I need them as a list to limit the type of characters that can be entered and also so that i can do work on the variables to get the final output.
CODE:
from Tkinter import *
import Tkinter
from PIL import Image, ImageTk
import os
Title= ("Helvetica", 20, "bold", "underline")
Heading= ("Courier", 20, "bold")
Body= ("Courier", 15)
Body1= ("Courier", 15, "bold")
notice= ("Courier", 10)
Body2= ("Courier", 15, "bold", "underline")
root = Tk()
root.title("Koala Series: Encrypter")
root.configure(background="#ffefd5")
root.geometry('{}x{}'.format(510, 600))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1) # not needed, this is the default behavior
root.rowconfigure(1, weight=1)
root.rowconfigure(2, weight=1)
website = StringVar()
Titlemsg = Label(root, text="Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
Titlemsg.grid( row=7, pady=25, sticky=N+S+E+W)
img1 = ImageTk.PhotoImage(Image.open("koala.jpeg"))
startpic = Label(root, image = img1, relief=RIDGE )
startpic.grid( row=10,pady=25, )
Head = Label(root,anchor=CENTER,text="Welcome to the Koala Encrypter \n\n A Koala series tool that allows you\n\n to Encrypt your passwords \n\n Click \'Start Encrypting\' to continue \n\n", font=Body, bg="#ffefd5", relief=RAISED,)
Head.grid( row=14, pady=25, columnspan=2, sticky=N+S+E+W)
web = Label(root, text="WEBSITE: ", font=Body, bg="#ffefd5", justify=CENTER,)
#website.set("Enter your website here")
entry = Entry(root,textvariable=website , justify=CENTER,relief=SUNKEN,cursor="pencil", takefocus=True )
Notice1 = Label( text="Please only insert the first 5 letters of the website!!",font=notice, bg="#ffefd5", fg="#0000ff",)
passw = Label(root, text="PASSWORD: ", font=Body, bg="#ffefd5", justify=CENTER)
passwordvar= StringVar()
entry1 = Entry(root, textvariable= passwordvar, justify=CENTER,relief=SUNKEN, cursor="pencil", takefocus=True )
Notice= Label(root, text="Your password must only be 5 characters long!!", font=notice, bg="#ffefd5", fg="#0000ff", justify=CENTER)
def callback(event):
if "<0>":
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Your secret number must be between 1 and 9:", font=Body1, fg="red", bg="#ffefd5")
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
secret = Label(root, text="SECRET NUMBER: ", font=Body, bg="#ffefd5" , justify=CENTER,)
numbervar = StringVar()
entry2 = Entry(root, textvariable=numbervar , justify=CENTER,relief=SUNKEN,cursor="pencil", takefocus=True)
entry2.bind("<0>", callback)
Notice2 = Label(root, text="your secret number must be between 1 and 9!!!", font=notice, bg="#ffefd5", fg="#0000ff", justify=CENTER)
img = ImageTk.PhotoImage(Image.open("Koalalogo.jpg"))
panel = Label(root, image = img, relief=SUNKEN)
correct= Label(root, text="Check the below details \n\n Click \'yes\' if they are correct \n\n Click \'No\' to go back \n\n", font=Body1, bg="#ffefd5")
yourwebsite = Label(root, text="The Website is :", font=Body, bg="#ffefd5")#
website1 = Label(root, font=Body2, bg="#ffefd5",fg= "#00009C", textvariable = website)#
yourpassword = Label(root, text="Your Password is:", font=Body, bg="#ffefd5")
yournumber1= Label(root, font=Body2, bg="#ffefd5",textvariable = numbervar , fg= "#00009C", )
yourpassword1 = Label(root, font=Body2, bg="#ffefd5",textvariable = passwordvar , fg= "#00009C", )
yournumber= Label(root, text="Your Secret Number is:", font=Body, bg="#ffefd5")
def restart():
Titlemsg.grid_forget()
correct.grid_forget()
yourwebsite.grid_forget()
website1.grid_forget()
yourpassword.grid_forget()
yourpassword1.grid_forget()
yournumber.grid_forget()
yournumber1.grid_forget()
panel.grid_forget()
toolbar.grid_forget()
yes.grid_forget()
no.grid_forget()
entry.delete(0,END)
entry1.delete(0,END)
entry2.delete(0,END)
Titlemsg.grid( row=7, pady=25, sticky=N+S+E+W)
startpic.grid( row=10,pady=25, )
Head.grid( row=14, pady=25, columnspan=2, sticky=N+S+E+W)
toolbar.grid( row=21, )
end.grid(column =3, row=1, sticky=N+S+E+W)
begin.grid(column =2, row=1, sticky=N+S+E+W)
def start():
#entry.destroy()
#entry1.destroy()
#entry2.destroy()
toolbar.grid_forget()
Titlemsg.grid_forget()
begin.grid_forget()
Head.grid_forget()
startpic.grid_forget()
web.grid(row=3, column=0, sticky= W+E)
entry.grid( row=3, column=1, padx=50)
passw.grid(row=10, column=0)
Notice1.grid(row=4, sticky=N+S+E+W, columnspan=2)
entry1.grid(row=10, column=1)
Notice.grid(row=11,column=0, columnspan=2,)
secret.grid(row=13, column=0)
entry2.grid( row=13, column=1)
Notice2.grid( row=14,column=0, columnspan=2,)
panel.grid(row=20,columnspan=2, pady=70)
confirm.grid(column =1, row=1)
reset.grid(column =2, row=1)
end.grid(column =3, row=1)
toolbar.grid(row=21, column=0, columnspan=2)
Titlemsg.grid(row=0, column=0, columnspan=2, sticky=E+W)
def Reset():
entry.delete(0,END)
entry1.delete(0,END)
entry2.delete(0,END)
def clear_text():
#entry.destroy()
#entry1.destroy()
#entry2.destroy()
panel.grid_forget()
entry.grid_forget()
entry1.grid_forget()
entry2.grid_forget()
web.grid_forget()
Notice.grid_forget()
passw.grid_forget()
secret.grid_forget()
Notice1.grid_forget()
Notice2.grid_forget()
confirm.grid_forget()
reset.grid_forget()
toolbar.grid_forget()
Titlemsg.grid_forget()
Titlemsg.grid(row=0, column=0, columnspan=2, sticky=E+W)
correct.grid(row=1, column=0, columnspan=2, sticky=E+W)
yourwebsite.grid(row=2,column=0,sticky=E+W, pady=5)
website1.grid(row=2, column=1, padx=65,sticky=E+W, pady=5)
yourpassword.grid(row=4, column=0,sticky=E+W, pady=5)
yourpassword1.grid(row=4, column=1, padx=65,sticky=E+W, pady=5)
yournumber.grid(row=6, column=0,sticky=E+W, pady=5)
yournumber1.grid(row=6, column=1, padx=65,sticky=E+W, pady=5)
panel.grid(row=8, column=0, columnspan=2, pady=50)
toolbar.grid(row=10, column=0, columnspan=2)
yes.grid(column =1, row=1)
no.grid(column =2, row=1)
def popup():
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Your password is:", font=Body1, fg="red", bg="#ffefd5")
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
pwd= Label(top, font=Body2, text="password", bg="#ffefd5", fg= "#00009C", ) #textvariable = newpassword ,
pwd.grid(row= 2, column=1,sticky=E+W,padx=15)
button = Button(top, text="OK", command=top.destroy, relief=RAISED )
button.grid(column =0,columnspan=2, row=4, sticky=N+S+E+W)
def helpmsg():
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Koala series 1.0 - Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
pwd= Label(top, font=Body, text="Free software to help you keep your acounts safe", bg="#ffefd5")
pwd.grid(row= 1,sticky=E+W,)
Titlems = Label(top, text="Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
Titlems.grid( row=0, pady=25, sticky=N+S+E+W)
button = Button(top, text="OK", command=top.destroy, relief=RAISED )
button.grid(column =0,columnspan=2, row=4, sticky=N+S+E+W)
max_len = 5
def on_write(*args):
s = website.get()
if len(s) > max_len:
website.set(s[:max_len])
website.trace_variable("w", on_write)
max_len1 = 5
def on_write(*args):
s = passwordvar.get()
if len(s) > max_len1:
passwordvar.set(s[:max_len1])
passwordvar.trace_variable("w", on_write)
max_len2 = 1
def on_write(*args):
s = numbervar.get()
if len(s) > max_len2:
numbervar.set(s[:max_len2])
numbervar.trace_variable("w", on_write)
toolbar = Frame(root)
reset = Button(toolbar, text="Reset", width=6, command=Reset, cursor="cross", relief=RAISED, takefocus=True )
end = Button(toolbar, text="Quit" ,command=root.destroy, relief=RAISED, cursor="X_cursor", takefocus=True)
end.grid(column =3, row=1, sticky=N+S+E+W)
begin = Button(toolbar, text="Start Encrypting", command=start, relief=RAISED, cursor="star",takefocus=True )
begin.grid(column =2, row=1, sticky=N+S+E+W)
confirm = Button(toolbar, text="Next", command =clear_text, cursor="star", relief=RAISED,takefocus=True )
yes = Button(toolbar, text="Yes", command =popup, cursor="star", relief=RAISED,takefocus=True )
no = Button(toolbar, text="No", command =restart, cursor="pirate", relief=RAISED, takefocus=True )
toolbar.grid( row=21, )
menu = Menu(root)
root.config(menu=menu)
filemenu = Menu(menu)
menu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Restart", command=restart)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=root.destroy)
helpmenu = Menu(menu)
menu.add_cascade(label="Help", menu=helpmenu, )
helpmenu.add_command(label="About...", command=helpmsg)
app = root
root.mainloop()
# add functionality, fix validation
To restrict the type/number of characters that can be typed into an entry widget, you can use the entry validatecommand. Here is an example to allow only letters and another one to restrict the entry to 4 digits:
from tkinter import Tk, Entry, Label
def only_letters(action, char):
if action == "1":
# a character is inserted (deletion is 0) allow the insertion
# only if the inserted character char is a letter
return char.isalpha()
else:
# allow deletion
return True
def only_numbers_max_4(action, new_text):
if action == "1":
return new_text.isdigit() and len(new_text) <= 4
else:
return True
root = Tk()
# register validate commands
validate_letter = root.register(only_letters)
validate_nb = root.register(only_numbers_max_4)
Label(root, text="Only letters: ").grid(row=0, column=0)
e1 = Entry(root, validate="key", validatecommand=(validate_letter, '%d', '%S'))
# %d is the action code and %S the inserted/deleted character
e1.grid(row=0, column=1)
Label(root, text="Only numbers, at most 4: ").grid(row=1, column=0)
e2 = Entry(root, validate="key", validatecommand=(validate_nb, '%d', '%P'))
# %P is the new content of the entry after the modification
e2.grid(row=1, column=1)
root.mainloop()
For more details on entry validation, see http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html