Problem:
I want to create my own widget that uses an image in a button, but the image causes the button to be way too big. How can I resize the button to the normal button size (the size of normal Text).
Code:
add = Button(master=controlfrm , image=myimagepath)
add.pack()
Result:
Goal:
I want the image to be resized to a height equal to the Entry widget.
Tkinter doesn't shrink or expand images. The best you can hope for is to use the zoom and subsample methods on a PhotoImage, which will allow you to change the size by a factor of 2.
If you want to use an image on a button, and you want it to be smaller, the best solution is to start with an image that is the right size.
You can use ImageTk.PhotoImage to resize the image and call it in a Button. Use the zoom to shrink or expand your button image.
button_image_file = "images/square-button-1.png"
button_image = Image.open(button_image_file)
zoom = .40 # multiplier for image size by zooming -/+
pixels_x, pixels_y = tuple([int(zoom * x) for x in button_image.size])
button_image = ImageTk.PhotoImage(button_image.resize((pixels_x, pixels_y)))
button = tk.Button(root_main, text="Button", command=lambda: do_something(), font="Arial",
bg="#20bebe", fg="white", image=button_image)
button.place(rely=0.01, relx=.01)
Try to set the width and height properties of the image, so that the image can fit to size of the button that you require.
Related
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?
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".
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()
Is there any way to fill a Tkinter element (more specifically an oval) with an image. If not, is there any way to resize an image to fit into an oval? I also would prefer not to use PIL.
canvas.create_oval(val1, val2, val1+sz, val2+sz, fill=clr, outline=outln)
How would you get an image to fit inside a circle like so?
I would also certainly cull the edges around the image if you were wondering.
In plain Tkinter your options are limited. One thing you could do is create a
'mask' image that has a transparent circle in the middle. Then lower your
own image in behind it. (not very efficient though)
from tkinter import *
root = Tk()
canvas = Canvas(root, width=200, height=200, bd=0,
highlightthickness=0)
canvas.pack()
mask = PhotoImage(width=200, height=200)
cx,cy = 100,100 # image & circle center point
r = 100 # circle radius
r_squared = r*r
for y in range(200):
for x in range(200):
# using the formula for a circle:
# (x - h)^2 + (y - k)^2 = r^2
# any pixel outside our circle gets filled
if (x - cx)**2 + (y - cy)**2 > r_squared:
mask.put('blue', (x,y))
canvas.create_image(100,100, image=mask, anchor='c')
myimage = PhotoImage(file='bigpython.gif')
item = canvas.create_image(100,100, image=myimage, anchor='c')
canvas.lower(item)
root.mainloop()
No, there is no way to put an image inside an oval. That is to say, you can't make one fill up an oval. Images can only be rectangular.
Your only choice for resizing images without using PIL is to resize it by factors of two.
I've tried all ways to try and get a photo to fit inside a circle but the only kind-of effective way is to resize the image using the Paint 2D app in Windows and then using the resized image as the image used to fill the circle.
I'm using python,pygame and PGU to develop a game. I'd like to create a fixed size button, but it seems resize() doesn't have any effect. Here is a snippet of my code:
app = gui.App()
top = gui.Container()
button = gui.Button("Start")
button.resize(200, 100)
top.add(button, 0, 0)
app.init(top, screen)
The button will always appear at the minimum size required to display its text. Is there any way to enforce the button size with PGU?
If you want to create a fixed size button, you should initialize it, passing width and height.
Remember that, if the dimensions in pixel aren't "large enough", it forces the button to have the minimum size required to display its text, also considering padding (from style/theme, which you can also configure) etc.
Theese are three useful (of course alternative) examples:
button = gui.Button("Start", width = 200)
button = gui.Button("Start", height = 100)
button = gui.Button("Start", width = 200, height = 100)
Where the one you are looking for is the last.
The question is rather old, but still useful for others, I think.