How can I prevent Toplevel() from opening two additional windows? - python

I have a program that uses Tkinter and I'm trying to assign a command to a button in my root window that opens one additional window. I'm using Toplevel(), but whenever I click the button I've assigned the command to, two windows open, one with my root window's name and one with the name of the additional window I've assigned.
I've tried using .withdraw and .destroy, to hide or remove this extra root window, but nothing seems to be working.
Here is my code:
import Tkinter
from Tkinter import *
root = Tk()
root.wm_title("VACS")
# # Top label # #
SetParameters = Label(text="Set Parameters", width=110, relief=RIDGE)
SetParameters.grid(row=1, column=0, columnspan=7, padx=5, pady=5)
# # Spatial freq settings # #
SpatialFreq = Label(text="Spatial Frequency", width=15, relief=RIDGE)
SpatialFreq.grid(row=3, column=0, padx=5, pady=5)
From1 = Label(text="from")
From1.grid(row=3, column=1, padx=5, pady=5)
Select1 = Spinbox(from_=0, to=10, width=25)
Select1.grid(row=3, column=2, padx=5, pady=5)
To1 = Label(text="to")
To1.grid(row=3, column=3, padx=5, pady=5)
Select2 = Spinbox(from_=0, to=10, width=25)
Select2.grid(row=3, column=4, padx=5, pady=5)
Steps = Label(text="in steps of")
Steps.grid(row=3, column=5, padx=5, pady=5)
Select3 = Spinbox(from_=0, to=10, width=25)
Select3.grid(row=3, column=6, padx=5, pady=5)
# # Contrast settings # #
Contrast = Label(text="Contrast", width=15, relief=RIDGE)
Contrast.grid(row=5, column=0, padx=5, pady=5)
From2 = Label(text="from")
From2.grid(row=5, column=1, padx=5, pady=5)
Select4 = Spinbox(from_=0, to=10, width=25)
Select4.grid(row=5, column=2, padx=5, pady=5)
To2 = Label(text="to")
To2.grid(row=5, column=3, padx=5, pady=5)
Select5 = Spinbox(from_=0, to=10, width=25)
Select5.grid(row=5, column=4, padx=5, pady=5)
Steps2 = Label(text="in steps of")
Steps2.grid(row=5, column=5, padx=5, pady=5)
Select6 = Spinbox(from_=0, to=10, width=25)
Select6.grid(row=5, column=6, padx=5, pady=5)
# # Test button # #
Test = Button(text="Begin Test", width=25, command=Top)
Test.grid(row=6, column=0, columnspan=7, pady=5)
# # Directory input window # #
def Top():
Toplevel()
Toplevel().wm_title("Directory")
root.mainloop()
If you click "Begin Test" in the root window, two extras pop up. I only want the one that says "Directory."
Any ideas?

You're creating two, since Toplevel() is the constructor call:
Toplevel()
Toplevel().wm_title("Directory")
Instead, create one and save it:
top = Toplevel()
top.wm_title("Directory")

Related

How do I left-align buttons in tkinter?

