Canvas background image doesnt fit the entire window tkinter python - python

I'm new with tkinter GUI and trying to make a background to a top-level window by using canvas. I have tried to make the canvas the same size as the entire window by expand=TRUE.
However, it doesn't work well and the image is not sized as the window. can anyone help me fix that problem?
The top-level window is overviewWindow, which is in the function createOverviewWindow.
This is my code:
There is no output image because unfortunately I cant add images. The window I got has the background image in the top left corner but small sized
from tkinter import *
from tkinter import ttk, font, messagebox
from PIL import ImageTk, Image
import os
root = Tk()
root.title("Decoder of ultrasound images to detect colon tumors")
# Adding window icon
root.iconbitmap('afekaImage.ico')
rootWidth, rootHeight = 600, 600
screenWidth = root.winfo_screenwidth()
screenHeight = root.winfo_screenheight()
topLeftPosition = (screenWidth / 2 - rootWidth / 2, screenHeight / 2 - rootHeight / 2)
# Configure window size
root.geometry(f'{rootWidth}x{rootHeight}+{int(topLeftPosition[0])}+{int(topLeftPosition[1])}')
# open doc file
def openDocFile():
os.startfile("FinalProject.docx")
# adjusting background image to fit window
def adjustBackgroundImage(event):
label = event.widget
# avoid garbage collection option 1
# global resizedBackgroundImage, newBackgroundImage
# ----------
width = event.width
height = event.height
resizedBackgroundImage = copyImage.resize((width, height))
newBackgroundImage = ImageTk.PhotoImage(resizedBackgroundImage)
label.config(image=newBackgroundImage)
# avoid garbage collection option 2
label.image = newBackgroundImage
# ----------
def createUserManualWindow(button_userManual):
# global image1
userManualWindow = Toplevel(root)
userManualWindow.geometry(f'{rootWidth}x{rootHeight}+{int(topLeftPosition[0])}+{int(topLeftPosition[1])}')
userManualWindow.iconbitmap('afekaImage.ico')
image1 = ImageTk.PhotoImage(Image.open('background.jpg'))
label1 = ttk.Label(userManualWindow, image=image1)
label1.pack()
label1.bind('<Configure>', adjustBackgroundImage)
label1.pack(fill=BOTH, expand=YES)
def activateButtonUserManual():
button_userManual.configure(state="normal")
userManualWindow.destroy()
button_userManual.configure(state="disabled")
button_exit_userManualWindow = Button(userManualWindow, text="Exit", font=fontStyle,
command=lambda: [userManualWindow.destroy(), activateButtonUserManual()])
button_exit_userManualWindow.place(relx=0.4, rely=0.8, relwidth=0.2, relheight=0.1)
# will occurs only when esc pressed
userManualWindow.protocol("WM_DELETE_WINDOW", activateButtonUserManual)
# ----------
def createOverviewWindow(button_overview):
global image1, canvas
overviewWindow = Toplevel(root)
overviewWindow.geometry(f'{rootWidth}x{rootHeight}+{int(topLeftPosition[0])}+{int(topLeftPosition[1])}')
overviewWindow.iconbitmap('afekaImage.ico')
canvas = Canvas(overviewWindow, width=600, height=600)
canvas.pack(fill=BOTH, expand=TRUE)
image1 = ImageTk.PhotoImage(Image.open('background.jpg'))
canvas.create_image(0, 0, image=image1, anchor='nw')
image = Image.open('background.jpg')
copyImage = image.copy()
backgroundImage = ImageTk.PhotoImage(image)
label = ttk.Label(root, image=backgroundImage)
label.bind('<Configure>', adjustBackgroundImage)
label.pack(fill=BOTH, expand=YES)
fontStyle = font.Font(family="Segoe Script", size=10, weight=font.BOLD)
# Create buttons
button_userManual = Button(root, text="USER MANUAL", command=lambda: createUserManualWindow(button_userManual), font=fontStyle)
button_userManual.place(relx=0.4, rely=0.2, relwidth=0.2, relheight=0.1)
button_overview = Button(root, text="OVERVIEW", command=lambda: createOverviewWindow(button_overview), font=fontStyle)
button_overview.place(relx=0.4, rely=0.4, relwidth=0.2, relheight=0.1)
button_openDocFile = Button(root, text="DOC FILE", font=fontStyle, command=openDocFile)
button_openDocFile.place(relx=0.4, rely=0.6, relwidth=0.2, relheight=0.1)
button_quit = Button(root, text="Exit", font=fontStyle, command=root.destroy)
button_quit.place(relx=0.4, rely=0.8, relwidth=0.2, relheight=0.1)
root.mainloop()

