I just learned how to use tkinter in Python (3.2.2), and I'm having some problem using the grid manager. When I put button.grid(sticky=SE), for example, the button is not being put in the bottom-right and is just being put in the upper-left, ignoring the sticky value. What am I doing wrong here? I tried to search it but I couldn't really find out what I am doing wrong.
You probably need to set a minimum size for the widget containing the button.
If you don't, the container widget may shrink to occupy only the space required to display the button. If so, the sticky option will be meaningless since the container widget gives no space to show any difference.
For example, using a tk.Frame as the container widget:
import Tkinter as tk
class SimpleApp(object):
def __init__(self, master, **kwargs):
title = kwargs.pop('title')
frame = tk.Frame(master, borderwidth=5, bg = 'cyan', **kwargs)
frame.grid()
button = tk.Button(frame, text = title)
button.grid(sticky = tk.SE)
frame.rowconfigure('all', minsize = 200)
frame.columnconfigure('all', minsize = 200)
def basic():
root = tk.Tk()
app = SimpleApp(root, title = 'Hello, world')
root.mainloop()
basic()
yields
PS. I don't have tkinter installed in Python3.2 so I can't test this, but I think the only change you need to make this work with Python3.2 is
import tkinter as tk
instead of
import Tkinter as tk
When you say "What am I doing wrong here", you need to post your code, otherwise how would anyone be able to guess what's wrong.
The following works fine, placing the button in the lower right corner (SE) of the grid cell - the default is center, not upper left (NW).
from tkinter import Button, Label, Entry, Tk, SE
root = Tk()
Label(text="Lots o' Stuff", width=30, height=15,
borderwidth=2, relief="raised").grid(rowspan=2)
Entry().grid(row=0, column=2)
Button(text="Hit Me").grid(row=1, column=2, sticky=SE)
root.mainloop()
Related
I wonder if someone could tell me if its possible to update toplevel windows using external functions. I've replicated my issue below what I need to do is update the Toplevel(master) using the function updatelabel(). I have used similar external function to update items in root which works like a dream. However, with the top level window I always get the
NameError: name 'newWindow' is not defined
The only work around I found was to kill the newWindow using newWindow.destroy() on each load but this method makes the screen pop up and then close again which doesn't look pretty. Any help most welcome thanks.
from tkinter import *
from tkinter.ttk import *
master = Tk()
master.geometry("200x200")
def updatelabel():
Label(newWindow,
text="I changed").pack()
def openNewWindow():
# Toplevel object which will
# be treated as a new window
newWindow = Toplevel(master)
# sets the title of the
# Toplevel widget
newWindow.title("New Window")
# sets the geometry of toplevel
newWindow.geometry("200x200")
# A Label widget to show in toplevel
Label(newWindow,
text="I want to change").pack()
button1 = Button(newWindow,
text="Click me to change label", command=updatelabel).pack()
btn = Button(master,
text="open a new window",
command=openNewWindow)
btn.pack(pady=10)
mainloop()
Your “newWindow” is defined in your “openNewWindow” function and so it basically only exists in there, you could probably fix this by either defining “newWindow” outside of the function, or by using it as an argument(just add it to the brackets and give it a name in the function itself’s brackets) calling “updateLabel”
I think this should work, though I haven’t worked with tkinter in a bit so don’t blame me if it doesn’t
from tkinter import *
from tkinter.ttk import *
master = Tk()
master.geometry("200x200")
def updatelabel(newWindow):
Label(newWindow,
text="I changed").pack()
def openNewWindow():
# Toplevel object which will
# be treated as a new window
newWindow = Toplevel(master)
# sets the title of the
# Toplevel widget
newWindow.title("New Window")
# sets the geometry of toplevel
newWindow.geometry("200x200")
# A Label widget to show in toplevel
Label(newWindow,
text="I want to change").pack()
button1 = Button(newWindow,
text="Click me to change label", command= lambda: updatelabel(newWindow)).pack()
btn = Button(master,
text="open a new window",
command=openNewWindow)
btn.pack(pady=10)
mainloop()
I have been creating an application for taking the test. So, for that, I have to do two things.
First, disable the drag of the Tkinter window and don't let the user focus on other windows rather than my application window. This means I wanted to make my application such that, No other application can be used while my application is in use.
Try this:
import tkinter as tk
class FocusedWindow(tk.Tk):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# Force it to be unminimisable
super().overrideredirect(True)
# Force it to always be on the top
super().attributes("-topmost", True)
# Even if the user unfoceses it, focus it
super().bind("<FocusOut>", lambda event: self.focus_force())
# Take over the whole screen
width = super().winfo_screenwidth()
height = super().winfo_screenheight()
super().geometry("%ix%i+0+0" % (width, height))
root = FocusedWindow()
# You can use it as if it is a normal `tk.Tk()`
button = tk.Button(root, text="Exit", command=root.destroy)
button.pack()
root.mainloop()
That removed the title bar but you can always create your own one by using tkinter.Labels and tkinter.Buttons. I tried making it work with the title bar but I can't refocus the window for some reason.
One way to do this is by the following, another could be to overwrite the .geometry() method of tkinter.
In the following code I simply had get the position by using winfo_rootx and winfo_rooty. After this you can force the window by calling the geometry method via binding the event every time the window is configured.
import tkinter as tk
def get_pos():
global x,y
x = root.winfo_rootx()
y = root.winfo_rooty()
def fix_pos():
root.bind('<Configure>', stay_at)
def stay_at(event):
root.geometry('+%s+%s' % (x,y))
root = tk.Tk()
button1 = tk.Button(root, text='get_pos', command=get_pos)
button2 = tk.Button(root, text='fix_pos', command=fix_pos)
button1.pack()
button2.pack()
root.mainloop()
I'm trying to make a simple outline for a gui, and I'm getting the warning
"variable" May be undefined or defined from star imports: tkinter for all of my variables.
Here is my code:
from tkinter import *
class myApp :
def __init__(self, gui,) :
self.root = gui
self.bframe = Frame(self.root) # Create a container Frame at bottom
self.bframe.pack(side=BOTTOM)
self.xlabel = Label(self.root, text="Item ID") # Create the Label
self.xlabel.pack(side=LEFT)
self.xentry = Entry(self.root, bd=5) # Create the Entry box
self.xentry.pack(side=LEFT)
self.xentry.bind('<Return>', self.showStockItem)
self.xentry.focus_set() # Set focus in the Entry box
self.xopen = Button(self.root, text="Show", command=self.showStockItem) # Create the open Button
self.xopen.pack(side=LEFT)
self.xquit = Button(self.bframe, text="Quit", command=self.quitit) # Create the quit Button
self.xquit.pack(side=BOTTOM)
return
gui = Tk()
gui.title("Travel")
app = myApp(gui)
gui.mainloop()
from tkinter import *
In this line, you import everything from tkinter. This is not recommended, so linter will warn you. But if you really want to do this, it's OK, just ignore it.
To be better, you should explicitly import what you need. For example:
from tkinter import Tk, Label, Frame, Entry, Button
Consider using:
import tkinter as tk
and then, prefix all your calls like:
root = tk.Tk()
or,
variableName.pack(side = tk.LEFT)
and so on...
I create a check button / box, with the following call
x=ttk.Checkbutton(tab1,state='disabled',command = lambda j=i,x=k: fCheckButton(j,x))
x.state(['selected'])
The box appears fine and is selected, but it appears on load up, with a black box in it, which seems to have nothing to do with the state of it.
I have looked for reasons why, but can't actually find anyone with the same problem.
thanks
I hit this problem when creating a Checkbutton object from within a class. I was declaring a local variable instead of a member variable in the class. The local variable was getting out of scope causing the checkbox value to not be either a 0 or a 1.
Wrong:
import tkinter as Tk
from tkinter import IntVar
from tkinter.ttk import Frame, Checkbutton
class TestGui(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
var1 = IntVar()
var1.set(1)
button = Checkbutton(parent,
text="Pick me, pick me!",
variable=var1)
button.grid()
root = Tk.Tk()
app = TestGui(root)
root.mainloop()
Fixed:
import tkinter as Tk
from tkinter import IntVar
from tkinter.ttk import Frame, Checkbutton
class TestGui(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.var1 = IntVar()
self.var1.set(1)
button = Checkbutton(parent,
text="Pick me, pick me!",
variable=self.var1) # note difference here
button.grid()
root = Tk.Tk()
app = TestGui(root)
root.mainloop()
I've had a similar issue on Windows 7.
After loading the app, one of my checkbuttons contained a filled square. But after clicking on it, it became a normal checkbutton:
In my case, it was because I had multiple checkbuttons sharing the same variable... After creating a separate Tk.IntVar() variable for each checkbutton, the problem disappeared.
import Tkinter as Tk
import ttk
root = Tk.Tk()
checkVar = Tk.IntVar()
x = ttk.Checkbutton(root, variable=checkVar, text="check 1")
x.pack()
checkVar2 = Tk.IntVar()
y = ttk.Checkbutton(root, variable=checkVar2, text="check 2")
y.pack()
root.mainloop()
I am trying to make a GUI in Tkinter and am wondering how to refresh a window, namely if I fill in a rectangle, I want the GUI to delete it a specified time later. How would I go about doing this? Documentation on Tkinter seems to be thin...
Each Tkinter widget has a after method, which you can use to call your rectangle delete function e.g. in the example below first I change a msg using after, and then destruct the window using after
from Tkinter import *
def changeMsg():
label.configure(text="I will self destruct in 2 secs")
label.after(2000, root.destroy)
root = Tk()
mainContainer = Frame(root)
label = Label(mainContainer, text="")
label.configure(text="msg will change in 3 secs")
label.pack(side=LEFT, ipadx=5, ipady=5)
mainContainer.pack()
label.after(3000, changeMsg)
root.title("Timed event")
root.mainloop()