The following code
root = tk.Tk()
frame = ttk.Frame(root, padding=10)
frame.grid()
# Browse
tk.Text(frame, state="disabled", height=1).grid(column=0, row=0, columnspan=3, sticky="W", pady=5, ipadx=2, ipady=2)
ttk.Button(frame, text="Browse", command=None).grid(column=3, row=0, sticky="E")
# Selected files
tk.Text(frame, state="disabled").grid(column=0, row=1, columnspan=4, sticky="EW", pady=10)
# Options
ttk.Button(frame, text="SELECT", command=None).grid(column=0, row=2, sticky="W")
ttk.Button(frame, text="DELETE", command=None).grid(column=1, row=2, sticky="W")
ttk.Button(frame, text="Merge", command=None).grid(column=2, row=2, sticky="W")
ttk.Button(frame, text="Close", command=root.destroy).grid(column=3, row=2, sticky="E")
root.mainloop()
produces this,
but I want the DELETE and MERGE buttons to be left-aligned so they are together with the SELECT button. How can I achieve this?
Put buttons in new Frame and this frame put in original Frame
buttons_frame = ttk.Frame(frame)
buttons_frame.grid(column=0, row=2, sticky="W")
ttk.Button(buttons_frame, text="SELECT", command=None).grid(column=0, row=2, sticky="W")
ttk.Button(buttons_frame, text="DELETE", command=None).grid(column=1, row=2, sticky="W")
ttk.Button(buttons_frame, text="Merge", command=None).grid(column=2, row=2, sticky="W")
BTW:
In buttons_frame you may even use .pack(side='left') instead of grid()
Full code:
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
frame = ttk.Frame(root, padding=10)
frame.grid()
# Browse
tk.Text(frame, state="disabled", height=1).grid(column=0, row=0, columnspan=3, sticky="W", pady=5, ipadx=2, ipady=2)
ttk.Button(frame, text="Browse", command=None).grid(column=3, row=0, sticky="E")
# Selected files
tk.Text(frame, state="disabled").grid(column=0, row=1, columnspan=4, sticky="EW", pady=10)
# Options
buttons_frame = ttk.Frame(frame)
buttons_frame.grid(column=0, row=2, sticky="W")
ttk.Button(buttons_frame, text="SELECT", command=None).grid(column=0, row=2, sticky="W")
ttk.Button(buttons_frame, text="DELETE", command=None).grid(column=1, row=2, sticky="W")
ttk.Button(buttons_frame, text="Merge", command=None).grid(column=2, row=2, sticky="W")
ttk.Button(frame, text="Close", command=root.destroy).grid(column=3, row=2, sticky="E")
root.mainloop()
EDIT:
You may also add empy column between Merge and Close and assign weight=1 to this column so it will get all empty space.
It needs to move Browse and Close to next column, and increase columnspan in both Text
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
frame = ttk.Frame(root, padding=10)
frame.grid()
frame.columnconfigure(3, weight=1) # column 3 will use all free space
# Browse
tk.Text(frame, state="disabled", height=1).grid(column=0, row=0, columnspan=4, sticky="W", pady=5, ipadx=2, ipady=2)
ttk.Button(frame, text="Browse", command=None).grid(column=4, row=0, sticky="E")
# Selected files
tk.Text(frame, state="disabled").grid(column=0, row=1, columnspan=5, sticky="EW", pady=10)
# Options
ttk.Button(frame, text="SELECT", command=None).grid(column=0, row=2, sticky="W")
ttk.Button(frame, text="DELETE", command=None).grid(column=1, row=2, sticky="W")
ttk.Button(frame, text="Merge", command=None).grid(column=2, row=2, sticky="W")
ttk.Button(frame, text="Close", command=root.destroy).grid(column=4, row=2, sticky="E")
root.mainloop()

Pass widget name on button click

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.)

Set tkinter alignment/position

If Info is blank, then the Entry Field and Button are at the red vertical line. But if Info has text, then they shift to the right. How can I fix the positions of the Entry Field and Button? Thanks.
window = Toplevel()
window.geometry('400x400')
searchL = Label(window, text='Enter ID:')
searchL.grid(row=0, column=0, padx=10, pady=10)
searchE = Entry(window)
searchE.grid(row=0, column=1, padx=10, pady=10)
def searchEmp():
for e in listOfEmployees:
if e.i == searchE.get():
results.set(repr(e))
search = Button(window, text='Search', command=searchEmp)
search.grid(row=1, column=0, columnspan=2)
infoL = Label(window, text='Info:')
infoL.grid(row=2, column=0, padx=10, pady=10)
results = StringVar()
resultsL = Label(window, textvariable=results)
resultsL.grid(row=2, column=1, padx=10, pady=10)
Adding the sticky arg fixed it for this Entry Field.
searchE.grid(row=0, column=1, padx=10, pady=10, **sticky=W**)
For the Search button, columnspan was set to 2, so if I removed columnspan, set the column=2, and added sticky=W, it worked.
Thanks to stovfl for the link.

Dynamically fit tkinter window to its content

