What is the X & Y for a Tkinter perfect square? - python

Quick question, when you put in something like padx = 10, pady = 10 into a Label/Button it will give you a rectangle.
Does anyone know what X by Y is a perfect square?

The width and height of a label is dependent on several factors - the font being used, the image being used, borderwidths, padding, etc. Many of those are symmetrical, however.
If you want a perfect square, you need to either start with an image (which causes width and height attributes to be treated as pixels), or a font where the characters are as wide as they are tall (even if you don't have any text).
Put another way, without an image height and width refer to a number of average size characters. Unless your font is the same in the x and y axis, these attributes will resolve to a different number of pixels. If you include an image in the label -- even just a one pixel image -- then width and height are in units of pixels rather than characters.
Here's an example that creates a square label using an image:
import tkinter as tk
root = tk.Tk()
root.geometry("200x200")
image = tk.PhotoImage(width=1, height=1)
label = tk.Label(root, image=image, width=50, height=50, background="red")
label.place(relx=.5, rely=.5, anchor="c")
root.mainloop()

Related

How to remove vertical padding of label in tkinter completely?

I want to create a desktop-application using tkinter. When placing text (of big size) in Labels, I always get a large vertical padding. Can I anyhow get rid of this additional space? I would like to place the text right on the bottom of the label.
I have already tried to set pady as well as the text anchor.
self.lbl_temp = Label(self.layout, text='20°C', font=('Calibri', 140), bg='green', fg='white', anchor=S)
self.lbl_temp.grid(row=0, column=1, sticky=S)
Here is an image of how it looks:
I would like to remove the green space below (and on top of) the text.
Removing the space above and below the text cannot be done with a Label because the height corresponds to an integer number of lines whose height is determined by the font size. This line height reserves space for letters going below the baseline, like 'g', but since you don't use such letters, you have a lot of empty space below your text (I don't have as much extra space a the top on my computer though).
To remove this space, you can use a Canvas instead of a Label and resize it to be smaller.
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, bg='green')
canvas.grid()
txtid = canvas.create_text(0, -15, text='20°C', fill='white', font=('Calibri', 140), anchor='nw')
# I used a negative y coordinate to reduce the top space since the `Canvas`
# is displaying only the positive y coordinates
bbox = canvas.bbox(txtid) # get text bounding box
canvas.configure(width=bbox[2], height=bbox[3] - 40) # reduce the height to cut the extra bottom space
root.mainloop()

Is it possible to place an image in Tkinter without a Label or canvas

I am trying to place images next to each other side by side but the labels overlap and the label sticks out.
from tkinter import *
root = Tk()
root.geometry("1000x700")
root.resizable(0, 0)
##############################################
TFi = PhotoImage(file="images/Topframe.png")
TF = Label(root, image=TFi)
TF.place(x=-3, y=-3)
BFi = PhotoImage(file="images/Botframe.png")
BF = Label(root, image=BFi)
BF.place(x=-3, y=650)
LF1i = PhotoImage(file="images/LeftFrame1.png")
LF1 = Label(root, image=LF1i)
LF1.place(x=-3, y=50)
##############################################
root.mainloop()
Is it possible to place an image in Tkinter without a Label or canvas
Your most common choices for labels are a canvas or a label. You can also put images on buttons, and embed them in a text widget.
The best choice for creating labels that are next to each other are to use pack or grid. pack is good if you're making a single horizontal or vertical grouping, but grid is better if you're making both rows and columns of widgets.
You can use place, but that requires that you do all of the math to compute the location of each image, and usually results in a user interface that isn't very resilient to changes in screen resolution. It also sometimes ends up causing you to have to do changes to every widget even if you only want to tweak the layout slightly.
My guess for why they overlap is that you aren't aware that the coordinates you give place by default specify the center of the image rather than the upper-left corner. You can specify which part of the image is at the given coordinate with the anchor option.
the label sticks out.
I'm not exactly sure what you mean by that, but if you mean that it has a 3D appearance, you can control that by giving it a borderwidth of zero and/or a relief of "flat".

Parameters like width, align, justify won't work in Tkinter Message

