Closing a second Tkinter window doesn't work - python

Imagine the following very simple example:
from tkinter import *
from tempFunctions import *
startingWin = Tk()
button = Button(startingWin, text="Open Other Win", command=lambda: openSecondWin()).grid(row=0, column=0, padx=30, pady=30)
startingWin.mainloop()
The output is simply as following:
No if I click on the button, I open the second Win like:
The second window has the following code in tempFunctions.py:
from tkinter import *
def openSecondWin():
secondWin = Tk()
cancelButton = Button(secondWin, text="Cancel", command=secondWin.quit).grid(row=0, column=0, padx=30, pady=30)
secondWin.mainloop()
I expect that when I press cancel, the secondWin should close. That doesn't happen. What I get is that when I click cancel, the second Win doesn't close. However, if click twice both windows (startingWin and secondWin) close together. Why?
Is there a logical explanation for this? Thanks!
UPDATE:
Trying with binding results in the same problem.
Also making the second win as Toplevel doesn't help.

The problem was that I was using quit(). However, in case of multiple windows, one should use destroy() according to the answer here. That solved my problem.

Related

Tkinter button issue

import tkinter
win=tkinter.Tk()
win.configure(background='grey')
k=False
def g():
k=True
v=tkinter.Button(win, text='click', command=g)
v.pack()
while k==True:
win.configure(background='black')
win.mainloop()
There's no reason why that while loop would run after the button is clicked, since (as you know) your program is run "from top to bottom", and control remains in win.mainloop() until the window is closed. (You can find that out by adding print("bye!") after that call.)
You might want to just directly call .configure(). (I gave the button some padding here so you can see the background change; otherwise the button may take up the entirety of the window and you won't see a change.)
import tkinter
win = tkinter.Tk()
def change_color():
win.configure(background='black')
button = tkinter.Button(win, text='click', command=change_color)
button.pack(padx=10, pady=10)
win.mainloop()

How to remove error made when adding exit button?

from tkinter import*
import sqlite3
class login:
def __init__(self,root):
self.root=root
self.root.geometry("250x250")
self.root.title("Login")
self.root.resizable(False,False)
self.var_username=StringVar() ##variables
self.var_password=StringVar()
username=Label(self.root,text="Username",font=("Bahnschrift SemiBold",15),bg="white",fg="black").place(x=15,y=20)
username=Entry(self.root,textvariable=self.var_username,font=("Bahnschrift SemiBold",15),bg="white",fg="black").place(x=125,y=20,width=115)
password=Label(self.root,text="Password ",font=("Bahnschrift SemiBold",15),bg="white",fg="black").place(x=15,y=60)
password=Entry(self.root,textvariable=self.var_password,font=("Bahnschrift SemiBold",15),bg="white",fg="black").place(x=125,y=60,width=115)
_exit=Button(self.root,text="exit",command=self.destroy,font=("Bahnschrift SemiBold",15),bg="green",fg="white",cursor="hand2").place(x=125,y=100,width=55,height=28)
if __name__ == "__main__":
root=Tk()
obj=login(root)
root.mainloop()
it comes up with a attribute error and im not to sure how to fix it because it works in other pieces of code.
You might want to change the button command from self.destroy to self.root.destroy.
Button(self.root,
text="exit",
command=self.root.destroy,
font=("Bahnschrift SemiBold",15),
bg="green",
fg="white",
cursor="hand2").place(x=125, y=100, width=55, height=28)
As a side note, doing label = Label(root, ...).place(x=...) does not do anything (for any widget). The value of label will be stored as None and you wont be able to reference that later to change its properties. If this is the goal, then simply: Label(root, ...).place(x=...) would work. Otherwise, you'll have to create widgets in one line, and place them in the next lline
PS: It is a recommended practice to also include the error faced in order for ease of diagnosing. Please do refer How to ask for asking further questions.

Python-Tkinter: Trying to unpack a button with an if statement

I know there are better ways about this, but I cant figure out what's
wrong about this code, or at least, why it wont function the way I want it. Currently I made a simple test program to try my concept away from my
main code.
from tkinter import *
root = Tk()
test = True
def click():
global test
print("working")
test = False
button = Button(root, text="Hi", command=click)
if test:
button.pack()
root.mainloop()
Everything runs fine but when I press the button all I get is the message "working" without the button going away.
In your code python checks if test is True and as it is, it packs the button and moves on. What you need to use is <tkinter widget>.pack_forget(). It removes the widget from the screen without destroying it. If you later call pack it should put it back in its original place. This is your code with the pack_forget:
from tkinter import *
root = Tk()
def click():
print("working")
button.pack_forget()
button = Button(root, text="Hi", command=click)
button.pack()
root.mainloop()

How to create a button inside of a a Tk canvas in python 3.7

I was wondering how to put a button inside of a canvas using the tkinter module. This question was asked, but it was 5 years ago and for a different version so It was not very convenient for my situation and I am still a beginner so I only understood about 3/4 of the code in the best answer. Here is the question: How to make a Button using the tkinter Canvas widget?
from tkinter import *
root = Tk()
c=Canvas(root,width=200,height=150,bg='blue')
c.pack(side = 'top')
c.create_text(100,50,anchor='c',fill='orange',font='Times 28',text='List')
button = Button(root, text="Quit",command=root.destroy)
button.pack()
mainloop()
When I run this code it creates the button below my Canvas and not on the Canvas. I looked for help on https://docs.python.org/3.7/library/tkinter.html the guide for the IDE I am using. I could not find a way to put the button on the Canvas even though I may or may not have missed something. If this question is seen as not helpful or unnecessary I apologize and will close it immediately.
Version of Python: 3.7
Level: Beginner
Running Code on: IDLE 64-bit
OS: Windows 10
When you use pack() tkinter will place the button on it's master (root), and the area where the canvas is drawn is already occupied.
To place the button on the canvas you should use the function create_window() on the canvas:
from tkinter import *
root = Tk()
c = Canvas(root,width=200,height=150,bg='blue')
c.pack(side = 'top')
c.create_text(100, 50, anchor='c', fill='orange', font='Times 28', text='List')
button = Button(root, text="Quit", command=root.destroy)
canvas_widget = c.create_window(100, 100, window=button)
root.mainloop()
delete button.pack()
try use the code below
button = Button(root, text="Quit", command=root.destroy)
c.create_window(10, 10, anchor=NW, window=button)

Keep a menu open in Tkinter

I want to keep a menu cascade open, after a command button within the cascade is clicked. So it basically only closes when the user clicks anywhere else (like it would normally too). Can't seem to find a proper option or a method to open said menu in the callback. The invoke() function only works on buttons wihtin the cascade right? How would you go about that?
Yes, I know this was asked a long time ago, but I was curious if there was any way to accomplish this with tkinter, so I fiddled about for a while and figured out how to do it. I was unable to come up with a way to properly place the persistent menu where it was when it originally opened, but I have managed to make it persist in any location you request (I use upper-left corner of root window). And yes, I know this isn't a nice proper class based implementation, but I was just going for as simple a test as I could write without obscuring it with too many extraneous details.
try:
from tkinter import *
from tkinter.ttk import *
except:
from Tkinter import *
from ttk import *
root = Tk()
var = StringVar()
def menu_click(menu, item):
global root
var.set(item)
menu.post(root.winfo_rootx(), root.winfo_rooty())
root.option_add('*tearOff', False) # remove tearoff from all menus
Label(root, textvariable=var).pack() # just to give menu clicks some feedback
root.geometry('400x300')
menubar = Menu(root)
root['menu'] = menubar
menu_test = Menu(menubar)
menubar.add_cascade(menu=menu_test, label='Test')
menu_test.add_command(label='One', command=lambda: menu_click(menu_test, 'One'))
menu_test.add_command(label='Two', command=lambda: menu_click(menu_test, 'Two'))
menu_test.add_command(label='Three', command=lambda: menu_click(menu_test, 'Three'))
menu_cas = Menu(menu_test)
menu_test.add_cascade(menu=menu_cas, label='Four')
menu_cas.add_command(label='One', command=lambda: menu_click(menu_cas, 'Fourty One'))
menu_cas.add_command(label='Two', command=lambda: menu_click(menu_cas, 'Fourty Two'))
menu_cas.add_command(label='Three', command=lambda: menu_click(menu_cas, 'Fourty Three'))
root.mainloop()

Categories