import tkinter as tk
root = tk.Tk()
root.title("window")
yellow_header = tk.Label(root, text = 'Header', bg = 'light yellow')
yellow_header.pack(side = tk.TOP, anchor = tk.N, expand = 1, fill = tk.X)
yellow_header2 = tk.Label(root, text = 'paragraph', bg = 'light yellow')
yellow_header2.pack(side = tk.TOP, anchor = tk.N, expand = 1, fill = tk.X)
root.mainloop()
For the above code I am trying to have both these labels anchored to the top and directly below one another. Although the first label (yellow_header) anchors to the top, where as the second label (yellow_header2) when expanded move towards the centre. How can I fix this?
Thank you in advance!
Don't use expand=1. From effbot:
The expand option tells the manager to assign additional space to the widget box. If the parent widget is made larger than necessary to hold all packed widgets, any exceeding space will be distributed among all widgets that have the expand option set to a non-zero value.
With expand=1, when you make the window larger, the space is distributed between the two labels. So even though you only tell them to fill it in the X direction, they are given the space in both directions. The second label is placed directly under the space that is available to the first label, which is half of the window.
I've tried to explain and visualize the difference between expand and fill in this answer.
P.S. You don't need anchor=tk.N either. When the space available to the widget and the size of the widget are the same, the anchor option makes no difference. Also, side=tk.TOP is the default so you could decide to omit that too, leaving you with only fill=tk.X.
Looking at the docs I see:
The Text widget is used to display text in multiple lines.
and this seems to work:
import tkinter as tk
root = tk.Tk()
root.title("window")
yellow_header = tk.Label(root, text = 'Header\nParagraph', bg = 'light yellow')
yellow_header.pack(side = tk.TOP, anchor = tk.N, expand = 1, fill = tk.X)
That might be a bit OS specific and perhaps the proper way would be:
import os
...
yellow_header = tk.Label(root, text = 'Header' + os.linesep + 'Paragraph', bg = 'light yellow')
When increasing the length of the first string the second still remains in the center.
Related
I want to anchor this label but for some reason, it keeps going off the screen in my computer, i don't know if its just me but here's my code:
import tkinter as tk
root = tk.Tk()
root.attributes("-fullscreen", True)
label_frame = tk.Frame(root)
answer_label = tk.Label(label_frame, text="text")
answer_label.grid(row = 0, column = 0)
label_frame.place(anchor = "n")
root.mainloop()
Why does this label go off screen when anchored?
Consider this line of code:
label_frame.place(anchor = "n")
The anchor option tells tkinter what part of the frame is to be placed at the given coordinates. n means "north", or the top-center of the frame. So, whatever coordinates are given, the top-center portion of the frame will be at those coordinates.
Since you did not give any coordinates, they default to x=0 and y=0. Thus, the top-middle portion of the frame will be placed at 0,0. That means that the left half of the frame will be to the left of coordinate 0,0.
If you insist on using place, and if you want the frame centered, you can give a relx of .5, meaning that the anchor position (n) will be placed half-way across the width of the containing widget.
label_frame.place(relx=.5, y=0, anchor = "n")
try
label_frame.place(anchor = "nw")
Tested this and it seems to put the label in the right place.
I am making a Python program, and I am looking for ways to make a nice centre-aligned title at the top of inside my program. However, I am having trouble doing this because with the current tools I have, I would have to experiment my label spacing length to match how many characters I have for my title. Is there a way to make a Python label be certain amount of pixels long regardless of length of the text? I am specifically looking for a way of specifically making a label be a specific number of pixels long so I don't have to experiment with all these different lengths.
I tried using the "padx" and "pady" parameters, but I have found that the lengths will always change depending on the length of the text of the label itself. I also tried the "width" parameter, but it only extends by a number of textlengths long.
from tkinter import *
root = Tk()
root.geometry("960x600")
label_toptitle = Label(root,
text="Program Name",
padx=40,
pady=40,
font=(None, 40),
#height=2,
#width=30
)
root.mainloop()
This is my current code right here, but if I change the name "Program Name" to another name, the padx and pady and/or width or height functions will become not the same amount of pixels long. I need a way to make the label a fixed amount of pixels long.
Your question title mentions setting the length of a label, but it seems your real goal is to center a label without having to calculate margins.
The best solution for that is to not use padding or margins to center the widget. Just tell tkinter you want things centered when you use grid or pack, which is actually the default. You don't have to do much at all.
For example, the following will give a window with a centered title:
import tkinter as tk
root = tk.Tk()
root.geometry("960x600")
label_toptitle = tk.Label(root,
text="Program Name",
font=(None, 40),
)
label_toptitle.pack(side="top", fill="x")
root.mainloop()
Grid can center things too, though the exact syntax depends on what other rows and columns you have. Without knowing that it's hard to give a useful example.
If you really need to specify an exact width in pixels for a label, you can add a transparent one-pixel image to the label and hide it behind the text. When you add an image, the width attribute represents a width in pixels rather than characters.
Example:
pixel = tk.PhotoImage(width=1, height=1)
label = tk.Label(root, image=pixel, text="Hello", compound="center", width=100)
You could make a variable that declares the max size of a label and then use it to fix the width/height issues on all label declarations as follows:
maxSizeX = 100
maxSizeY = 100
labelTitleText = "Program Name"
labelTitleTextSize = len(labelTitleText)
labelTitle = Label(root,
text=labelTitleText,
width=(maxSizeX-labelTitleTextSize),
height=maxSizeY,
font=(None, 40)
)
Although I'm unsure as to how you would get character pixel width on the display if you could then you could change the above to:
maxSizeX = 100
maxSizeY = 100
labelTitleText = "Program Name"
labelTitleTextSize = len(labelTitleText) * pixelWidth
labelTitle = Label(root,
text=labelTitleText,
padx=(maxSizeX-labelTitleTextSize),
pady=maxSizeY,
font=(None, 40)
)
How to I prevent the automatic widening of Tkinter widgets (specifically labels)? I have a label in my code to which I pass strings of varying length. In the case that the strings are wider than the column width (using the grid layout manager), I would prefer them to be moved to a new line rather than stretching the column. Below is some code that illustrates the problem.
import Tkinter
class window(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def initialize(self):
self.grid()
self.columnconfigure(0, minsize=50)
self.columnconfigure(0, minsize=150)
self.rowconfigure(0,minsize=20)
self.rowconfigure(1,minsize=20)
self.rowconfigure(2,minsize=20)
self.labvar = Tkinter.StringVar()
self.lab = Tkinter.Label(self,bg='white',relief='groove',
textvariable=self.labvar)
self.lab.grid(row=0,column=0,rowspan=2,sticky='NSEW')
self.labvar.set("I don't want this to resize (Y dimension) ...")
self.but = Tkinter.Button(self, text='Click me!',command=self.onbut)
self.but.grid(row=2,column=0, sticky='NSEW')
def onbut(self):
self.labvar.set("I don't want this to resize (Y dimension) ...I'd rather this on a new line!")
if __name__ == "__main__":
app = window(None)
app.title('Window')
app.mainloop()
As a quick side note: what is the correct way to avoid the self.labvar.set("I dont...") line stretching over the 80 character limit? I tried using """ and breaking it over two lines but the string was then put in to the label with two lines as well.
Use wraplength option:
self.lab = Tkinter.Label(self,bg='white', relief='groove',
textvariable=self.labvar, wraplength=250)
According to The Tkinter Label Widget documentation:
Labels can display multiple lines of text. You can use newlines or use
the wraplength option to make the label wrap text by itself. When
wrapping text, you might wish to use the anchor and justify options to
make things look exactly as you wish.
...
wraplength=
Determines when a label’s text should be wrapped into multiple lines. This is given in screen units. Default is 0 (no wrapping).
If you give a label a width, it will try its best to honor that width even if the content changes. If you add text that is larger than the width, the text will be truncated. So, for example, you could create your label like this:
self.lab = Tkinter.Label(self,..., width=40)
If you instead want the text to wrap, you can define the wraplength argument, and text longer than the value will wrap to the next line. Unfortunately, the wraplength requires a screen unit (pixels) rather than character width, so you might have to do some math based on the font that you're using. Or, wait until the original widget is rendered, get it's width, and use that for the wraplength.
I was trying out something new on Tkinter (I am still a newbie), but it keeps failing...maybe someone could help out?
I wanted to create a window with several Frames, so that I can open and close them and show that way different content. However I am already stuck with not being able to "place" the, in this case a button, to the frame. Instead I get a blank frame with nothing inside...
The reason I want to use the place manager is so that I can easily choose the x and y coordinates. I don't want to create empty columns just in order to get a button appear in the middle of the screen.
Here the code:
from Tkinter import *
root = Tk()
root.title("Tkinter window")
root.geometry("800x600")
StartFrame = Frame(root)
StartFrame.pack()
Button1 = Button(StartFrame, command = StartTkinter, text = "Start", bg = "white", fg = "black", height = 2, width = 15)
Button1.place(x=0, y=50)
root.mainloop()
The problem is that you forgot to specify the dimensions of the frame. So, by default, it is created to be just 1 pixel high and 1 pixel wide. This means that its contents will not be visible on the window.
To fix the problem, you can either set exact values for these dimensions when you create the frame:
StartFrame = Frame(root, height=600, width=800)
or you can do:
StartFrame.pack(expand=True, fill="both")
to have the frame fill all available space.
How to I prevent the automatic widening of Tkinter widgets (specifically labels)? I have a label in my code to which I pass strings of varying length. In the case that the strings are wider than the column width (using the grid layout manager), I would prefer them to be moved to a new line rather than stretching the column. Below is some code that illustrates the problem.
import Tkinter
class window(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def initialize(self):
self.grid()
self.columnconfigure(0, minsize=50)
self.columnconfigure(0, minsize=150)
self.rowconfigure(0,minsize=20)
self.rowconfigure(1,minsize=20)
self.rowconfigure(2,minsize=20)
self.labvar = Tkinter.StringVar()
self.lab = Tkinter.Label(self,bg='white',relief='groove',
textvariable=self.labvar)
self.lab.grid(row=0,column=0,rowspan=2,sticky='NSEW')
self.labvar.set("I don't want this to resize (Y dimension) ...")
self.but = Tkinter.Button(self, text='Click me!',command=self.onbut)
self.but.grid(row=2,column=0, sticky='NSEW')
def onbut(self):
self.labvar.set("I don't want this to resize (Y dimension) ...I'd rather this on a new line!")
if __name__ == "__main__":
app = window(None)
app.title('Window')
app.mainloop()
As a quick side note: what is the correct way to avoid the self.labvar.set("I dont...") line stretching over the 80 character limit? I tried using """ and breaking it over two lines but the string was then put in to the label with two lines as well.
Use wraplength option:
self.lab = Tkinter.Label(self,bg='white', relief='groove',
textvariable=self.labvar, wraplength=250)
According to The Tkinter Label Widget documentation:
Labels can display multiple lines of text. You can use newlines or use
the wraplength option to make the label wrap text by itself. When
wrapping text, you might wish to use the anchor and justify options to
make things look exactly as you wish.
...
wraplength=
Determines when a label’s text should be wrapped into multiple lines. This is given in screen units. Default is 0 (no wrapping).
If you give a label a width, it will try its best to honor that width even if the content changes. If you add text that is larger than the width, the text will be truncated. So, for example, you could create your label like this:
self.lab = Tkinter.Label(self,..., width=40)
If you instead want the text to wrap, you can define the wraplength argument, and text longer than the value will wrap to the next line. Unfortunately, the wraplength requires a screen unit (pixels) rather than character width, so you might have to do some math based on the font that you're using. Or, wait until the original widget is rendered, get it's width, and use that for the wraplength.