Set Inputfield to have a transparent background - python

I've got a problem.
I want to realize an Inputfield ( Text() ) in front of an image ( ImageTk.Photoimage() )
But the white background of the Inputfield covers the image. So my Question is, how can i set the background of Text() to full transparency?
from Tkinter import *
from PIL import ImageTk, Image
path = 'C:/Users/David/Pictures/5.png'
root = Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
Text(root).pack()
root.mainloop()

Make a Text widget at full width of the parent window ( and remain that )
Text(root).pack( side = "BOTTOM", fill ="X", expand = 1 )
or
Text(root).grid( sticky = W+S+E )
Make a Text widget have a transparent background
Ref. >>> https://stackoverflow.com/a/18479446/3666197

to make a transparent background:
if you pack your image into a canvas widget then you can post text over the top of it using
canvas.create_text()
a good reference for the canvas widget can be found here:
http://effbot.org/tkinterbook/canvas.htm
to control how wide the widget packs itself
If you are using pack you could use either:
Text.pack(fill="x")
or:
Text.pack(fill="x", expand=True)
# this one would also make it expand if you resize the window
or if you use grid:
Text.grid(sticky="nesw")
and to make it expand if you resize window:
parent.grid_columnconfigure(columnnumber, weight=1)
if you use grids you can change the relative rate at which your widgets expand by changing the weight of that row/column
James

Related

Python - placing Entry with relative X/Y position changes background stretch in Tkinter

I have an application with Tkinter in Python.
I put an image as a background, and the user can resize the window's size and the image is stretched.
I added an Entry and put it in the center of the application, but now if the user resizes the window - now the background is not streched well.
Resize function:
def bg_resize(e):
global heig, wid, bbg, resized_bbg, newBg, clicked
bbg = Image.open(r"C:\backround.png")
resized_bbg = bbg.resize((e.width, e.height), Image.ANTIALIAS)
heig = e.height
wid = e.width
newBg = ImageTk.PhotoImage(resized_bbg)
cnv.create_image(0, 0, image=newBg, anchor="nw")
Widget placement:
searchEntry = Entry(cnv, width=100).place(rely=.5, relx=.5, anchor= "center")
before resize:
after resize:

Python Tkinter - How to contain a widget within a Canvas?

I'm trying to put an image inside the Canvas that has the same width as the Canvas but the height is according to the aspect ratio, and using a Scrollbar to scroll the same. Here's the relevant part of the code.
#Canvas and Scrollbar
img_canvas = Canvas(main_frame, height = height, width = width+15)
vsb = Scrollbar(img_canvas, orient = 'vertical')
vsb.pack(side = 'right', fill = 'y')
vsb.configure(command = img_canvas.yview)
canvas.config(yscrollcommand = vsb.set)
text.window_create("end", window = img_canvas)
text.insert("end", "\n")
#Insert Image into the Canvas
im = Image.open(str(opath)+"//Ques_"+str(temp)+".png")
w, h = im.size
im = im.resize((width, int((h/w)*width)), Image.ANTIALIAS)
img = ImageTk.PhotoImage(im)
ques = Label(img_canvas, image = img)
ques.image = img
ques.pack(side = 'left', expand = False)
The problem I am encountering is that the image expands completely in y, and hence can't be scrolled.
I want to contain the part of the image that fits into the Canvas's dimensions and the rest can be scrolled.
You have to use create_image to put an image on a canvas and have it be scrollable. You can't use pack or place or grid. You don't need to put the image in a label first, unless you specifically want it to be a label with a border. In that case, you need to use create_window to add the label to the canvas.

Dynamically resize two panels in tkinter