I have a Toplevel Window with one grid row containing a Label, Entry and a "+" Button (window on startup)
When I hit the Add-Button a new row with the same content is generated. But the problem is, that the window doesn't resize and fit to its new contents. Should look like this resized window.
The code is below:
def process_map():
numbers = {0:'\u2080', 1:'\u2081', 2:'\u2082', 3:'\u2083', 4:'\u2084', 5:'\u2085', 6:'\u2086', 7:'\u2087', 8:'\u2088', 9:'\u2089'}
button_pos = tk.IntVar(0)
ENTRIES = {}
def add_button():
if button_pos.get() >= 10:
index = numbers[button_pos.get()//10] + numbers[button_pos.get()%10]
else:
index = numbers[button_pos.get()]
lb = tk.Label(top_root, text='\u03C6'+index)
lb.grid(row=button_pos.get(), column=0, sticky='NWES')
entry = tk.Entry(top_root, width=4, relief='sunken', bd=2)
entry.grid(row=button_pos.get(), column=1, sticky='WE', padx=5, pady=5)
ENTRIES.update({button_pos.get():entry})
bt.grid(row=button_pos.get(), column=2, sticky='WE', padx=5, pady=5)
bt_close.grid(row=button_pos.get()+1, column=1, padx=5, pady=5)
bt_start.grid(row=button_pos.get()+1, column=0, padx=5, pady=5)
button_pos.set(button_pos.get()+1)
center(top_root)
top_root = tk.Toplevel(root)
top_root.title('Select \u03C6')
lb = tk.Label(top_root, text='\u03C6\u2081', height=1)
lb.grid(row=0, column=0, sticky='NWES')
entry = tk.Entry(top_root, width=4, relief='sunken', bd=2)
entry.grid(row=0, column=1, sticky='WE', padx=5, pady=5)
button_pos.set(button_pos.get()+2)
ENTRIES.update({button_pos.get():entry})
bt = tk.Button(top_root, text='+', command=add_button,)
bt.grid(row=0, column=2, sticky='WE', padx=5, pady=5)
bt_close = tk.Button(top_root, text='Cancel', width=15, command=top_root.destroy)
bt_close.grid(row=button_pos.get()+1, column=1, padx=5, pady=5)
bt_start = tk.Button(top_root, text='Start', width=15)
bt_start.grid(row=button_pos.get()+1, column=0, padx=5, pady=5)
center(top_root)
top_root.mainloop()

Need help creating a window that will enter into a options menu with sliders. In python using Tkinter

I have created a window with a button saying Enter, when clicked I would like it to proceed to an options menu with 3 separate sliders whereby the user can adjust them to get a value then press enter. With this value I would like to have a timed output that is the same as that value in seconds. I am very new to Python and need as much help as possible please :)
This is my code so far; and so far the first enter screen will appear then when the enter button is pressed it will load the next window I have created with the three sliders inside it I am not sure this is the best way to do it? Complete novis!
Please Advise :)
FIRST WINDOW FOR "PRESS ENTER SCREEN"
#! /usr/bin/env python
from Tkinter import *
def callback():
execfile('process screen 2nd draft.py')
exit
window = Tk()
window.title( 'company name ' )
window.configure ( bg = 'purple' )
label = Label( window, text = 'company name with slogan ' )
label.grid(row=0, column=1)
btn_nxt = Button( window , bg = 'purple', text = 'Enter' , command=callback , )
btn_nxt.grid(row=1, column=1, padx=100, pady=100)
window.mainloop()
SECOND WINDOW FOR OPTIONS MENU 3 SEPERATE SLIDERS
#! /usr/bin/env python
from Tkinter import *
window = Tk()
window.title( 'random title' )
window.configure( bg = 'purple' )
def show_values () :
print (w1.get(), w2.get(), w3.get())
btn_ent = Button( window , text = 'Enter' , command=show_values)
btn_ent.grid(row=3, column=3, padx=5, pady=5)
label_chem= Label( window , bg = 'purple', text = 'Please Choose Chemical Levels' )
label_chem.grid(row=0, column=2, padx=5, pady=5)
label_nic= Label( window , bg = 'purple', text = 'Nictonine (mg)' )
label_nic.grid(row=1, column=1, padx=5, pady=5)
label_glyc= Label( window , bg = 'purple', text = 'Glycol (mg)' )
label_glyc.grid(row=1, column=2, padx=5, pady=5)
label_gli= Label( window , bg = 'purple', text = 'Glycerine (mg) ' )
label_gli.grid(row=1, column=3, padx=5, pady=5)
w1 = Scale( window, bg = 'purple', from_=30, to=0, orient=VERTICAL, resolution=0.5 )
w1.grid(row=2, column=1, padx=5, pady=5)
w2 = Scale( window, bg = 'purple', from_=30, to=0, orient=VERTICAL, resolution=0.5 )
w2.grid(row=2, column=2, padx=5, pady=5)
w3 = Scale( window, bg = 'purple', from_=30, to=0, orient=VERTICAL, resolution=0.5 )
w3.grid(row=2, column=3, padx=5, pady=5)
window.mainloop()
First version with Toplevel to create second window and timed window - all in one file.
I use after(time_miliseconds, function_name) to run function after time_miliseconds
Press buton Enter to see timed window. It closes after constant time.
#! /usr/bin/env python
from Tkinter import *
#-----------------------------------------------
# global variable
time = 0
#-----------------------------------------------
# second window
def second_window():
subwindow = Toplevel(window)
subwindow.title('random title')
subwindow.configure(bg='purple')
def show_values():
print w1.get(), w2.get(), w3.get()
btn_ent = Button(subwindow, text='Enter', command=timed_window)
btn_ent.grid(row=3, column=3, padx=5, pady=5)
label_chem = Label(subwindow, bg='purple', text='Please Choose Chemical Levels')
label_chem.grid(row=0, column=2, padx=5, pady=5)
label_nic = Label(subwindow, bg='purple', text='Nictonine (mg)')
label_nic.grid(row=1, column=1, padx=5, pady=5)
label_glyc = Label(subwindow, bg='purple', text='Glycol (mg)')
label_glyc.grid(row=1, column=2, padx=5, pady=5)
label_gli = Label(subwindow , bg='purple', text='Glycerine (mg)')
label_gli.grid(row=1, column=3, padx=5, pady=5)
w1 = Scale(subwindow, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w1.grid(row=2, column=1, padx=5, pady=5)
w2 = Scale(subwindow, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w2.grid(row=2, column=2, padx=5, pady=5)
w3 = Scale(subwindow, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w3.grid(row=2, column=3, padx=5, pady=5)
#-----------------------------------------------
# timed window
def timed_window():
global time
time = 50
def countdown():
global time
if time > 0:
time -= 1
lab.config(text=str(time))
subwindow.after(100, countdown) # 100 miliseconds
else:
subwindow.destroy()
subwindow = Toplevel(window)
subwindow.title('countdown')
subwindow.configure(bg='purple')
lab = Label(subwindow, bg='purple', text=str(time))
lab.pack(padx=20, pady=20)
subwindow.after(100, countdown) # 100 miliseconds
#-----------------------------------------------
# mainwindow
window = Tk()
window.title('company name')
window.configure(bg='purple')
label = Label(window, text='company name with slogan')
label.grid(row=0, column=1)
btn_nxt = Button(window, bg='purple', text='Enter', command=second_window)
btn_nxt.grid(row=1, column=1, padx=100, pady=100)
window.mainloop()
Second version with one window and two frames - all in one file.
I use pack() and pack_forget() to show and hide frames.
I use the same timed window as before.
#! /usr/bin/env python
from Tkinter import *
#-----------------------------------------------
frame_1 = None
frame_2 = None
time = 0
#-----------------------------------------------
def create_frame_1():
global frame_1
frame_1 = Frame(window)
frame_1.configure(bg='purple')
label = Label(frame_1, text='company name with slogan')
label.grid(row=0, column=1)
btn_nxt = Button(frame_1, bg='purple', text='Enter', command=show_frame_2)
btn_nxt.grid(row=1, column=1, padx=100, pady=100)
def create_frame_2():
def show_values():
print w1.get(), w2.get(), w3.get()
global frame_2
frame_2 = Frame(window)
frame_2.configure(bg='purple')
btn_ent = Button(frame_2, text='Enter', command=timed_window)
btn_ent.grid(row=3, column=3, padx=5, pady=5)
label_chem = Label(frame_2, bg='purple', text='Please Choose Chemical Levels')
label_chem.grid(row=0, column=2, padx=5, pady=5)
label_nic = Label(frame_2, bg='purple', text='Nictonine (mg)')
label_nic.grid(row=1, column=1, padx=5, pady=5)
label_glyc = Label(frame_2, bg='purple', text='Glycol (mg)')
label_glyc.grid(row=1, column=2, padx=5, pady=5)
label_gli = Label(frame_2 , bg='purple', text='Glycerine (mg)')
label_gli.grid(row=1, column=3, padx=5, pady=5)
w1 = Scale(frame_2, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w1.grid(row=2, column=1, padx=5, pady=5)
w2 = Scale(frame_2, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w2.grid(row=2, column=2, padx=5, pady=5)
w3 = Scale(frame_2, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w3.grid(row=2, column=3, padx=5, pady=5)
btn_back = Button(frame_2, text='Back', command=show_frame_1)
btn_back.grid(row=3, column=1, padx=5, pady=5)
#-----------------------------------------------
def show_frame_1():
frame_2.pack_forget()
window.title('company name')
frame_1.pack()
def show_frame_2():
frame_1.pack_forget()
window.title('random title')
frame_2.pack()
#-----------------------------------------------
def timed_window():
global time
time = 50
def countdown():
global time
if time > 0:
time -= 1
lab.config(text=str(time))
subwindow.after(100, countdown) # 100 miliseconds
else:
subwindow.destroy()
subwindow = Toplevel(window)
subwindow.title('countdown')
subwindow.configure(bg='purple')
lab = Label(subwindow, bg='purple', text=str(time))
lab.pack(padx=20, pady=20)
subwindow.after(100, countdown) # 100 miliseconds
#-----------------------------------------------
window = Tk()
create_frame_1()
create_frame_2()
show_frame_1()
window.mainloop()

Categories

Resources