I'm trying to change the width of a Message widget in Tkinter by using the width parameter. I couldn't get it to work so I tried align, justify and aspect which all produced the same result - the box remains centred and the width of the text.
Here is my code:
console_Fetch = Message(text="test\ntest\ntest\ntest\ntest",bd=1,relief="sunken",width=300)
console_Fetch.grid(row=7,column=0,padx=5,pady=1,columnspan=2)
I'm obviously using .grid() to pack it into the window.
Here's a screenshot of my window:
Pragmatic answer
Often setting width in widgets is not working as expected, depending on priority of other aspects, cell width, you name it. It gets easily overruled, or depends on other conditions.
What I always do is give the grid a "skeleton" of canvases in adjecent cells, with height (or width) of zero. Subsequently stretch the widget with sticky inside their cells. Just look at the example below:
from tkinter import *
win = Tk()
console_Fetch = Message(text="test\ntest\ntest\ntest\ntest",bd=1,relief="sunken",width=3000)
canvas = Canvas(width = 500, height = 0)
canvas.grid(row=0,column=0)
console_Fetch.grid(row=1,column=0,padx=5,pady=1,columnspan=2, sticky = N+W+E+S)
win.mainloop()
The same I did in shaping the grid in the minesweeper- matrix in this answer.

tkinter - create label widget (containing text) with size defined by pixel dimensions

I am trying to make a tkinter label containing text with width and height defined by pixel dimensions. It is made clear that a label widget containing text's size is defined in terms of its text size in the docs:
If the label displays text, the size is given in text units. If the label displays an image, the size is given in pixels (or screen units). If the size is set to 0, or omitted, it is calculated based on the label contents.
I have tried using this information to achieve what I am trying to do. I want to create labels of fixed width 700 and variable height as I am creating a timetable application. Here's an example of what I have tried so far:
import tkinter as tk
root = tk.Tk()
root.geometry("800x600")
height = 20
label = tk.Label(root,width=700,bg="white",text="test",borderwidth=0,font=("Calibri",height))
label.place(x=10,y=10)
root.mainloop()
This almost achieves what I want in terms of height, but I would expect the height to be 1 pixel when height = 1, but it is actually 5 pixels (I've got very good eyesight!). As for width, its completely off the screen as its 700 times the width of a character.
Using individual frames as each "label" and then creating label widgets as children of these frames does not work either, as the frame just gets resized to fit the label. My question is: is there a way to create a text-containing label sized by pixel dimensions?
I have found a solution in my case. I used a frame, disabled its pack_propagate and made a label the child of this frame. I hope others will find it useful. This question helped me a lot.
import tkinter as tk
root = tk.Tk()
root.geometry("800x600")
height = 20
label_frame = tk.Frame(root,width=700,height=height,bg="white")
label_frame.pack_propagate(0) # Stops child widgets of label_frame from resizing it
tk.Label(label_frame,bg="white",fg="black",text="test",font=("Calibri",15)).pack()
label_frame.place(x=10,y=10)
root.mainloop()
doing a timetable is something that lends itself to using the grid packing method, which has a grid_columnconfigure and a grid_rowconfigure method which can be used to set the minimum and maximum size of a row or column, and the rate at which they expand:
import tkinter as tk
root = tk.Tk()
tk.Label(root, text="Test").grid(column=1, row=1, sticky="nesw")
root.grid_columnconfigure(1, minsize=700)
root.mainloop()

Change padding color of Label widget in ttk / python

I am trying to display an image with ttk/tkinter in python. The image has a white border, and I want to display this image on a larger white background - so it has lots of white space around.
For this I use "padx" and "pady" in the label with 100px each. Unfortunately the padding area is gray.
Now I tried changing the label's foreground and background color to no avail. The padding area stays gray. Then I put the label in a Frame widget, and tried changing the Frame's foreground/background color. But unfortunately the Frame widget does not listen to width= and height= arguments. Also if I change the foreground color the SUNKEN border changes color - really cool, but totally useless for me :/ .
Could anybody help me with this? The current nonworking code looks like this:
style = Style()
style.configure('Dlr.TFrame', background="blue", relief=SUNKEN)
frm = Frame(self, style="Dlr.TFrame") # does not work: ,height=500,width=500)
frm.grid(row=0, column=0, rowspan=8, columnspan=2, sticky=N+S+E+W)
style.configure("Dlr.TLabel", background="white")
style.configure("Dlr.TLabel.padding", background="white") # just guessed ...
self.IMG = Label(frm, style="Dlr.TLabel")
self.IMG.grid(row=0, column=0, padx=100, pady=100)
Your technique for putting the image inside a frame and then setting the frame color is the right technique.
The width and height don't work because both grid and pack cause the containing widget to "shrink-to-fit" by default. This is called geometry propagation. You can turn this feature on or off using the methods grid_propagate or pack_propagate on the containing widget.
For example, if you call frm.grid_propagate(False) and then set the widget and height of frm, the width and height will be honored.

Categories