This question already has an answer here:
How do I create child windows with Python tkinter?
(1 answer)
Closed 5 years ago.
I am quite new to Python and started learning Tkinter yesterday. I am creating a banking system and I have a Menu made out of the buttons. The problem that I have is that I do not know how to open an additional window when the button is clicked. I have tried with top=Toplevel(), but it only opens two windows on top of each other. What I need is for the additional window to open only when it is activated with a button(event). Can someone help me because I am really stuck as I have about six buttons?
My code so far is:
root.minsize(width=400, height=400)
root.maxsize(width=400, height=400)
root.configure(background='#666666')
label = Frame(root).pack()
Lb = Label(label, text='Welcome to Main Menu',bg='#e6e6e6', width=400).pack()
menu = Frame(root,).pack()
btn_1 = Button(menu, text='Make Deposit', width=15, height=2).pack(pady=5)
btn_2 = Button(menu, text='Withdrawal', width=15, height=2).pack(pady=5)
btn_3 = Button(menu, text='Accounts', width=15, height=2).pack(pady=5)
btn_4 = Button(menu, text='Balance', width=15 ,height=2).pack(pady=5)
btn_5 = Button(menu, text='Exit', width=15, height=2).pack(pady=5)
root.mainloop()
Thank you for the help in advance
Maybe this could work:
from Tkinter import *
class firstwindow:
def __init__(self):
#Variables
self.root= Tk()
self.switchbool=False
#Widgets
self.b = Button(self.root,text="goto second window",command= self.switch)
self.b.grid()
self.b2 = Button(self.root,text="close",command= self.root.quit)
self.b2.grid()
self.root.mainloop()
#Function to chage window
def switch(self):
self.switchbool=True
self.root.quit()
self.root.destroy()
class secondwindow:
def __init__(self):
self.root= Tk()
self.b2 = Button(self.root,text="close",command= self.root.quit)
self.b2.grid()
self.root.mainloop()
one = firstwindow()
if one.switchbool:
two = secondwindow()
Take a look to the Tkinter reference. Check all universal methods and widgets methods. You can do anything you want.
Below is a small example of how you can open a window by clicking on a button. When the user clicks on the button, the function open_window, which was passed to the command option of the button, is called.
import tkinter as tk
def open_window():
top = tk.Toplevel(root)
tk.Button(top, text='Quit', command=top.destroy).pack(side='bottom')
top.geometry('200x200')
root = tk.Tk()
tk.Button(root, text='Open', command=open_window).pack()
tk.Button(root, text='Quit', command=root.destroy).pack()
root.mainloop()
Related
Hi I am pretty new to tkinter and have being trying to create a button that opens a window then a have a button in the new window the gives a message when pressed. I ran into the problem that the only whay I could get it to recognise the function I wrote was to write it inside the function that opens the second window. I don't know if I have being searching for the wrong things but I can't find how to do this properly. Can someone help me out Here is my code
from tkinter import *
master = Tk()
master.title("frame control")
def win():
window2 = Toplevel()
def open():
stamp = Label(window2, text="Staped").pack()
lab2 = Button(window2,text = "yo ",command = open).pack()
lab1 = Button(master,text = " open a new window" , command = win).pack()
mainloop()
This is your code but with best practises:
import tkinter as tk
def create_stamp():
stamp = tk.Label(window2, text="Stamp")
stamp.pack()
def create_second_win():
global window2
window2 = tk.Toplevel(root)
lab2 = tk.Button(window2, text="Click me", command=create_stamp)
lab2.pack()
root = tk.Tk()
root.title("Frame control")
button = tk.Button(root, text="Open a new window", command=create_second_win)
button.pack()
root.mainloop()
I made window2 a global variable so that I can access it from create_stamp. Generally it is discouraged to use from ... import *. As #Matiiss said, sometimes you can have problems with global variables if you don't keep track of the variable names that you used.
If you want to avoid using global variables and want to use classes, look at this:
import tkinter as tk
class App:
def __init__(self):
self.stamps = []
self.root = tk.Tk()
self.root.title("Frame control")
self.button = tk.Button(self.root, text="Open a new window", command=self.create_second_win)
self.button.pack()
def create_stamp(self):
stamp = tk.Label(self.window2, text="Stamp")
stamp.pack()
self.stamps.append(stamp)
def create_second_win(self):
self.window2 = tk.Toplevel(self.root)
self.lab2 = tk.Button(self.window2, text="Click me", command=self.create_stamp)
self.lab2.pack()
def mainloop(self):
self.root.mainloop()
if __name__ == "__main__":
app = App()
app.mainloop()
As #Matiiss mentioned it would be more organised if you move the second window to its own class. For bigger projects it is a must but in this case you don't have to.
I have a readymade game(2048), where the game starts without a welcome window, so, I have just made a welcome window with a bunch of buttons like New Game and AI mode, now when I click the New Game button, I expect to get a new window where the game can be played. However, the game displays at the bottom of the main window, and another window that is supposed to display the actual game displays nothing.
# mainwindow.py file:
from tkinter import *
from PIL import ImageTk, Image
import game_2048
root = Tk()
root.iconbitmap('unnamed.ico')
root.title('2048')
bg = ImageTk.PhotoImage(Image.open("welcome.png"))
my_canvas = Canvas(root, width=780, height=550)
my_canvas.grid()
my_canvas.create_image(0, 0, image=bg, anchor=NW)
button1 = Button(root, text="New Game", fg="black", bg="#ddf0d0", padx=3,
pady=3, font=('Helvetica', '12', 'bold'), activebackground="#94d3c3", command=lambda: game_2048.mains(root)
)
button2 = Button(root, text="AI Mode", fg="black", bg="#ddf0d0",
padx=3, pady=3, font=('Helveica', '12', 'bold'), activebackground="#94d3c3")
button1_window = my_canvas.create_window(10, 10, anchor=NW, window=button1)
button2_window = my_canvas.create_window(120, 10, anchor=NW, window=button2)
root.mainloop()
And I have tried to modify the game_2048 file i.e. 2048 game like this:
def mains(root):
Top = Toplevel(root)
l1 = Button(Top, command=lambda:Game())
l1.pack()
class Game(tkinter.Frame):
def __init__(self):
tkinter.Frame.__init__(self)
self.grid()
self.master.title('2048')
self.main_grid = tkinter.Frame(
self, bg=c.GRID_COLOR, bd=3, width=400, height=400)
self.main_grid.grid(pady=(80, 0))
self.make_GUI()
self.start_game()
self.master.bind("<Left>", self.left)
self.master.bind("<Right>", self.right)
self.master.bind("<Up>", self.up)
self.master.bind("<Down>", self.down)
self.mainloop()
if __name__ == "__main__":
mains()
I am pretty sure that I have made some mistakes in the mains() function as a result of which I am not getting the desired output. So my question is what should I do to rectify these mistakes?
Here are the changes I made to your code:
Removed import mainwindow from game_2048.py, as it will lead to circular import calling the functions twice.
You created a class inheriting from a Frame, this frame is just like any other tkinter widget, requires to be placed in the window using geometric manager, like pack()/grid()/place(), you did not do that
I also destroyed the root window before creating another new root window. Also note that instead of using Toplevel, I used Tk. This is done, so that closing the game window will close the app. But if using Toplevel, you will have to close the menu window too.
from tkinter import *
import tkinter
import random
import colors as c
def mains(root):
root.destroy()
root = Tk()
def init(root):
l1.destroy()
game = Game(root)
game.pack()
l1 = Button(root, text='Start Game',command=lambda: init(root))
l1.pack()
class Game(tkinter.Frame):
def __init__(self, parent):
tkinter.Frame.__init__(self, parent)
.......
But if you were to ask me, I would not go for such structure, but this will work here too. Understand this, work on it, implement your own structure that does not call more than one Tk().
I have a GUI using Tkinter, it has a main screen and then when you press a button a popup window appears, where you select a checkbutton and then a email will get sent to you.
Not matter what I do, I cannot read the value of the checkbutton as 1 or True it always = 0 or False.
This is my code:
import tkinter as tk
from tkinter import *
import time
root = tk.Tk()
root.title('Status')
CheckVar1 = IntVar()
def email():
class PopUp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
popup = tk.Toplevel(self, background='gray20')
popup.wm_title("EMAIL")
self.withdraw()
popup.tkraise(self)
topframe = Frame(popup, background='gray20')
topframe.grid(column=0, row=0)
bottomframe = Frame(popup, background='gray20')
bottomframe.grid(column=0, row=1)
self.c1 = tk.Checkbutton(topframe, text="Current", variable=CheckVar1, onvalue=1, offvalue=0, height=2, width=15, background='gray20', foreground='snow', selectcolor='gray35', activebackground='gray23', activeforeground='snow')
self.c1.pack(side="left", fill="x", anchor=NW)
label = tk.Label(bottomframe, text="Please Enter Email Address", background='gray20', foreground='snow')
label.pack(side="left", anchor=SW, fill="x", pady=10, padx=10)
self.entry = tk.Entry(bottomframe, bd=5, width=35, background='gray35', foreground='snow')
self.entry.pack(side="left", anchor=S, fill="x", pady=10, padx=10)
self.button = tk.Button(bottomframe, text="OK", command=self.on_button, background='gray20', foreground='snow')
self.button.pack(side="left", anchor=SE, padx=10, pady=10, fill="x")
def on_button(self):
address = self.entry.get()
print(address)
state = CheckVar1.get()
print (state)
time.sleep(2)
self.destroy()
app = PopUp()
app.update()
tk.Button(root,
text="EMAIL",
command=email,
background='gray15',
foreground='snow').pack(side=tk.BOTTOM, fill="both", anchor=N)
screen = tk.Canvas(root, width=400, height=475, background='gray15')
screen.pack(side = tk.BOTTOM, fill="both", expand=True)
def latest():
#Other code
root.after(300000, latest)
root.mainloop()
The popup works perfectly, and the email will print when entered but the value of checkbox is always 0.
I have tried:
CheckVar1 = tk.IntVar() - No success
self.CheckVar1 & self.CheckVar1.get() - No success
Removing self.withdraw() - No success
I only have one root.mainloop() in the script, I am using app.update() for the popup window because without this it will not open.
I have checked these existing questions for solution and none have helped:
Self.withdraw - Can't make tkinter checkbutton work normally when running as script
Self.CheckVar1 - TKInter checkbox variable is always 0
Only one instance of mainloop() - Python tkinter checkbutton value always equal to 0
I have also checked very similar questions but I wasn't going to post them all.
Any help is appreciated.
The problem is that you have two root windows. Each root window gets its own internal tcl interpreter, and the widgets and tkinter variables in one are completely invisible to the other. You're creating the IntVar in the first root window, and then trying to associate it with a checkbutton in a second root window. This cannot work. You should always only have a single instance of Tk in a tkinter program.
because of variable scope
try to put CheckVar1 = IntVar() inside the class
use it with self like this
self.CheckVar1 = tk.IntVar() # object of int
self.CheckVar1.set(1) # set value
variable=self.CheckVar1 # passing to the checkbutton as parameter
state = self.CheckVar1.get() # getting value
My program should destroy btn1 and create it again after one second in loop. I don't no why but my program only destroy btn1 and don't show this again. Anyone have idea why?
from tkinter import *
import random
def hide():
btn1.destroy()
btn1.after(2000,hide)
def show():
btn1 = Button(root, bd=c, text="Hello\nWorld", relief="ridge", cursor="trek")
btn1.grid(row=0,column=0)
btn1.after(3000,show)
root = Tk()
root.geometry("350x150+400+400")
c=random.randint(20,40)
btn1 = Button(root, bd=c, text="Hello\nWorld", relief="ridge", cursor="trek")
btn1.grid(row=0,column=0)
btn1.after(2000,hide)
btn1.after(3000,show)
root.mainloop()
It will work if you use grid_forget instead of creating a new object each time. Note that what happens at multiples of 6 seconds (2000 X 3000) depends on which one is the last one to execute.
def hide():
btn1.grid_forget()
btn1.after(2000,hide)
def show():
btn1.grid(row=0,column=0)
btn1.after(3000,show)
root = Tk()
root.geometry("350x150+400+400")
c=random.randint(20,40)
btn1 = Button(root, bd=c, text="Hello\nWorld",
relief="ridge", cursor="trek")
btn1.grid(row=0,column=0)
btn1.after(2000,hide)
btn1.after(3000,show)
root.mainloop()
I have a bit of difficulty with the code below. Basically, I want the code to, when I press the Enter button, to open the window2 but also close window1 simultaneously so that there is only one window and not two of them.
The code is...
from tkinter import *
def window1():
window = Tk()
window.title("Welcome")
f = Frame()
f.pack()
label1 = Label(window, text = "Welcome to the random window")
label1.pack()
button1 = Button(window, text = "Enter...", command = window2)
button1.pack()
def window2():
screen = Tk()
screen.title("Pop-Up!")
fr = Frame()
fr.pack()
label2 = Label(screen, text = "This is a pop-up screen!")
label2.pack()
button2 = Button(screen, text = "Return", command = window1)
button2.pack()
window1()
This is "Bad" because you're using two instances of Tk. Try instead using TopLevels.
import tkinter as tk
def window1():
window = tk.Toplevel(root)
window.title("Welcome")
# etc etc ...
tk.Button(window,text="Enter...",command=lambda: window2(window)).pack()
def window2(old_window):
old_window.destroy()
# window2 stuff
root = tk.Tk()
root.iconify() # to minimize it, since we're just using Toplevels on top of it
window1()
root.mainloop()
When you are using the Tk() function, you are creating a new instance of the Tcl/tkinter interpreter. Instead use Toplevel() which will make a new window in the current interpreter.