tkinter: how to not display the empty root window when creating it - python

I have a simple script that creates a window:
import Tkinter as tk
def center(win):
win.update_idletasks()
width = win.winfo_width()
frm_width = win.winfo_rootx() - win.winfo_x()
win_width = width + 2 * frm_width
height = win.winfo_height()
titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = height + titlebar_height + frm_width
x = win.winfo_screenwidth() // 2 - win_width // 2
y = win.winfo_screenheight() // 2 - win_height // 2
win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
def showDialog():
print "tkinter"
root = tk.Tk()
root.title("Say Hello")
label = tk.Label(root, text="Hello World")
label.pack(side="top", fill="both", expand=True, padx=20, pady=20)
button = tk.Button(root, text="OK", command=lambda: root.destroy())
button.pack(side="bottom", fill="none", expand=True, padx=10, pady=10)
center(root)
root.attributes("-topmost", True)
root.mainloop()
showDialog()
When running this script, a first empty window is displayed on the top left part of the screen and then the complete window is displayed centered in the screen.
I would like to not see this first empty window (it appears only for few milliseconds, but this is not nice)
How can I do that ?

Use the following two methods to hide or show the root window.
def hide(root):
root.withdraw()
def show(root):
root.update()
root.deiconify()
When you center the root window its size is (1, 1), you should give window size to center method.
lambda is not needed here, use command=root.destroy.
import Tkinter as tk
def center(win, width, height):
win.update_idletasks()
frm_width = win.winfo_rootx() - win.winfo_x()
win_width = width + 2 * frm_width
titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = height + titlebar_height + frm_width
x = win.winfo_screenwidth() // 2 - win_width // 2
y = win.winfo_screenheight() // 2 - win_height // 2
win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
def show(root):
root.update()
root.deiconify()
def hide(root):
root.withdraw()
def showDialog():
print "tkinter"
root = tk.Tk()
hide(root)
root.title("Say Hello")
label = tk.Label(root, text="Hello World")
label.pack(side="top", fill="both", expand=True, padx=20, pady=20)
button = tk.Button(root, text="OK", command=root.destroy)
button.pack(side="bottom", fill="none", expand=True, padx=10, pady=10)
center(root, width=200, height=200)
show(root)
root.mainloop()
showDialog()

Related

How can you make Python Tkinter Label text resize automatically along with the root window?

I am trying to make a tkinter label that stays in the middle of the root window and resizes along with it.
Is there any simple way to do that with using just .place() - and not using .grid() ?
Here is my code:
from tkinter import *
root= Tk()
root.geometry('200x200')
my_label= Label(root, text= 'Hello World!', font= ('Calibri', 20))
my_label.place(relx= 0.5, rely= 0.5, anchor= CENTER)
root.mainloop()
You can track the window size change and proportionally change the font size on the label.
from tkinter import *
i = 12
def config(event):
global i
i = 12
w = root.winfo_width()
h = root.winfo_height()
k = min(w, h) / 200
i = int(i + i*k)
my_label['font'] = ('Calibri', i)
root= Tk()
root.geometry('200x200')
root.bind("<Configure>", config)
my_label= Label(root, text= 'Hello World!', font= ('Calibri', i))
my_label.place(relx= 0.5, rely= 0.5, anchor= CENTER)
root.mainloop()

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

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

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

How to link two windows in tkinter python3 with/without Object Oriented approach?