The image you put was too big for the canvas. It's like putting a 8K image into a 720p monitor. It simply does not fit. So the solutions are
a) resize the image so it fits in the canvas (I see you have the PIL module so it should be quick)
b) Change the canvas size so it fits the image

Related

How do I adjust this frame with scrollbar inside the black space?

I want to fit this frame with scrollbar(refer the provided image) in the black space present in the provided image. How do I do that. The frame should totally cover the black space.
The code for program.The image
from tkinter import *
from tkinter import ttk
C = Tk()
C.maxsize(1200, 750)
C.geometry("1200x750")
C.title("Mainscreen")
style = ttk.Style()
style.theme_use('clam')
BG = PhotoImage(file="Mainscreen bg.png")
ML = PhotoImage(file="Music_label.png")
BG_label = Label(C, image=BG, border=0)
BG_label.place(x=0, y=0)
style.configure("Vertical.TScrollbar", gripcount=0,
background="Cyan", darkcolor="gray6", lightcolor="LightGreen",
troughcolor="Turquoise4", bordercolor="gray6", arrowcolor="gray6",arrowsize=15)
wrapper1= LabelFrame(C, width="1600", height="100", background="gray6",bd=0)
mycanvas = Canvas(wrapper1,background="gray6",borderwidth=0, highlightthickness=0, width=700, height=600)
mycanvas.pack(side=LEFT, expand="false", padx=0)
yscrollbar = ttk.Scrollbar(wrapper1, orient="vertical",command=mycanvas.yview)
yscrollbar.pack(side=RIGHT, fill="y")
mycanvas.configure(yscrollcommand=yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion=mycanvas.bbox("all")))
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window=myframe, anchor="n")
wrapper1.pack(side=RIGHT,expand="false", padx=0, pady=200)
for i in range(50):
Button(myframe, image=ML,bg="gray6",bd=0).pack()
mainloop()
EDIT:
Music_Label
Mainscreen bg
So after trying to understand the underlying problem for a while I have reached the conclusion, that the problem is with the fact that the button are being drawn in the myframe and the myframe is outside the mycanvas which contains the scrollbar. So by changing the master widget for the button from myframe to mycanvas, the problem gets fixed now the scrollbar is adjacent to the buttons. BUT, Also now the button r shifted the side since while packing the wrapper1, you did side = RIGHT, so I would also suggest that you use place here instead of pack, since pack depends on the space available and is not reliable if you are using a Background for your GUI and want the buttons within a portion of it.
I have changed the following lines -:
Button(mycanvas, image=ML,bg="gray6",bd=0).pack() # Changed to mycanvas from myframe
and
wrapper1.place(x = {YOUR X, WHERE THE BOX STARTS}, y = {YOUR Y, WHERE THE BOX STARTS}) # Use place instead..
You can use pack also, and change the padx and pady arguments but it will be tricky to get it to work always as expected.
The fixed code is this -:
from tkinter import *
from tkinter import ttk
C = Tk()
C.maxsize(1200, 750)
C.geometry("1200x750")
C.title("Mainscreen")
style = ttk.Style()
style.theme_use('clam')
BG = PhotoImage(file="Mainscreen bg.png")
ML = PhotoImage(file="Music_label.png")
BG_label = Label(C, image=BG, border=0)
BG_label.place(x=0, y=0)
style.configure("Vertical.TScrollbar", gripcount=0,
background="Cyan", darkcolor="gray6", lightcolor="LightGreen",
troughcolor="Turquoise4", bordercolor="gray6", arrowcolor="gray6",arrowsize=15)
wrapper1= LabelFrame(C, width="1600", height="100", background="gray6",bd=0)
mycanvas = Canvas(wrapper1,background="gray6",borderwidth=0, highlightthickness=0, width=700, height=600)
mycanvas.pack(side=LEFT, expand=False, padx=0)
yscrollbar = ttk.Scrollbar(wrapper1, orient="vertical",command=mycanvas.yview)
yscrollbar.pack(side=RIGHT, fill="y", expand = False)
mycanvas.configure(yscrollcommand=yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion=mycanvas.bbox("all")))
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window=myframe, anchor="n")
wrapper1.pack(expand=True, padx=0, pady=200) # Use place instead
for i in range(50):
Button(mycanvas, image=ML,bg="gray6",bd=0).pack() # Change this to mycanvas from myframe
mainloop()

