I've been making an app in python and I made a pop-up window to add a new reminder, but the "reminder", "date" and "time" labels don't appear on the new window. The "add new reminder" label also shows up at the bottom left of the window instead of the top center.
I've tried packing and grid configure, but they still don't show up.
def popup():
pop = tk.Toplevel()
pop.wm_title("New Reminder")
label = ttk.Label(pop, text="Add new reminder.")
label.grid(row=0, column=1)
label2 = ttk.Label(pop, text="Reminder")
label.grid(row=1, column=0)
label3 = ttk.Label(pop, text="Date")
label.grid(row=2, column=0)
label4 = ttk.Label(pop, text="Time")
label.grid(row=3, column=0)
rem = ttk.Entry(pop)
rem.grid(row=1, column=1)
date = ttk.Entry(pop)
date.grid(row=2, column=1)
time = ttk.Entry(pop)
time.grid(row=3, column=1)
addbutton = ttk.Button(pop, text="Add", command=pop.destroy)
addbutton.grid(row=4, column=0)
canbutton = ttk.Button(pop, text="Cancel", command=pop.destroy)
canbutton.grid(row=4, column=1)
pop.mainloop()
What instead shows up is the three entries stacked vertically at the top with the "add new reminder" label to the left of the last entry
Layout problems are much easier to visualize when you separate widget creation from widget layout.
Here's your layout code grouped together:
label.grid(row=0, column=1)
label.grid(row=1, column=0)
label.grid(row=2, column=0)
label.grid(row=3, column=0)
rem.grid(row=1, column=1)
date.grid(row=2, column=1)
time.grid(row=3, column=1)
addbutton.grid(row=4, column=0)
canbutton.grid(row=4, column=1)
Notice how you are calling grid on label four times, and never call grid on label2, label3, and label4.
Related
So I was wondering why my entry boxes are showing in the center. Before I had the label instructions for first and last name they were aligning right. I have the labels on column 0 and the entry boxes on column 1, however they dont line up directly next to each other. If someone could help me with a very basic solution and language, I am obviously a beginner..
root = Tk()
root.title("Login Information Help")
root.configure(background='black')
root.geometry("1920x1080")
def button_click(number):
textbox.delete(0, END)
textbox.insert(0, number)
instructions = Label(root, text="Please fill in all information below to recieve student account details.", bg="black", fg="white", font="times, 20") #Create instructions line
first_name_text = Label(root, text="Enter First Name", bg="black", fg="white", font="times, 20" ) #enter first name text
inputbox1 = Entry(root, width=30, font="times, 20") #Create input boxes
last_name_text = Label(root, text="Enter Last Name", bg="black", fg="white", font="times, 20" ) #enter last name text
inputbox2 = Entry(root, width=30, font="Times, 20") #Create input boxes
button_1 = Button(root, text="Get Info", padx=45, pady=5, bg="#808080", font="times, 15", command=lambda: button_click("1")) #Define Buttons
instructions.grid(row=0, column=0) #Define Instructions variables (labels)
first_name_text.grid(row=1, column=0, pady=0, sticky=W) #position first name text
inputbox1.grid(row=1, column=1, padx=10) #Postion inputbox 1
last_name_text.grid(row=2, column=0, sticky=W) #position last name text
inputbox2.grid(row=2, column=1, padx=10, pady=10, sticky=W) #Postion inputbox 2
button_1.grid(row=3, column=0, sticky=W) #Put Buttons on Screen
root.mainloop()```
First row must span 2 columns.
instructions.grid(row=0, column=0, columnspan=2)
Use sticky=EW with every widget to fill the column.
Add root.columnconfigure(0, weight=0) to not expand the first column.
First of all this method uses pack since that is what I came up with (more explanation below) here is my code:
from tkinter import Tk, Label, Entry, Button, Frame
root = Tk()
root.title("Login Information Help")
root.configure(background='black')
root.geometry("1920x1080")
def button_click(number):
textbox.delete(0, END)
textbox.insert(0, number)
row0 = Frame(root, bg='black')
row0.pack(side='top', fill='y', anchor='nw')
row1 = Frame(root, bg='black')
row1.pack(side='top', fill='y', anchor='nw')
row2 = Frame(root, bg='black')
row2.pack(side='top', fill='y', anchor='nw')
row3 = Frame(root, bg='black')
row3.pack(side='top', fill='y', anchor='nw')
instructions = Label(row0, text="Please fill in all information below to recieve student account details.", bg="black", fg="white", font="times, 20") #Create instructions line
first_name_text = Label(row1, text="Enter First Name", bg="black", fg="white", font="times, 20" ) #enter first name text
inputbox1 = Entry(row1, width=30, font="times, 20") #Create input boxes
last_name_text = Label(row2, text="Enter Last Name", bg="black", fg="white", font="times, 20" ) #enter last name text
inputbox2 = Entry(row2, width=30, font="Times, 20") #Create input boxes
button_1 = Button(row3, text="Get Info", padx=45, pady=5, bg="#808080", font="times, 15", command=lambda: button_click("1")) #Define Buttons
instructions.pack(side='left')
first_name_text.pack(side='left')
inputbox1.pack(side='left')
last_name_text.pack(side='left')
inputbox2.pack(side='left', padx=2)
button_1.pack(side='left')
root.mainloop()
Explanation: those frames created at the top are stacked like rows, so whenever I add something to each of them using side argument in pack they get added there like columns, that padx is to make the alignment look nicer. Also I would suggest organizing the code better and start learning classes since they imo help a lot when dealing with tkinter.
So basically lets take one of the frames for example. the row1: when adding with .packand using one side (left in this case) widgets get packed in a row however it is not that easy to make them then packed in the second row so that is why there is another frame that is directly below the row1 called row2 and it gets directly packed underneath because of top side similarly as left side for widgets and those frames expand only where there are widgets (or maybe for that expansion it has to have the argument of fill, dunno rn) anyhow have a good day and experiment
This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 2 years ago.
I have a small issue for which I can`t find the reason.
I have the following GUI, and it pops the message box when I run it, even though it is inside a procedure which is triggered only on button press.
Tried even creating a secondary function which will show only the message box and still did not fix the issue.
Thank you for your help... I am quite sure that there is an easy fix which I just do not see...
import tkinter as tk
from tkinter import ttk
import tkinter.messagebox
import jl_generator
def run():
jl_generator.run_process()
tkinter.messagebox.showerror('Done','Done')
def show():
temp_list = user_input_list
for i in range(0, len(user_input_list[0])):
listBox.insert("", "end", values = (user_input_list[0][i],user_input_list[1][i],user_input_list[2][i],user_input_list[3][i],user_input_list[4][i],user_input_list[6][i],user_input_list[8][i]))
# Column Names for the TreeView
cols = ('Entity', 'Customer Nr', 'Account Code', 'Profit Centre', 'Partner Profit Centre', 'Amount', 'Nr Of Journal Lines')
# Input data for the tree view
user_input_list, journal_code = jl_generator.get_user_input()
#Creating the
root = tk.Tk()
root.title('JL Generator')
#Create the treeview
listBox = ttk.Treeview(root, columns=cols, show='headings')
for col in cols:
listBox.heading(col, text=col)
listBox.grid(row=1, column=0, columnspan=3)
#-------------LABELS--------------
#Title Label
label = tk.Label(root, text="Journal Lines Generator", font=("Arial",30)).grid(row=0, columnspan=3)
#Journal Code Label
show_journal_code = tk.Label(root, text = 'Journal Code = ' + journal_code).grid(row=6, column=1)
#Number of Journal Lines Label
show_number_of_journal_lines = tk.Label(root, text = 'Number of Journal Lines = ' + str(sum(user_input_list[8][i] for i in range(0, len(user_input_list[0]))))).grid(row=5, column=1)
#------------BUTTONS-----------
#Run the Generation
run_process = tk.Button(root, text="Generate JLs", width=15, command=run()).grid(row=4, column=1)
#Show the input data
showScores = tk.Button(root, text="Show Input", width=15, command=show).grid(row=4, column=0)
#Close the window
closeButton = tk.Button(root, text="Exit", width=15, command=exit).grid(row=4, column=2)
root.mainloop()
run_process = tk.Button(root, text="Generate JLs", width=15, command=run()).grid(row=4, column=1)
this is incorrect.
I used to feel confused about this.
You should use:
run_process = tk.Button(root, text="Generate JLs", width=15, command=run).grid(row=4, column=1)
In python,function is an object,call function should use function()
If you debug this code,you will find that after debug this code
run_process = tk.Button(root, text="Generate JLs", width=15, command=run()).grid(row=4, column=1)
you will find it will call run function and run it.
And Finally,run_process["command"] will be the returned value ofrun()
I made a program that swaps character in a string according my data dictionary but I want to display the swapped string as a text in the GUI that i can copy and paste outside the program.
I just started using tkinter a few days ago, but i do understand python:
import tkinter as tk
root = tk.Tk()
root.title("code converter")
itext = tk.StringVar()
top_spacer = tk.Label(root, text=" ")
top_spacer.grid(row=0, column=1)
text_label = tk.Label(root, text="type/paste text you want to convert")
text_label.grid(row=0, column=2)
text_entry = tk.Entry(root, textvariable=itext)#itext is the input text
text_entry.grid(row=1, column=2)
def translate():
trans_dict = {
'a':'z','b':'y', 'c':'x', 'd':'w', 'e':'v', 'f':'u', 'g':'t', 'h':'s', 'i':'r', 'j':'q', 'k':'p', 'l':'o', 'm':'n'
,'n':'m','o':'l', 'p':'k','q':'j','r':'i','s':'h','t':'g' ,'u':'f','v':'e','w':'d','x':'c','y':'b','z':'a'
,'A':'Z','B':'Y', 'C':'X','D':'W','E':'V', 'F':'U','G':'T','H':'S', 'I':'R', 'J':'Q', 'K':'P', 'L':'O', 'M':'N'
,'N':'M','O':'L', 'P':'K','Q':'J','R':'I','S':'H','T':'G','U':'F','V':'E','W':'D','X':'C','Y':'B','Z':'A'
#,'(1)':'(26)','(2)':'(25)','(3)':'(24)','(4)':'(23)','(5)':'(22)','(6)':'(21)','(7)':'(20)','(8)':'(19)', '(9)':'(18)', '(10)':'(17)', '(11)':'(16)', '(12)':'(15)', '(13)':'(14)'
#,'(14)':'(13)','(15)':'(12)','(16)':'(11)','(17)':'(10)','(18)':'(9)','(19)':'(8)','(20)':'(7)','(21)':'(6)','(22)':'(5)','(23)':'(4)','(24)':'(3)','(25)':'(2)','(26)':'(1)'
}
ttext = itext.get()
translation = "".join([trans_dict.get(c,c) for c in ttext])
ntext.set(translation)
convertion_button = tk.Button(root, text="convert text", command=translate)
convertion_button.grid(row=2, column=2)
ntext = tk.StringVar()
ntext_Message = tk.Message(root, textvariable=ntext, relief="sunken", bg="white", width=200)
ntext_Message.grid(row=3, column=2)
copy_button = tk.Button(root, text="copy text to clipboard")
copy_button.grid(row=2, column=1)
root.mainloop()
i want to display the ntext variable string in the GUI and copy it to the system clipboard when the copy button is pressed. is that possible?
i am using tkinter to make a gui and have made various different buttons and now i have made all this i am unsure how to correctly make the first gui box close as the second one opens (sign_in function)
from tkinter import *
class login:
def __init__(self, master):
frame = Frame(master)
frame.grid()
self.button1 = Button(frame, text="signup", fg="green",command=self.sign_in)
self.button2 = Button(frame, text="sign in", fg="black",)
self.button3 = Button(frame, text="quit", fg="red", command=frame.master.destroy)
self.button1.grid(stick=W)
self.button2.grid(stick=W)
self.button3.grid(stick=W)
def sign_in(self):
frame = Frame()
frame.grid()
name = Label(root, text="Name: ")
password = Label(root, text="password: ")
entry1 = Entry(root)
entry2 = Entry(root)
name.grid(row=0, sticky=E)
password.grid(row=1, sticky=E)
entry1.grid(row=0, column=1)
entry2.grid(row=1, column=1)
c = Checkbutton(root, text="keep me logged in")
c.grid(columnspan=2, sticky="w")
root = Tk()
account=login(root)
root.mainloop()
Your code contains some indentation errors so I'll just go by your question.
when i click the button 'signup' it closes that gui and opens the next one
You can do so by first withdrawing your root window like this: root.withdraw() which will hide your original window. Then create a Toplevel window like this: newWindow = tk.Toplevel(root) to create a new window. You will just need to place these lines in the button command call.
Here's what you can change in the sign_in note that I changed all the masters to frame and not root:
def sign_in(self):
root.withdraw()
frame = Toplevel(root)
name = Label(frame, text="Name: ")
password = Label(frame, text="password: ")
entry1 = Entry(frame)
entry2 = Entry(frame)
name.grid(row=0, sticky=E)
password.grid(row=1, sticky=E)
entry1.grid(row=0, column=1)
entry2.grid(row=1, column=1)
c = Checkbutton(frame, text="keep me logged in")
c.grid(columnspan=2, sticky="w")
I came up with the following code more as a reference to help me remember how to build GUI apps with TkInter. It runs great except when a click Button1 or any other widget whose command option is set to self.hello. As you can see in the code bellow, the hello function is like a place holder. While the button click works fine while running the script through IDLE, it simply causes the application to exit if you start the program by double-clicking the actual file test.pyw. My question is, why?
#Some guy somewhere
from tkinter import *
class Application:
def hello(self):
msg = messagebox.showinfo('Message Title','Message Body')
def __init__(self, parent):
parent.resizable(0,0)
parent.minsize(800, 400)
parent.title('Top Level')
# Global Padding pady and padx
pad_x = 0
pad_y = 0
# CASCADE MENU
# create a parent menu.
self.parentmenu1 = Menu(parent, tearoff=0)
#self.menubar1.add_command(label='Menu1', command=self.hello)
#create a child menu for parent menu.
self.parentmenu1_child1 = Menu(parent, tearoff=0)
self.parentmenu1_child1.add_command(label='Item1', command=self.hello)
self.parentmenu1_child1.add_command(label='Item2', command=self.hello)
self.parentmenu1_child1.add_command(label='Item3', command=self.hello)
#add child menu to parent menu.
self.parentmenu1.add_cascade(label='Menu1', menu=self.parentmenu1_child1)
#self.menubar1.add_separator()
# SINGLE MENU
# create a parent menu.
self.parentmenu1.add_command(label='Menu2', command=self.hello)
# SINGLE MENU
# create a parent menu.
self.parentmenu1.add_command(label='Menu3', command=self.hello)
# display the parent menu.
parent.config(menu=self.parentmenu1)
# Create controls
#create label
self.label1 = Label(parent, text='Label1')
#create textbox
self.textbox1 = Entry(parent)
#create button
self.button1 = Button(parent, text='Button1', command=self.hello)
#string variable to hold checkbox1 values.
self.str_checkbox1 = StringVar()
#create checkbox
self.checkbox1 = Checkbutton(parent, text='Checkbox1', variable=self.str_checkbox1, onvalue='on1', offvalue='off1')
#deselect checkbox1
self.checkbox1.deselect()
#string variable to hold checkbox2 values.
self.str_checkbox2 = StringVar()
#create checkbox
self.checkbox2 = Checkbutton(parent, text='Checkbox2', variable=self.str_checkbox2, onvalue='on2', offvalue='off2')
#deselect checkbox2
self.checkbox2.deselect()
#???? ..what sets the groupbox apart from others. primary key???!!
self.str_radiobutton1 = StringVar()
#command= parameter missing.
self.radiobutton1 = Radiobutton(parent, text='Radio 1', variable=self.str_radiobutton1, value='a')
self.radiobutton2 = Radiobutton(parent, text='Radio 2', variable=self.str_radiobutton1, value='b')
self.radiobutton1.select()
#create a list of options.
optionList = ('Option1', 'Option2', 'Option3')
#string variable to hold optionlist values.
self.str_optionmenu1 = StringVar()
#associate string variable with optionlist
self.str_optionmenu1.set(optionList[0])
#create optionmenu
self.optionmenu1 = OptionMenu(parent, self.str_optionmenu1, *optionList)
#create a frame
self.frame1 = Frame(parent)
#create a text.
self.textarea1 = Text(self.frame1, width=20, height=10)
#align text left and fill frame with it.
self.textarea1.pack(side=LEFT, fill=Y)
#create a scrollbar.
self.scrollbar1 = Scrollbar(self.frame1)
#align scrollbar right and fill frame with it.
self.scrollbar1.pack(side=RIGHT, fill=Y)
#what is going to be scrolled?
self.scrollbar1.config(command=self.textarea1.yview)
#set textarea scrollbar.
self.textarea1.config(yscrollcommand=self.scrollbar1.set)
#align frame left and fill.
self.frame1.pack(side=LEFT, fill=Y)
#create a frame
self.frame2 = Frame(parent)
#create a text.
self.listbox1 = Listbox(self.frame2, width=20, height=10, activestyle='none', selectmode=SINGLE)
#create a list of items.
optionList = ('Item1', 'Item2', 'Item3', 'Item4', 'Item5', 'Item6', 'Item7', 'Item8', 'Item9', 'Item10', 'Item11')
#add items from list to listbox
for item in optionList:
self.listbox1.insert(END, item)
#align text left and fill frame with it.
self.listbox1.pack(side=LEFT, fill=Y)
#create a scrollbar.
self.scrollbar2 = Scrollbar(self.frame2)
#align scrollbar right and fill frame with it.
self.scrollbar2.pack(side=RIGHT, fill=Y)
#what is going to be scrolled?
self.scrollbar2.config(command=self.listbox1.yview)
#set textarea scrollbar.
self.listbox1.config(yscrollcommand=self.scrollbar2.set)
#align frame left and fill.
self.frame2.pack(side=LEFT, fill=Y)
# Place controls inside of grid
self.label1.grid(row=0, column=0, padx=pad_x, pady=pad_y, sticky=W)
self.textbox1.grid(row=0, column=1, padx=pad_x, pady=pad_y, sticky=W)
self.button1.grid(row=1, column=0, padx=pad_x, pady=pad_y, sticky=W)
self.checkbox1.grid(row=1, column=1, padx=pad_x, pady=pad_y, sticky=W)
self.checkbox2.grid(row=1, column=2, padx=pad_x, pady=pad_y, sticky=W)
self.optionmenu1.grid(row=2, column=0, padx=pad_x, pady=pad_y, sticky=W)
self.frame1.grid(row=2, column=1, padx=pad_x, pady=pad_y, sticky=W)
self.radiobutton1.grid(row=3, column=0, padx=pad_x, pady=pad_y, sticky=W)
self.radiobutton2.grid(row=3, column=1, padx=pad_x, pady=pad_y, sticky=W)
self.frame2.grid(row=4, column=0, padx=pad_x, pady=pad_y, sticky=W)
if __name__ == '__main__':
parent = Tk()
app = Application(parent)
parent.mainloop()
Alright. Apparently tkMessageBox has been renamed to messagebox in Python 3.x. Also this
module is not available in tkinter so even though a developer might use:
from tkinter import *
..he/she would still need to:
from tkinter import messagebox