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

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.

Related

How to change tkinter geometry values in regard to (for example) a scrolled text height?

I was wondering how do the geometry() function values in tkinter come to play with the height value of for example a scrolled text? How can I convert the units to work with each other?
For example: If I want to open a scrolled text box underneath my tkinter window with a click of a button, I know I need then to change my window's geometry() (height) value, but I don't know by how much exactly.
(In the following example I randomly added 100 to the geometry value in the function open. But I want a more specific value that translates to the 7 of the height value of the scrolled text)
from tkinter import *
from tkinter import scrolledtext
def open():
root.geometry(f'{frame_width}x{frame_height+100}')
st.pack(side="bottom")
frame_width = 900
frame_height = 500
root = Tk()
root.geometry(f'{frame_width}x{frame_height}')
root.configure(bg='white')
root.resizable(False, False)
open_st = Button(root, text="OPEN SCROLLED TEXT", command= open)
open_st.pack()
st = scrolledtext.ScrolledText(root, width=frame_width, height=7)
root.mainloop()
Widgets that contains text usually provide their width and height in character space. This means tkinter takes the average width and height of your font and multiplies it with the given number in width and height.
There are mainly two ways to deal with that, either tk.Font.measure or metrics, if you want to convert characters to pixel or the much more comfortable way by just asking the widget for it's size via winfo. Happily your case fits for the latter.
The alternate code would looks like this:
def open_text():
st.pack(side="bottom")
width, window_height = root.winfo_width(), root.winfo_height()
requested_text_height = st.winfo_reqheight()
new_height = window_height + requested_text_height
root.geometry(f'{width}x{new_height}')
Please note that I have named your function differently. Cause you redefined open in the global namespace of your module and this could lead to unintended behavior. In addition I wonder why you want to do it like this and not just let the geometry managers do their job?

how to set width of text widget in tkinter to get text widget equal to length of line

This problem drives me crazy as it looks trivial but i have already wasted many hours to find a solution but still no success. I need help.
Let's say the line is 'HelloHelloHelloHelloHello', the font is Georgia 17. How to find a correct value for the width to get the width of the text widget equal to the length of line? "The width of the widget in characters (not pixels!), measured according to the current font size." My findings show that people asking similar questions get answers about using font measure method, but it doesnt work...
import tkinter
import tkinter.font as tkFont
txt='HelloHelloHelloHelloHello'
root=tkinter.Tk()
t_Font = tkFont.Font(family='Georgia', size=17)
width=t_Font.measure(txt)
t=tkinter.Text(root,width=width,font=('Georgia',17))
t.insert(1.0,txt)
t.pack()
The result is ridiculous http://joxi.net/E2p1NJlT7NgjvA.jpg (with width=280). Empirical research shows that 20 is a correct value..but how to get it? Using len(txt) looks much better but i believe there should be a good solution. Can't understand what I am missing here...
If you want the Text widget having width in pixels around the width of the text, you can put the Text widget inside a frame and set the size (in pixels) of the frame to the desired value and then use .place() on the Text widget to fill the frame:
t_Font = tkFont.Font(family='Georgia', size=17)
width, height = t_Font.measure(txt), t_Font.metrics('linespace')
print(width, height)
lines = 20
# +4 to include the width of the border (default 1) and padding (default 1)
frame = tkinter.Frame(root, width=width+4, height=lines*height+4)
frame.pack()
# put text box inside the frame
t = tkinter.Text(frame, font=t_Font)
t.insert(1.0, txt)
t.place(relwidth=1, relheight=1) # fill the available space of the frame

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

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()

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".

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()

Categories