Change background makes its labels disappear

I want to build an app where you can change the background image by clicking a button. First, to put a background to my frame, I created the image as a label and then sub-classed every other label to the background label. Now when you click the button "Change Background", it changes the background. However, all the labels disappear. Buttons only appear when you hover over them by the cursor. Labels never appear!
My questions are:
Why does this happen?
How to fix it?
Here is a simple code to reproduce the issue:
import tkinter as tk
from PIL import ImageTk, Image
class App():
def __init__(self, root):
self.root = root
self.controlFrame = tk.Frame(root, width=900, height=600)
self.controlFrame.pack_propagate(0) # Prevents resizing
self.controlFrame.pack()
img = Image.open('images/outside.jpg').resize((900, 600))
self.background_image = ImageTk.PhotoImage(img)
self.background_label = tk.Label(self.controlFrame, image=self.background_image)
self.background_label.configure(image = self.background_image)
self.background_label.pack(fill="both", expand="yes")
self.changeButton = tk.Button(self.background_label, text="Change Background",
command = self.changeBK)
self.changeButton.place(x=400, y=300)
self.someButton = tk.Button(self.background_label, text="Some Button")
self.someButton.place(x=400, y=100)
self.someOtherButton = tk.Button(self.background_label, text="Some Other Button")
self.someOtherButton.place(x=400, y=450)
self.userMessage = tk.Label(self.background_label, text="Label", height = 3 , width= 14, bg="white")
self.userMessage.place(x=400, y= 200)
def changeBK(self):
img = Image.open('images/muddyPath.jpg').resize((900, 600))
self.background_image = ImageTk.PhotoImage(img)
self.background_label.configure(image = self.background_image)
def main():
win = tk.Tk() # Create a window
win.title("Using Multiple Layouts") # Set window title
win.geometry("900x600") # Set window size
win.resizable(False, False) # Both x and y dimensions ...
# Create the GUI as a Frame
# and attach it to the window ...
myApp = App(win)
# Call the GUI mainloop ...
win.mainloop()
if __name__ == "__main__":
main()

How to call Turtle window from a GUI

