My question is about Python 2.7 tkinter. The difficulty lies in getting all the buttons in one window, right now it opens 2 windows, one window with the size I defined, and one with all the button without a defined size.
from Tkinter import *
master = Tk()
class Calculator:
def __init__(self,master):
self.var = IntVar()
frame = Frame(master)
frame.grid()
f2 = Frame(master,width=500,height=500)
f2.grid(row=0,column=1)
def callback():
print("Hello World")
b = Button(master, text="Calc", command=callback)
b.grid()
e = Entry(master, width=10)
e.grid()
e.focus_set()
b1 = Button(master, text = "Ok", width=10, command = callback)
b1.grid(row=20, column=30)
top = Tk()
app = Calculator(top)
mainloop()
Tkinter requires exactly one instance of Tk() to start the tkinter app and one instance of mainloop() to manage the update loop.
If you call on Tk() more than once you will run into the issue of having multiple windows and things not working as you want.
If you do happen to need a 2nd or more windows then you will need to use Toplevel() to create them.
If you delete:
top = Tk()
and change:
app = Calculator(top)
to:
app = Calculator(master)
You will have everything in one window as intended.
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 got example code were there are two windows and in the second one there's a tick box that doesn't change value when it is ticked. How can I fix this? I tried returning the value of the tickbox however that failed as well.
from tkinter import *
root = Tk()
def open_custom_gui():
custom_gui()
b = Button(root,command=open_custom_gui)
b.grid(row=1,column=0)
def custom_gui():
def getinfo():
print(var1.get())
custom= Tk()
var1 = IntVar()
tickbox_1 = Checkbutton(custom,text='TEST',variable=var1,)
tickbox_1.grid(row=0,column=0)
b = Button(custom,command=getinfo)
b.grid(row=1,column=0)
custom.mainloop()
root.mainloop()
The problem has something to do with calling Tk() twice. You can fix that by explicitly creating a second Toplevel window.
from tkinter import *
root = Tk()
def open_custom_gui():
custom_gui()
b = Button(root, command=open_custom_gui)
b.grid(row=1, column=0)
def custom_gui():
def getinfo():
print(var1.get())
custom = Toplevel() # CHANGE THIS (don't call Tk() again)
var1 = IntVar()
tickbox_1 = Checkbutton(custom, text='TEST', variable=var1)
tickbox_1.grid(row=0, column=0)
b = Button(custom, command=getinfo)
b.grid(row=1, column=0)
custom.mainloop()
root.mainloop()
Alternatively you can also fix it by specifying the second Tk instance when you create the IntVar tkinter variable:
def custom_gui():
def getinfo():
print(var1.get())
custom = Tk()
var1 = IntVar(master=custom) # ADD a "master" keyword argument
tickbox_1 = Checkbutton(custom, text='TEST', variable=var1)
tickbox_1.grid(row=0, column=0)
b = Button(custom, command=getinfo)
b.grid(row=1, column=0)
custom.mainloop()
However I would suggest using the first approach because the documentation says the following (about adding the argument to the IntVar constructor):
The constructor argument is only relevant if you’re running Tkinter with
multiple Tk instances (which you shouldn’t do, unless you really know what
you’re doing).
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()
from tkinter import *
def begin():
root = Tk()
root.title("main window")
root.geometry("1920x1080")
return #How would a button be placed in this window made by this function?
root = Tk()
root.title("Start up page")
root.geometry("1920x1080")
BeginButton = Button(app, text = "Begin", command=begin, bg="green")
BeginButton.grid(column = 2, row = 2, sticky = W)
BeginButton.config(height = 10, width = 30 )
root.mainloop()
How would I create new buttons in the new window, if the new window is being made by, in this case a function known as "begin".
Any response would be much appreciated!
I believe what you want to do is to modify the root window rather than create a new one. Here is a minimal working example:
from tkinter import *
root = Tk()
class App:
def __init__(self):
root.title("Start up page")
root.geometry("1920x1080")
self.beginB = Button(root, text="Begin", command=self.begin,
bg="green", height=10, width=30)
self.beginB.grid(sticky = W)
def begin(self):
root.title("main window")
self.beginB.destroy()
del self.beginB
self.goB = Button(root, text='Go on', command=self.go_on,
bg='red')
self.goB.grid(sticky=E)
def go_on(self):
self.label = Label(root, text="you have continued")
self.label.grid(row=1, sticky=S)
App()
root.mainloop()
An advantage of defining a class is that you can make forward references. In your code, you had to define the begin function before you create the begin button. With a class, I could put it after init, which to me is a more natural order. It is ofter the case that the initialization code calls or binds more than one function.
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.