Click to open a new canvas panel with an image- tkinter - python

Hi I want to click on a picture in the canvas in order to open a new canvas in which there is another picture and for some reason the new canvas opens and the picture does not appear anyone might know how to fix this?
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
root.title("root")
root.geometry('800x550')
canvas = Canvas(root,
bg='white',
bd=5,
relief='groove',
height=500,
width=700,
)
canvas.place(x=80, y=0)
def press_to_open(event):
x, y = event.x, event.y
print('{}, {}'.format(x, y))
new_img = Image.open("images/back_p.png")
w, h = new_img.size
if x >= 3 and x <= 3 + w and y >= 3 and y <= 3 + h:
canvas2 = Canvas(canvas,
bg='white',
bd=2,
relief='groove',
height=120,
width=250,
)
canvas2.place(x=100, y=90)
resize_text = Label(canvas2, text="Resize the image:", bg="white", font=('Bodoni MT',
12))
resize_text.place(x=65, y=10)
img = PhotoImage("images/x.png")
x_button = Button(canvas2, command=canvas2.destroy, bd=0, image=img)
x_button.pack()
canvas2.create_window(10, 10, window=x_button, height=65, width=65)
def destroy_window(event):
global new_label
new_label.destroy()
color_img = ImageTk.PhotoImage(Image.open("images/back_p.png"))
label = Label(canvas, image=color_img)
label.place(x=10, y=10)
root.bind('<Button-1>', press_to_open)
root.bind('<Button-3>', destroy_window)
root.mainloop()

Related

Problem in displaying three tabs control X, Y, Z. I only display two tabs and not three

Functional and executable code of a tabcontrol that has other tabcontrols inside. Inside Tab 1 I have Tabs X, Y, Z. I only see tabs X and Z, but I don't see the Y.
Initially there were tabs X and Y correctly, then I added tab Z but I encountered the problem.
How can I correctly display the X, Y, Z tabs (including their content with the scrollbar)?
What am I doing wrong? I'm sure the problem is very simple, but I can't find it. Can you show me the full code please? Thank you
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title("Tab Widget")
root.attributes('-zoomed', True)
tabControl = ttk.Notebook(root, style='Custom.TNotebook', width=400, height=220)
#I create Tab1 and Tab2
tab1 = ttk.Notebook(tabControl)
tab2 = ttk.Notebook(tabControl)
tabControl.add(tab1, text ='Tab 1')
tabControl.add(tab2, text ='Tab 2')
tabControl.place(x=1, y=1)
#TAB X
x = ttk.Frame(tab1)
canvas = tk.Canvas(x)
### X CONTENT'S ###
#Scrollbar of X
scrollbar = ttk.Scrollbar(x, orient="vertical", command=canvas.yview)
scrollable_frame = ttk.Frame(canvas, width = 500, height = 500)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
#X Element's
combo1=ttk.Combobox(scrollable_frame, width = 18)
combo1.place(x=20, y=20)
combo1['value'] = ["text1", "text2"]
combo2=ttk.Combobox(scrollable_frame, width = 18)
combo2.place(x=20, y=80)
combo2['value'] = ["text1", "text2"]
combo3=ttk.Combobox(scrollable_frame, width = 18)
combo3.place(x=20, y=140)
combo3['value'] = ["text1", "text2"]
combo4=ttk.Combobox(scrollable_frame, width = 18)
combo4.place(x=20, y=200)
combo4['value'] = ["text1", "text2"]
x.pack()
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
tab1.add(x, text="X")
###################################################
#TAB Y
y = ttk.Frame(tab1)
tab1.add(y, text="Y")
### Y CONTENT'S ###
y_content = ttk.Frame(y)
canvas = tk.Canvas(y_content)
#Scrollbar of Y
scrollbar = ttk.Scrollbar(y_content, orient="vertical", command=canvas.yview)
scrollable_frame = ttk.Frame(canvas, width = 500, height = 500)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
#Y Element's
combo1=ttk.Combobox(scrollable_frame, width = 18)
combo1.place(x=20, y=20)
combo1['value'] = ["text1", "text2"]
combo2=ttk.Combobox(scrollable_frame, width = 18)
combo2.place(x=20, y=80)
combo2['value'] = ["text1", "text2"]
combo3=ttk.Combobox(scrollable_frame, width = 18)
combo3.place(x=20, y=140)
combo3['value'] = ["text1", "text2"]
combo4=ttk.Combobox(scrollable_frame, width = 18)
combo4.place(x=20, y=200)
combo4['value'] = ["text1", "text2"]
y_content.pack()
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
###################################################
#TAB Z
z = ttk.Frame(tab1)
tab1.add(y, text="Z")
### Z CONTENT'S ###
z_content = ttk.Frame(z)
canvas = tk.Canvas(z_content)
#Scrollbar of Z
scrollbar = ttk.Scrollbar(z_content, orient="vertical", command=canvas.yview)
scrollable_frame = ttk.Frame(canvas, width = 500, height = 500)
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
#Z Element's
combo1=ttk.Combobox(scrollable_frame, width = 18)
combo1.place(x=20, y=20)
combo1['value'] = ["text1", "text2"]
combo2=ttk.Combobox(scrollable_frame, width = 18)
combo2.place(x=20, y=80)
combo2['value'] = ["text1", "text2"]
combo3=ttk.Combobox(scrollable_frame, width = 18)
combo3.place(x=20, y=140)
combo3['value'] = ["text1", "text2"]
combo4=ttk.Combobox(scrollable_frame, width = 18)
combo4.place(x=20, y=200)
combo4['value'] = ["text1", "text2"]
z_content.pack()
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
###################################################
root.mainloop()
You have a typo! You wanted to add the y Frame instead of z.
#TAB Z
z = ttk.Frame(tab1)
tab1.add(z, text="Z") # Here you should add "z" variable instead of "y"
I recommend to add something style configuration for TAB size because the sub-tabs are not visible very well.
For example for type configuration (Put these lines after imports):
style = ttk.Style()
style.theme_settings("default", {"TNotebook.Tab": {"configure": {"padding": [20, 5]}}})
GUI:

Python Tkinter frame newby geometry problem?

I am very new in tkinter and python. Thats how my code looks:
import tkinter as tk
main = tk.Tk()
# Window size
main.geometry("400x700")
main.resizable(0, 0)
# Window position
w = main.winfo_reqwidth()
h = main.winfo_reqheight()
ws = main.winfo_screenwidth()
hs = main.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
main.geometry('+%d+%d' % (x, y))
fr1 = tk.Frame(main, borderwidth=2, relief="solid", bg = "#271ee3", width=400, height=50)
fr2 = tk.Frame(main, borderwidth=2, relief="solid", bg = "#0d9467", width=200, height=650)
fr3 = tk.Frame(main, borderwidth=2, relief="solid", bg = "#3e1854", width=200, height=650)
fr1.pack()
fr2.pack(side="left")
fr3.pack(side="right")
main.mainloop()
With this code I get the
following window
So far so good. The problem comes when i add this code:
# Label
l = tk.Label(fr2, text="Heyho")
l.grid(row=0, column=0)
Now it looks so
My goal is to get a window where i have in the first frame (fr1) a button that has the same geometry like fr1. In fr2 und fr3 I want to have severel labels among each other. My labels in fr2 und fr3 should have column 0 but ascending rows (0,1,2,3...). How can I do it??
It automatically resize Frame to Label's size so you don't see green background which is hidden behind label - and you see main window's gray background.
You can see it better if you add other longer label and red background in main window
If you add
fr2.grid_propagate(False)
then frame will keep its size
but you still have problem with grid which doesn't use full size of Frame and you can't center it or align to right.
If you add
fr2.grid_columnconfigure(0, weight=1)
then column 0 will try to use full size if there is no other columns, and label will be centered in cell
If you use
sticky='we'
in grid() for labels then they will fill cell
import tkinter as tk
main = tk.Tk()
# Window size
main.geometry("400x200")
main.resizable(0, 0)
main['bg'] = 'red'
# Window position
w = main.winfo_reqwidth()
h = main.winfo_reqheight()
ws = main.winfo_screenwidth()
hs = main.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
main.geometry('+%d+%d' % (x, y))
fr1 = tk.Frame(main, borderwidth=2, relief="solid", bg = "#271ee3", width=400, height=50)
fr2 = tk.Frame(main, borderwidth=2, relief="solid", bg = "#0d9467", width=200, height=650)
fr3 = tk.Frame(main, borderwidth=2, relief="solid", bg = "#3e1854", width=200, height=650)
fr1.pack()
fr2.pack(side="left")
fr3.pack(side="right")
fr2.grid_propagate(False)
fr2.grid_columnconfigure(0, weight=1)
l1 = tk.Label(fr2, text="Heyho")
l1.grid(row=0, column=0, sticky='we')
l2 = tk.Label(fr2, text="Hello World")
l2.grid(row=1, column=0, sticky='we')
main.mainloop()