I have setup 2 panels in a frame as so:
frameA = Frame(master)
frameA.pack(side=LEFT, fill=BOTH, expand=YES)
frameB = Frame(master)
frameB.pack(side=RIGHT, fill=BOTH, expand=YES)
recale = 0.4
self.img = ImageTk.PhotoImage(img.resize((int(rescale*width), int(recale*height)), Image.ANTIALIAS)
self.panelA = Label(frameA, image=self.img)
self.pabelA.pack(side=LEFT, fill=BOTH, expand=YES)
self.panelB = Label(frameB, image=self.img)
self.pabelB.pack(side=LEFT, fill=BOTH, expand=YES)
Now, the size of the 2 panels are determined by the image size which I have resized to 0.4 times the original size. How can I dynamically set rescale such that the width of each of the panels takes up the entire width of the master frame when I press the maximize button(this is not a button I made, but rather the little square button next to minimize, and close on the top right) on the GUI?
When you use pack(fill=BOTH, expand=YES) then tkinter automatically resizes Frame and Label to fit window - so you don't have to resize it manually. But it will never resize PhotoImage and Image so it may looks like it doesn't resize Label and Frame. So your real problem probably is "how to resize Image when you change window's size"
Using
root.bind('<Configure>', on_resize)
you can run function when window changed size and then you can generate new image and replace in Label
This function will be executed not only for window but also fro every widget in window so I use str(event.widget) == '.' to resize it only when it is executed for window.
import tkinter as tk
from PIL import Image, ImageTk
def on_resize(event):
global rescaled_img
global photo
#print('[DEBUG] on_resize:', event.widget)
# resize only when root window changes size
if str(event.widget) == '.':
# generate new image
width = event.width//2 # -2 # -2*border
height = event.height # -2 # -2*border
rescaled_img = original_img.resize((width, height), Image.ANTIALIAS)
photo = ImageTk.PhotoImage(rescaled_img)
# replace images in labels
label_left['image'] = photo
label_right['image'] = photo
# ---- main ---
# resize at start
original_img = Image.open('image.jpg')
rescale = 0.4
width = int(rescale * original_img.width)
height = int(rescale * original_img.height)
rescaled_img = original_img.resize((width, height), Image.ANTIALIAS)
root = tk.Tk()
photo = ImageTk.PhotoImage(rescaled_img)
label_left = tk.Label(root, image=photo, border=0) # if border > 0 then you have to use `-2*border` in on_resize
label_left.pack(side='left', fill='both', expand=True)
label_right = tk.Label(root, image=photo, border=0) # if border > 0 then you have to use `-2*border` in on_resize
label_right.pack(side='left', fill='both', expand=True)
# resize when window changed size
root.bind('<Configure>', on_resize)
root.mainloop()
I tried to bind to label as you can see in some code in Tkinter resize background image to window size but it didn't work correctly - at start it makes images bigger and bigger till window fill all screen. Or at start it makes images small and small till window has no size.
if Label has border bigger then 0 then you have to substract 2*border from image size.

How can you have a background image with text on top on a button on tk?

I am trying to make tk buttons look better by adding a button background. The issue is, I can use an image or text, but not both, for a tk button.
How can you have both?
This is what I have tried:
from tkinter import *
from PIL import Image, ImageTk
print("I ran")
master = Tk()
canvas_width = 800
canvas_height = 400
window = Canvas(master,
width=canvas_width,
height=canvas_height)
img = Image.open("images/button_black.png").resize((80,40))
ph_image = ImageTk.PhotoImage(img)
l = Label(master, text='Button', image=ph_image, compound=CENTER, fg="white")
l.pack(side=LEFT)
button = Button ( master, image=l)
window.pack()
mainloop()
To use both an image and text you must set the compound option. From the canonical documentation:
Specifies if the widget should display text and bitmaps/images at the same time, and if so, where the bitmap/image should be placed relative to the text. Must be one of the values none, bottom, top, left, right, or center. For example, the (default) value none specifies that the bitmap or image should (if defined) be displayed instead of the text, the value left specifies that the bitmap or image should be displayed to the left of the text, and the value center specifies that the bitmap or image should be displayed on top of the text.
Example:
The following example uses this image:
The program renders like this when using compound="center":
import tkinter as tk
image_data = '''
R0lGODdhyABkAKIAAAAAAP8mAP/7AP///wAAAAAAAAAAAAAAACH5BAkAAAQALAA
AAADIAGQAAAP/KLrc/jDKSau9OOvNu/9gKI5kaZ5oqq5s675wLM90bd94ru987/
/AoHBILBqPyKRyyWw6n9CodEqtWq/YrHbL7Xq/4LB4TC6bz+i0es1uu9/wuHxOl
wTu+Lx+z+8H6jZ+goOEg4AnhYmKi3yHHIyQkZGOE5KWl5CUCpicnYx1nqGihHCj
pqd+a6irrHlnrbCwY7G0sl+1uKxeubyoXL3AplnBxMJWxciex8nMmFXN0JJU0dS
ZUtXYiVPZ3ILb3eB63+Hk4+Tg5ufc6erY0+3Zz/Du8vPQV/bRw/nFv/zAu/7lAi
Ow1qyCq14hFKVqobM3Dj/RiUhKE0U8miIUzIihNh3HEPo+toglsqTJkyhTqlzJs
qXLlzBjypxJs6bNmzhz6tzJs6fPn0CDCh1KtKjRo0iTKlWZAAA7
'''
root = tk.Tk()
image = tk.PhotoImage(data=image_data)
label = tk.Button(root, image=image, text="Hello, world", compound="center")
label.pack(padx=20, pady=20)
root.mainloop()

How to draw a coordinate system on top of an image using tkinter?

I want to show an image and draw a coordinate system(x-axe, y-axe) on top of it.
I can show the image
img = ImageTk.PhotoImage(Image.open(path).resize((400,400),Image.ANTIALIAS))
panel = tk.Label(root,image = img, width = 400, height = 400s)
panel.pack(size= "bottom", fill = "both", expand = "yes")
panel.place(rely = 073, rely = 0.5s)
I can also draw a line for the x-axe/y-axe(it would be even better if you know a way to draw a flash instead of a line)
canvas = Canvas(root)
canvas.create_line(x0,y0,x1,y1)
canvas.pack()
What I cannot do is place this line on top of the image. I tried using canvas.place(), but when I put it on top of the image I cannot see the image anymore. Is there a way to make the canvas transparent ? Or is there something else I can do ? I'm new to Tkinter.
Thanks.
EDIT: apparently it is not possible to make a canvas transparent Transparent canvas in tkinter python
But can I add a background image in the canvas and then draw the line, so that I can see both ?
You have to place the image on the canvas and then put the axis lines on top of it:
import Tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
img_path = 'water-drop-splash.png'
img = ImageTk.PhotoImage(Image.open(img_path).resize((400,400), Image.ANTIALIAS))
canvas = tk.Canvas(root, height=400, width=400)
canvas.create_image(200, 200, image=img)
canvas.create_line(0, 200, 399, 200, dash=(2,2)) # x-axis
canvas.create_line(200, 0, 200, 399, dash=(2,2)) # y-axis
canvas.pack()
root.mainloop()
Ta-da!

Categories