I'm trying to open a Turtle window from a GUI to select a position on the image with a mouse click. The x and y coordinates are then returned as an input to the GUI.
Here is a minimal working example:
from tkinter import *
from tkinter import font as tkFont
import turtle
xclick = 0
yclick = 0
def callback3():
getcoordinates()
def getcoordinates():
screen = turtle.Screen()
screen.setup(400, 400)
screen.bgpic("stunden.gif")
screen.onscreenclick(modifyglobalvariables)
def modifyglobalvariables(rawx,rawy):
global xclick
global yclick
xclick = int(rawx//1)
yclick = int(rawy//1)
print(xclick)
print(yclick)
turtle.bye()
root = Tk()
helv30 = tkFont.Font(family='Helvetica', size=30)
button1 = Button(root, text = "1", width=3, font=helv30, borderwidth=0, command=callback3)
button1.grid(row=0, column=0, padx=5, pady=0)
root.mainloop()
Then the error image "pyimage2" doesn't exist shows up. I found out, that it has something to do with two instances of Tk, as there is the root and the turtle window and that I should solve it with Toplevel(). However, after hours of research and try and error I still could not come up with the right solution to make my code work. Any help is greatly appreciated.
Here's how to implement it directly in tkinter — so no turtle module required — as I suggested earlier in a (now-deleted) comment:
from tkinter import *
from tkinter import font as tkFont
CLOCK_IMAGE_PATH = 'clock.png'
xclick, yclick = 0, 0
def callback3():
window = Toplevel()
window.title("Stunden")
img = PhotoImage(file=CLOCK_IMAGE_PATH)
img_width, img_height = img.width(), img.height()
window.minsize(width=img_width, height=img_height)
canvas = Canvas(window, width=img_width, height=img_height)
canvas.pack()
canvas.image = img # Keep reference to avoid image being garbage collected.
canvas.create_image(0, 0, anchor='nw', image=img)
canvas.bind("<Button-1>", get_coordinates) # Set up event-handler callback.
def get_coordinates(event):
global xclick, yclick
xclick = int(event.x // 1)
yclick = int(event.y // 1)
print(f'xclick={xclick}, yclick={yclick}')
root = Tk()
helv30 = tkFont.Font(family='Helvetica', size=30)
button1 = Button(root, text="1", width=3, font=helv30, borderwidth=0, command=callback3)
button1.grid(row=0, column=0, padx=5, pady=0)
root.mainloop()

How to make the text of a variable bold in Tkinter?

I have a scenario where I would like to bold the text which is present inside a variable in Tkinter.
The code is as follows:
best_batsmen = dataset.loc[dataset.loc[dataset['Innings']>=15,'Average'].idxmax(),'Names']
message = ("The best Batsman of the Tournament could possibly be: " + best_batsmen)
canvas_width = 500
canvas_height = 500
root = Toplevel()
root.geometry("700x600")
root.title("Best Batsman")
canvas = Canvas(root, width=canvas_width, height=canvas_height)
canvas.create_text(1, 10, anchor=W, text=message)
img = ImageTk.PhotoImage(Image.open("virat.jpeg"))
canvas.create_image(0, 20, anchor=NW, image=img)
canvas.image = img
canvas.pack()
root.mainloop()
In the above code, I would like to bold only the text present inside the best_batsmen variable using Tkinter. Can anyone please help me in figuring that out.
You have to use second create_text to put only text best_batsman with font='bold'
canvas.create_text(1, 10, anchor='w', text=message)
canvas.create_text(380, 10, anchor='w', text=best_batsmen, font='bold')
but you have to manually calculate x position for best_batsmen (ie. 380)
import tkinter as tk
from PIL import Image, ImageTk
best_batsmen = "James Bond"
message = "The best Batsman of the Tournament could possibly be: "
canvas_width = 500
canvas_height = 500
root = tk.Tk()
canvas = tk.Canvas(root, width=canvas_width, height=canvas_height)
canvas.pack()
canvas.create_text(1, 10, anchor='w', text=message)
canvas.create_text(380, 10, anchor='w', text=best_batsmen, font='bold')
img = ImageTk.PhotoImage(Image.open("virat.jpeg"))
canvas.create_image(0, 20, anchor='nw', image=img)
#canvas.image = img
root.mainloop()
Eventually you can try to calculate position with tkinter.font.Font().measure()
import tkinter.font as tkfont
#width = tkfont.Font(family='arial', size=20, weight='normal').measure(message)
width = tkfont.Font().measure(message)
canvas.create_text(width, 10, anchor='w', text=best_batsmen, font='bold')
If you put text above image so you don't need text with transparent background then you can put Frame using pack() and put two Labels inside Frame using pack(side='left')
frame = tk.Frame(root)
frame.pack()
tk.Label(frame, text=message).pack(side='left')
tk.Label(frame, text=best_batsmen, font='bold').pack(side='left')
This way you don't have to calculate x position for best_batsmen
And you can put image in position (0, 0)
import tkinter as tk
from PIL import Image, ImageTk
best_batsmen = "James Bond"
message = "The best Batsman of the Tournament could possibly be: "
canvas_width = 500
canvas_height = 500
root = tk.Tk()
frame = tk.Frame(root)
tk.Label(frame, text=message).pack(side='left')
tk.Label(frame, text=best_batsmen, font='bold').pack(side='left')
frame.pack()
canvas = tk.Canvas(root, width=canvas_width, height=canvas_height)
canvas.pack()
img = ImageTk.PhotoImage(Image.open("virat.jpeg"))
canvas.create_image(0, 0, anchor='nw', image=img)
#canvas.image = img
root.mainloop()
Or you can use create_window(..., window=frame) to put it on canvas. You have to do it after you create Canvas.
frame = tk.Frame(root)
canvas.create_window(0, 0, window=frame, anchor='nw')
tk.Label(frame, text=message).pack(side='left')
tk.Label(frame, text=best_batsmen, font='bold').pack(side='left')
If you would like to put on image - not above - the you would have to use creat_window after create_image. But widgets (Frame, 'Label', etc.) can't have transparent background.
import tkinter as tk
from PIL import Image, ImageTk
import tkinter.font as tkfont
best_batsmen = "James Bond"
message = "The best Batsman of the Tournament could possibly be: "
canvas_width = 500
canvas_height = 500
root = tk.Tk()
canvas = tk.Canvas(root, width=canvas_width, height=canvas_height)
canvas.pack()
frame = tk.Frame(root)
canvas.create_window(1, 0, window=frame, anchor='nw')
tk.Label(frame, text=message).pack(side='left')
tk.Label(frame, text=best_batsmen, font='bold').pack(side='left')
img = ImageTk.PhotoImage(Image.open("virat.jpeg"))
canvas.create_image(0, 20, anchor='nw', image=img)
#canvas.image = img
root.mainloop()
Instead of Frame with Labels you could use Text with tags with assigned colors and weights.
You can create a text on the canvas and edit its font styles.
canvas.create_text(1, 10, font=('arial', 20, BOLD), text='your text here')
You would have to import the style from tkinter fonts for this.
from tkinter.font import BOLD
You can separate the message into 2 parts:
best_batsmen = 'Virat Kohli'
message = 'The best Batsman of the Tournament could possibly be: '
Then draw the first part as usual:
msg = canvas.create_text(1, 10, text=message, anchor=W)
Use the returned item ID msg to get the bounding box and font for the message:
bbox = canvas.bbox(msg) # get the message bounding box
# import tkinter.font as tkfont
font = tkfont.Font(font=canvas.itemcget(msg, 'font')) # get the message font
Then set the weight of the font to 'bold' and draw the second part at the end of the first part using bold style:
font['weight'] = 'bold' # change font weight to bold
# show best_batsmen at the end of the message with bold style
canvas.create_text(bbox[2], bbox[1], text=best_batsmen, font=font, anchor=NW)

Image in tkinter window by clicking on button

I need help about this program, this program should open image in new tkinter window by clicking on button, but it doesn't it just opens new window without image.
Where is the problem?
Using: python 3.3 and tkinter
This is program:
import sys
from tkinter import *
def button1():
novi = Toplevel()
canvas = Canvas(novi, width = 300, height = 200)
canvas.pack(expand = YES, fill = BOTH)
gif1 = PhotoImage(file = 'image.gif')
canvas.create_image(50, 10, visual = gif1, anchor = NW)
mGui = Tk()
button1 = Button(mGui,text ='Sklop',command = button1, height=5, width=20).pack()
mGui.mainloop()
create_image needs a image argument, not visual to use the image, so instead of visual = gif1, you need image = gif1. The next problem is that you need to store the gif1 reference somewhere or else it'll get garbage collected and tkinter won't be able to use it anymore.
So something like this:
import sys
from tkinter import * #or Tkinter if you're on Python2.7
def button1():
novi = Toplevel()
canvas = Canvas(novi, width = 300, height = 200)
canvas.pack(expand = YES, fill = BOTH)
gif1 = PhotoImage(file = 'image.gif')
#image not visual
canvas.create_image(50, 10, image = gif1, anchor = NW)
#assigned the gif1 to the canvas object
canvas.gif1 = gif1
mGui = Tk()
button1 = Button(mGui,text ='Sklop',command = button1, height=5, width=20).pack()
mGui.mainloop()
It's also probably not a good idea to name your Button the same name as the function button1, that'll just cause confusion later on.
from tkinter import *
root = Tk()
root.title("Creater window")
def Img():
r = Toplevel()
r.title("My image")
canvas = Canvas(r, height=600, width=600)
canvas.pack()
my_image = PhotoImage(file='C:\\Python34\\Lib\idlelib\\Icons\\Baba.gif', master= root)
canvas.create_image(0, 0, anchor=NW, image=my_image)
r.mainloop()
btn = Button(root, text = "Click Here to see creator Image", command = Img)
btn.grid(row = 0, column = 0)
root.mainloop()

Categories