Why is my code printing ".!canvas.!entry"?

I don't understand what is going on. I have defined 2 functions. 1 function displays text, entry boxes, and a submit button. I have it so that when the submit button is pressed, it prints the information the user put inside of the entry boxes. I've shortened my code for easier readability.
from tkinter import *
from PIL import Image, ImageTk
canvas_width = 360
canvas_height = 525
file = r"C:\Users\kraak\Desktop\PyCharm Community Edition 2017.1.2\borderedpaper.GIF"
master = Tk()
canvas = Canvas(master, width=canvas_width, height=canvas_height)
old_img = PhotoImage(file=file)
new_img = old_img.subsample(3, 3)
canvas.create_image(-11, -10, anchor=NW, image=new_img)
canvas.create_window(0, 0, height=1, width=1, anchor=NW)
canvas.create_text(0, 0, text="Test")
e1 = Entry(canvas)
def callback():
print(e1)
def answer():
e1 = Entry(canvas)
canvas.create_window(250, 100, window=e1, height=15, width=100)
label = Label(text="Enter a word.")
label.place(x=40, y=90)
e2 = Entry(canvas)
canvas.create_window(250, 125, window=e2, height=15, width=100)
label = Label(text="Enter a word.")
label.place(x=40, y=115)
button = Button(text="Submit.", command=callback)
button.place(x=150, y=460)
answer()
canvas.pack()
mainloop()

Layout changes using Tkinter

I am trying to make a full screen app for my Raspberry Pi. I got the code working to a degree. All I want to do now is split the top red section into 3 parts which I can put labels in containing data that will frequently change.
#!/usr/bin/python
from tkinter import *
from tkinter import ttk
root = Tk()
root.title("Learning Number Bonds!")
test = StringVar(value="XX + XX = XXX")
score = StringVar(value="0")
question = StringVar(value="7/10")
time = StringVar(value="8s")
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
topFrame = Frame(root, bg="red", width=w, height=h/4)
##Label(topFrame, text="test").grid(row=1, column=1)
topFrame.pack()
bottomFrame = Frame(root, bg="blue", width=w, height= h-(h/4))
bottomFrame.pack()
equation = Label(bottomFrame, textvariable=test, font=("Arial", 70))
equation.pack(fill=X)
root.mainloop()
This is what I have, and the bottom how I want
But when I add the commented line it looks like this:
[It all breaks - Removed]
How can I get 3 equal size boxes at the top with labels in them?!
EDIT:
I must have just been too tired and stupid to think about this and got caught up in the fact the boxes "HAD" to be the same size. After a few minutes of code changes from the original above, I ended up with:
#!/usr/bin/python
from tkinter import *
from tkinter import ttk
root = Tk()
root.title("Learning Number Bonds!")
test = StringVar(value="XX + XX = XXX")
score = StringVar(value=999)
question = StringVar(value="10/10")
time = StringVar(value="10")
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
topFrame = Frame(root, bg="red", width=w, height=h/4)
##Score
scoreTextLabel = Label(topFrame, text="Score: ", font=("Arial", 30))
scoreTextLabel.pack(side=LEFT)
Label2 = Label(topFrame, textvariable=score, font=("Arial", 30))
Label2.pack(side=LEFT, padx=(0,50))
##Question
qTextLabel = Label(topFrame, text="Question: ", font=("Arial", 30))
qTextLabel.pack(side=LEFT)
TextLabel2 = Label(topFrame, textvariable=question, font=("Arial", 30))
TextLabel2.pack(side=LEFT, padx=(0,50))
##Time
tTextLabel = Label(topFrame, text="Time: ", font=("Arial", 30))
tTextLabel.pack(side=LEFT)
TextLabel3 = Label(topFrame, textvariable=time, font=("Arial", 30))
TextLabel3.pack(side=LEFT, padx=(0,50))
topFrame.pack(pady=(0,120))
bottomFrame = Frame(root, bg="blue", width=w, height= h-(h/4))
bottomFrame.pack()
equation = Label(bottomFrame, textvariable=test, font=("Arial", 70))
equation.pack(fill=X)
root.mainloop()
Which looks like this
Thanks for all the help!
This shows how to configure the top row so it shows, and uses sticky to stretch the frame so it occupies the entire space, and uses a set width for the Label as well. You might also want to increase the font size of the label if you want the type to be larger.
root = Tk()
root.title("Learning Number Bonds!")
test = StringVar(value="XX + XX = XXX")
score = StringVar(value="0")
question = StringVar(value="7/10")
time = StringVar(value="8s")
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
topFrame = Frame(root, bg="red", width=w, height=h/4)
## put an empty row on top
topFrame.rowconfigure(0, weight=1, minsize=100)
Label(topFrame, text="test", bg="lightblue", width=50).grid(row=1, column=1)
topFrame.grid(sticky="nsew")
bottomFrame = Frame(root, bg="blue", width=w, height= h-(h/4))
bottomFrame.grid(row=1)
equation = Label(bottomFrame, textvariable=test, font=("Arial", 70))
equation.pack(fill=X)
root.mainloop()