I am learning basics of tinker in python 3.x using PyCharm as an IDE.I am building a basic two window program where 'Customer choice' window should be called after clicking CustomerButton in Welcome Window.
Welcome window has two buttons- customer and staff.
customer choice window has two buttons- order and cancel order.
For some reason, a blank 'Customer choice' window appears instead of the intended one.
from tkinter import *
print("aa")
def customerwindow():
root1 = Tk()
root1.title("Customer Choice")
window_width = 1000
window_height = 600
screen_height = root1.winfo_screenheight()
screen_width = root1.winfo_screenwidth()
x_coordinate = (screen_width / 2) - (window_width / 2)
y_coordinate = (screen_height / 2) - (window_height / 2)
root1.geometry('%dx%d+%d+%d' % (window_width, window_height, x_coordinate, y_coordinate))
frame1 = Frame(root1, height=1000, width=600)
frame1.pack(fill=BOTH)
Order = PhotoImage(file="fast-food.png")
Cancel = PhotoImage(file="delete.png")
OrderButton = Button(frame1, image=Order)
OrderButton.place(x=152, y=125)
CancelButton = Button(frame1, image=Cancel)
CancelButton.place(x=550, y=125)
OrderLabel = Label(frame1, text=" ORDER", font=("Poiret One", 24), fg='#34495E')
CancelLabel = Label(frame1, text=" CANCEL ORDER", font=("Poiret One", 24), fg='#34495E')
OrderLabel.place(x=152, y=405)
CancelLabel.place(x=550, y=405)
mainloop()
print("bb")
def welcomeWindow():
root = Tk()
root.title("Welcome")
window_width = 1000
window_height = 600
screen_height = root.winfo_screenheight()
screen_width = root.winfo_screenwidth()
x_coordinate = (screen_width/2) - (window_width/2)
y_coordinate = (screen_height/2) - (window_height/2)
root.geometry('%dx%d+%d+%d' % (window_width, window_height, x_coordinate, y_coordinate))
frame1 = Frame(root, height=1000, width=600)
frame1.pack(fill=BOTH)
customerPhoto = PhotoImage(file="boy.png")
staffPhoto = PhotoImage(file="boss.png")
customerButton = Button(frame1, image=customerPhoto, command=customerwindow)
customerButton.place(x=152, y=125)
staffButton = Button(frame1, image=staffPhoto)
staffButton.place(x=550, y=125)
customerLabel = Label(frame1, text=" CUSTOMER", font=("Poiret One", 24), fg='#34495E')
staffLabel = Label(frame1, text=" STAFF", font=("Poiret One", 24), fg='#34495E')
customerLabel.place(x=152, y=405)
staffLabel.place(x=550, y=405)
mainloop()
welcomeWindow()
print("SS")
#aa,bb,ss are just to check the interpreters progress.
Pass "root" to the customerwindow function and use a Toplevel instead of a 2nd Tk() instance which can cause problems. Don't expect much help in the future when you post code that can't be run, i.e. uses images, etc.
import sys
if 3 == sys.version_info[0]: ## 3.X is default if dual system
import tkinter as tk ## Python 3.x
else:
import Tkinter as tk ## Python 2.x
from functools import partial
print("aa")
def customerwindow(root):
root1 = tk.Toplevel(root)
root1.title("Customer Choice")
window_width = 1000
window_height = 600
screen_height = root1.winfo_screenheight()
screen_width = root1.winfo_screenwidth()
x_coordinate = (screen_width / 2) - (window_width / 2)
y_coordinate = (screen_height / 2) - (window_height / 2)
root1.geometry('%dx%d+%d+%d' % (window_width, window_height, x_coordinate, y_coordinate))
frame1 = tk.Frame(root1, height=1000, width=600, bg="lightblue")
frame1.pack(fill=tk.BOTH)
## Order = PhotoImage(file="fast-food.png")
## Cancel = PhotoImage(file="delete.png")
"""---- these buttons don't do anything
OrderButton = Button(frame1, text="Order")
OrderButton.place(x=152, y=125)
"""
CancelButton = tk.Button(frame1, text="Cancel", command=root1.destroy)
CancelButton.place(x=550, y=125)
OrderLabel = tk.Label(frame1, text=" ORDER", font=("Poiret One", 24), fg='#34495E')
CancelLabel = tk.Label(frame1, text=" CANCEL ORDER", font=("Poiret One", 24), fg='#34495E')
OrderLabel.place(x=152, y=405)
CancelLabel.place(x=550, y=405)
## mainloop()
print("bb")
def welcomeWindow():
root = tk.Tk()
root.title("Welcome")
window_width = 1000
window_height = 600
screen_height = root.winfo_screenheight()
screen_width = root.winfo_screenwidth()
x_coordinate = (screen_width/2) - (window_width/2)
y_coordinate = (screen_height/2) - (window_height/2)
root.geometry('%dx%d+%d+%d' % (window_width, window_height, x_coordinate, y_coordinate))
frame1 = tk.Frame(root, height=1000, width=600)
frame1.pack(fill=tk.BOTH)
## customerPhoto = PhotoImage(file="boy.png")
## staffPhoto = PhotoImage(file="boss.png")
customerButton = tk.Button(frame1, text="customerPhoto", command=partial(customerwindow, root))
customerButton.place(x=152, y=125)
## this button doesn't do anything
##staffButton = tk.Button(frame1, text="staffPhoto")
##staffButton.place(x=550, y=125)
customerLabel = tk.Label(frame1, text=" CUSTOMER", font=("Poiret One", 24), fg='#34495E')
staffLabel = tk.Label(frame1, text=" STAFF", font=("Poiret One", 24), fg='#34495E')
customerLabel.place(x=152, y=405)
staffLabel.place(x=550, y=405)
root.mainloop()
welcomeWindow()
print("SS")

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