What is the equal function of PyQt setGeometry() in tkinter? Or Is there any function works like that? I searched a bit but couldn't find, all of examples looks like tkinter works on a specific widget and we just can set width-height.
EDIT:
The setGeometry() does two things. It locates the window on the
screen and sets its size. The first two parameters are the x and y
positions of the window. The third is the width and the fourth is the
height of the window.
The nearest thing tkinter has is probably the place geometry manager. With it you can set the x,y coordinates (either absolute or relative) and the width and height attributes (also absolute or relative).
For example, to place a label at 100,100 and with a width and height 50% of its parent you would do something like this:
import tkinter as tk
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
label.place(x=100, y=100, relwidth=.5, relheight=.5)
root.mainloop()
However, place is very rarely the right choice. Tkinter is very smart about picking the right size for widgets, and for laying them out. Without knowing the actual problem you're trying to solve it's hard to give good recommendations, but almost certainly, pack or grid will work better.
You can also do something similar to #BryanOakley's answer by the grid geometry manager:
from tkinter import *
root = Tk()
label = Label(root, bg='cyan')
label.grid(ipadx=100, ipady=50, padx=50, pady=50)
UPDATE: Please feedback why you think this answer is not useful.
Related
I am using Python 3.7, and I am using tkinter to try and grid a widget in the middle of the screen. I don't want to use pack, because I still need to use grid for other widgets later. Is there a way to to grid the widget in the middle of the window?
This might not be the best solution, but one way is to essentially create an entire grid.
In short, empty grid cells with some minimum width and then place the object in the centre-most grid box.
Something similar to this:
from tkinter import *
win = Tk()
for i in range(5):
win.grid_rowconfigure(i, minsize=100)
win.grid_columnconfigure(i, minsize=100)
lbl = Label(win, text="Test")
lbl.grid(row=2, column=2)
win.mainloop()
One thing to note is with this approach you might have to fidget with other widgets such as setting varying columnspans and rowspans during declaration.
Hi I didn't really understand how furas made the below code work. Why didn't he get an error message about grid and pack on the same root when he added a box? In the addbox function he sets a frame to the root which is pack already and even uses the pack inside the function and then uses the grid.
Can someone please explain to me how this "magic" works?
a link to the his answer:
Creating new entry boxes with button Tkinter
from Tkinter import *
#------------------------------------
def addBox():
print "ADD"
frame = Frame(root)
frame.pack()
Label(frame, text='From').grid(row=0, column=0)
ent1 = Entry(frame)
ent1.grid(row=1, column=0)
Label(frame, text='To').grid(row=0, column=1)
ent2 = Entry(frame)
ent2.grid(row=1, column=1)
all_entries.append( (ent1, ent2) )
#------------------------------------
def showEntries():
for number, (ent1, ent2) in enumerate(all_entries):
print number, ent1.get(), ent2.get()
#------------------------------------
all_entries = []
root = Tk()
showButton = Button(root, text='Show all text', command=showEntries)
showButton.pack()
Thanks
There's no magic, it's just working as designed. The code uses pack in the root window, and uses grid inside a frame. Each widget that acts as a container for other widgets can use either grid or pack. You just can't use both grid and pack together for widgets that have the same master.
not really an answer but I think you will be helped by the link.
tkinter and it's layout is indeed a bit hard to understand.
I never understood how to deal with it until I stumbled over this presentation which explained the layout particulars in a way where I finally could get the hang of it.
Just putting it out there for others to find as well.
tkinter tutorial by beazley
I think you miss out on what pack and grid actually are. Consider such code:
import tkinter as tk
root = tk.Tk()
myFrame = tk.Frame(root)
myFrame.pack()
myButton1 = tk.Button(myFrame, text='This is button 1')
myButton2 = tk.Button(myFrame, text='This is button 2')
myButton1.grid(row=0, column=0)
myButton2.grid(row=1, column=0)
root.mainloop()
By creating root we create a new window. In this window we will put everything else. Then we create myFrame. Note, that the actual "thing" (in more adequate terms - widget) is created in line myFrame = tk.Frame(root). Note, that we have to specify where we are going to put this widget in brackets and we've written that it is going to be root - our main window. Blank frame probably isn't the best example since you can not see it being placed (not unless you use some more specifications at least), but still. We have created it, but not placed it in our user interface. The we use .pack() to place it. Now you refer to widgets as being used as packs or grids. That is not true though. Pack and grid are just the set of rules, on which the widgets are being placed inside some kind of window. Because of that, if you want to add something more to the root in our case, you will have to use .pack() again. Why? If you will give two sets of rules on how to place things on the screen for your computer - they will most likely conflict with each other. However, if we go one more level down and now want to place something inside our myFrame, we can again choose which set of rules to use. It is because it does not matter, where our frame is going to end up inside root, we now just want to specify where our Buttons 1 and 2 are going to end up inside the frame. Therefore we can again use .pack() or switch to .grid().
To conclude: .pack(), .grid() and .place() are sets of rules on how place widgets inside other widgets. In more general terms though these are rules on how place boxes in other boxes. One boxes in which we arrange other boxes can only have one set of rules.
I hope this example helps.
I am trying to place a button on a frame for an application that am working on...
But the frame disappears when I use pack or grid
from Tkinter import *
root=Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
root.geometry(str(width)+'x'+str(height))
frame=Frame(root,width=500, height=500, bg='black')
but1=Button(frame,text='qwe')
but1.grid()
frame.grid()
root.mainloop()
And if I use place, even worse, both of them disappear...I dont see the Frame and the Button
from Tkinter import *
root=Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
root.geometry(str(width)+'x'+str(height))
frame=Frame(root,width=500, height=500, bg='black')
but1=Button(frame,text='qwe')
but1.place()
frame.place()
root.mainloop()
but when I use pack_propagate(0), I can see them both...
from Tkinter import *
root=Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
root.geometry(str(width)+'x'+str(height))
frame=Frame(root,width=500, height=500, bg='black')
but1=Button(frame,text='qwe')
but1.pack()
frame.pack_propagate(0)
frame.pack()
root.mainloop()
My Questions are,
What does pack_propagate(0) mean ?
Why is the frame behaving weird with and without pack_propagate(0) ?
What is the equivalent of pack_propagate(0) for GRID and PLACE ?
What does pack_propagate(0) mean ?
pack_propagate(0) tells tkinter to let the parent control its own size, rather than letting it's size be determined by the children of the widget when using pack to manage the children.
Why is the frame behaving weird with and without pack_propagate(0)
I don't see any weird behavior. You'll have to be more precise about what you mean by "weird". It's behaving as documented. place will not cause the children to determine the size of the parent. If you don't give the frame a size, it's size will be 1x1 (ie: a single pixel). And, if the frame is invisible, any widgets inside the frame will also be invisible.
When you use pack or grid, the frame will try to shrink to fit its children. It doesn't disappear, you just can see it because its children are on top of it. If you add some padding, you'll see the frame.
For example, in the first block, change where you call grid on but1 to be like the following code and your black frame will appear:
but1.grid(padx=20, pady=20)
This is one of the reasons why place is rarely the right choice. Both pack and grid do a really great job of making sure all widgets are just the right size based on what is inside them.
What is the equivalent of pack_propagate(0) for GRID and PLACE
For grid it's grid_propagate. There's no equivalent for place because that's the defined behavior of place -- it never affects the size of the containing widget.
For the vast majority of cases, you should not use pack_propagate(0), grid_propagate(0), or place. When you use grid and pack properly, your gui will be the right size on every platform you run it on, no matter what the resolution and no matter what fonts the user has loaded.
I am familiarizing myself with Tkinter, and I am attempting to write a very simple program, which displays a button in a window, using the pack geometry manager.
I was experimenting with various configuration options for pack(), such as expand, fill, and side, and I've run into a peculiar problem. I have written the following code:
from Tkinter import *
root = Tk()
widget = Button(root, text='text')
widget.pack(expand=YES, fill=BOTH)
root.mainloop()
The problem is that the button expands to fill the window in the horizontal direction, but not the vertical direction. This is the same result that I get if instead of specifying fill=BOTH I use fill=X. In addition, if I specify instead fill=Y the button does not expand in either direction. Something seems to be going wrong with the fill in the vertical direction, and I cannot figure out what it might be.
I attempted to Google this problem and surprisingly found no mention of this happening to anyone else. I am using a Mac with OS X Yosemite and running python 2.7.5. I also attempted to compile with python 3.4.1 and saw no change.
Edit:
Based off of the answer and comments below, it is clear that there is nothing wrong with my code, because it seems to work on other machines. If not an error in the code, does anyone know what could possibly be causing the button to not stretch vertically when I run the above code?
This is a feature of native buttons on OSX. Buttons on OSX will be a fixed height and will not expand vertically. There is nothing you can do, short of using a different widget such as a label.
try running this code to see the behavior of fill and expand
from Tkinter import *
root = Tk()
root.geometry("500x500")
widget = Button(root, text='text1')
widget.pack(fill=X, expand=1)
widget = Button(root, text='text2')
widget.pack(fill=Y, expand=1)
widget = Button(root, text='text3')
widget.pack(fill=BOTH, expand=1)
root.mainloop()
Argument fill does fill in vertical direction as well
I am also beginner, defining geometry for fill was missing in your code as given below:
from Tkinter import *
root = Tk()
root.geometry("600x400")
widget = Button(root, text='text')
widget.pack(expand=YES, fill=BOTH)
root.mainloop()
How to create multi-lines in an entry widget in tkinter and use those inputs to create something?
For example, I want a textbox widget to come up and ask the user:
How many squares do you want? (ex: 4x4, 5x5)
What color do you want them?
And with the users input, I would like to create that many x-amount of squares in that specific height/width and specify the colors etc.
I am totally new to tkinter and I'm not really sure how to approach this.
I tried using this, but i'm not really sure how to add more lines and to use the values inputted.
import tkinter
from tkinter import *
class Squares:
root = Tk()
root.title('Random')
x = Label(text='How many squares? (ex: 4x4, 5x3)').pack(side=TOP,padx=10,pady=10)
Entry(root, width=10).pack(side=TOP,padx=10,pady=10)
Button(root, text='OK').pack(side= LEFT)
Button(root, text='CLOSE').pack(side= RIGHT)
You have a number of problems here.
I'm not sure what the Squares class is supposed to be doing, but it's basically not doing anything. You have a bunch of code that runs when you define the class, creating a few variables (which will end up as class attributes, shared by all instances of the class), and… that's it. Rather than try to figure out what you're intending here, I'm just going to scrap the class and make it all module-level code.
You never call root.mainloop(), so your program will just define a GUI and then never run it.
You don't bind your buttons to anything, so there's no way they can have any effect. You need to create some kind of function that does something, then pass it as the command argument, or .bind it later.
You don't store references for any of your controls, so there's no way to access them later. If you want to get the value out of the entry, you need some way to refer to it. (The exception is your x variable, but that's going to be None, because you're setting it to the result of calling pack on the Label, not the Label itself.)
Once you've done that, you just need to parse the value, which is pretty easy.
Putting it all together:
import tkinter
from tkinter import *
root = Tk()
root.title('Random')
Label(text='How many squares? (ex: 4x4, 5x3)').pack(side=TOP,padx=10,pady=10)
entry = Entry(root, width=10)
entry.pack(side=TOP,padx=10,pady=10)
def onok():
x, y = entry.get().split('x')
for row in range(int(y)):
for col in range(int(x)):
print((col, row))
Button(root, text='OK', command=onok).pack(side=LEFT)
Button(root, text='CLOSE').pack(side= RIGHT)
root.mainloop()
You just have to change that print to do something useful, like creating the squares.
If you don't need an outline for the text box, create_text would be the easiest thing, even though it doesn't have a wrap text feature(at least, in python 3 you can do this):
from tkinter import *
tk = Tk()
canvas = Canvas(tk, 1000, 1000)
canvas.pack()
canvas.create_text(200, 200, text="Example Text")
Try it!