Centering window python tkinter

Ive recently started using tkinter in python, and I was having trouble centering the window. I tried all the tips on this website, but whenever I try them, the window is like a line in the middle of the screen. I have widgets already on it, and it works fine without the centering, but I would really appreciate it if someone could help me solve my problem.
This is what I have been trying so far.
root = Tk()
root.title("Password")
root.resizable(FALSE,FALSE)
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
w = mainframe.winfo_width()
h = mainframe.winfo_height()
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
You need to use winfo_reqwidth() and winfo_reqheight(), because the window does not have a height or width at the time that you call winfo_height() and winfo_width().
An example program:
from tkinter import Tk
from tkinter import ttk
root = Tk()
style = ttk.Style()
style.configure("BW.TLabel", foreground="black", background="white")
l1 = ttk.Label(text="This is the best label in the world", style="BW.TLabel")
l1.pack()
w = l1.winfo_reqwidth()
h = l1.winfo_reqheight()
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
print(w, h, x, y)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
root.mainloop()
Ok I have found and fixed the problem. Piggybacking off of OregonTrail's solution, i found that if the window is the right size and you just want to change the location, then you can easily instead of setting the root's size, you can just move the window to the center.
w = root.winfo_reqwidth()
h = root.winfo_reqheight()
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('+%d+%d' % (x, y)) ## this part allows you to only change the location
I think that this answer isn't exactly in the center, probably off by a little since h was returning 200 when it should be less, but it looks to be at the center and works fine.
Hopefully someone will find use of this code, basically this is a solution you can use to center a TopLevel window relative to master (parent) window.
Probably not the cleanest solution, but it will get the work done.
from Tkinter import *
class PasswordDialog(Toplevel):
def __init__(self, master=None):
Toplevel.__init__(self, master)
self.master = master
self.title("Password")
self.label_info = Label(self, text="You need to enter your password", pady=10)
self.label_info.grid(row=0, column=0, columnspan=2, padx=20, pady=10, sticky="ew")
self.label_pw = Label(self, text="Enter password:", pady=10)
self.label_pw.grid(row=1, column=0, padx=(20, 2), sticky="e")
self.entry = Entry(self, show="*")
self.entry.bind("<KeyRelease-Return>", self.store_pass_event)
self.entry.grid(row=1, column=1, padx=(2,20), sticky="w")
self.button = Button(self, command=self.store_pass, text="Log in")
self.button.grid(row=2, column=0, columnspan=2, pady=10)
self.update()
size = tuple(int(_) for _ in self.geometry().split('+')[0].split('x'))
parent_offset = tuple(int(_) for _ in self.master.geometry().split('x')[1].split('+'))
parent_width = self.master.winfo_width()
parent_height = self.master.winfo_height()
x = parent_width//2 - size[0]//2 + parent_offset[1]
y = parent_height//2 - size[1]//2 + parent_offset[2]
self.geometry("+%d+%d" % (x, y))
def store_pass_event(self, event):
self.store_pass()
def store_pass(self):
self.master.password = self.entry.get()
self.destroy()

Categories