I have an issues with window resizing in tkinter when a user variable is displayed. As the program takes in the name of a team and display's it later in the program, having a set size for the display window will not work as it needs to be adaptive. I have got code for centring the window, but is there a way to automatically set the size of the window?
Current Look:
team_2 = t2_entry.get()
top_2.withdraw()
confirm_screen = Toplevel(master)
w = 160 + len(team_2) + len(team_1)
h = 50
ws = confirm_screen.winfo_screenwidth()
hs = confirm_screen.winfo_screenheight()
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
confirm_screen.geometry('%dx%d+%d+%d' % (w, h, x, y))
t1_name = Label(confirm_screen, text = "Team 1: " + team_1).grid(row = 1, column = 1)
t2_name = Label(confirm_screen, text="Team 2: " + team_2).grid(row = 1, column = 2)
confirm_button = Button(confirm_screen, text = "Submit", width = 10, command = team_name_1).grid(row = 4, column = 1)
redo = Button(confirm_screen, text="Redo", width=10, command= lambda: [start_team1(), clear()]).grid(row=4, column=2)
Attempts 1:
team_2 = t2_entry.get()
top_2.withdraw()
confirm_screen = Toplevel(master)
w = 160 + len(team_2) + len(team_1)
h = 50
ws = confirm_screen.winfo_screenwidth()
hs = confirm_screen.winfo_screenheight()
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
confirm_screen.geometry('%dx%d+%d+%d' % (w, h, x, y))
t1_name = Label(confirm_screen, text = "Team 1: " + team_1).grid(row = 1, column = 1)
t2_name = Label(confirm_screen, text="Team 2: " + team_2).grid(row = 1, column = 2)
confirm_button = Button(confirm_screen, text = "Submit", width = 10, command = team_name_1).grid(row = 4, column = 1)
redo = Button(confirm_screen, text="Redo", width=10, command= lambda: [start_team1(), clear()]).grid(row=4, column=2)
Attempt 2:
team_2 = t2_entry.get()
top_2.withdraw()
confirm_screen = Toplevel(master)
w = confirm_screen.winfo_width
h = confirm_screen.winfo_height
ws = confirm_screen.winfo_screenwidth()
hs = confirm_screen.winfo_screenheight()
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
confirm_screen.geometry('%dx%d+%d+%d' % (w, h, x, y))
t1_name = Label(confirm_screen, text = "Team 1: " + team_1).grid(row = 1, column = 1)
t2_name = Label(confirm_screen, text="Team 2: " + team_2).grid(row = 1, column = 2)
confirm_button = Button(confirm_screen, text = "Submit", width = 10, command = team_name_1).grid(row = 4, column = 1)
redo = Button(confirm_screen, text="Redo", width=10, command= lambda: [start_team1(), clear()]).grid(row=4, column=2)
I think this is what you are after:
from tkinter import *
confirm_screen = Tk()
t1_name = Label(confirm_screen, text = "Team 1: " + "team_1").grid(row = 1, column = 1)
t2_name = Label(confirm_screen, text="Team 2: " + "team_2").grid(row = 1, column = 2)
confirm_button = Button(confirm_screen, text = "Submit", width = 10, command = None).grid(row = 4, column = 1)
redo = Button(confirm_screen, text="Redo", width=10, command= lambda: [start_team1(), clear()]).grid(row=4, column=2)
# You need to update the display so that the widgets are actually displayed on the screen.
# Otherwise `w` and `h` will both = 1
confirm_screen.update()
w = confirm_screen.winfo_width()
h = confirm_screen.winfo_height()
ws = confirm_screen.winfo_screenwidth()
hs = confirm_screen.winfo_screenheight()
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
confirm_screen.geometry('+%d+%d' % (x, y))
You have to first place all of the widgets and then calculate where the window should go. Also there is no need to always include the size of the window when using <tkinter.Tk>.geometry(...).
Related
Here's my current code and the changes I've made so far from the previous version
I've reset the variables at the start because I did not want them to be reset each time the function was executed
I've added a ess_e variable for the entry of the procedure, I want this variable to store the localtime when the function is executed
I've added a ess_s variable for the exit of the procedure after all the infos are entered which should be localtime when the submit button (changed text) is pushed
The remaining problems are
root.bind does not work, I've tried several alternatives with fenetre as you suggested but I could not make it work.
I get an error when I run the 2nd function (essenceresult)
File "D:\Bureautique\Python\Scripts\interface-test.py", line 57, in essenceResult
ess_e = ent0.get()
AttributeError: 'datetime.datetime' object has no attribute 'get'
I still have to make the frame to display the previous results but I'll get there in due time :)
Thanks a lot for the help
from tkinter import *
from datetime import *
import time
ess=[[],[],[],[],[]]
rel=[[],[],[],[],[]]
c60=[[],[]]
def c60duree(delta):
(h, r) = divmod(delta.seconds, 3600)
(m, s) = divmod(r, 60)
return "%s%02d:%02d:%02d" % (
"%d jour(s) " % delta.days if delta.days > 0 else "",
h,
m,
s,
)
def code60():
saisie=0
while saisie != "X":
c60d=datetime.now()
print ("Code 60 activé à ", c60d.strftime("%H:%M:%S"))
saisie=input("Tapez entree pour la fin du code 60, X pour sortir : ")
c60f=datetime.now()
print("Debut ", c60d.strftime("%H:%M:%S"))
print("Fin ", c60f.strftime("%H:%M:%S"))
c60x=c60f-c60d
print("Duree ", c60duree(c60x))
print("-------------")
c60[0].append(c60d)
c60[1].append(c60f)
#del(c60[0],[-1])
#del(c60[1],[-1])
#return
def relais():
print("Relais pilote demarré ")
relh=datetime.now()
relv=input("Quelle voiture ? ")
relp=input("Quel pilote repart ? ")
rele=input("Quantité d'essence ? ")
input("Tapez entrée à la sortie des stands ")
rels=datetime.now()
rel[0].append(relh), rel[1].append(relv), rel[2].append(relp), rel[3].append(rele), rel[4].append(rels)
print("Dureé ", rels-relh)
print(*rel)
#def essence():
#ess=[[],[],[],[]]
#print("Ravitaillement essence demarré ")
#essh=datetime.now()
#essv=input("Quelle voiture ? ")
#essp=input("Quel pilote ? ")
#essq=input("Combien de litres ? ")
#ess[0].append(essh), ess[1].append(essv), ess[2].append(essp), ess[3].append(essq)
#print(*ess)
def essenceResult(ess, ent0, ent1, ent2, ent3):
ess_e = ent0.get()
essv = ent1.get()
essp = ent2.get()
essq = ent3.get()
ess_s = datetime.now()
ess[0].append(ess_e), ess[1].append(essv), ess[2].append(essp), ess[3].append(essq), ess [4].append(ess_s)
resultLabel = Label(Frame4, text = str(*ess))
resultLabel.grid(row = 5, column = 0, columnspan = 2)
def essence():
print("yr")
ess_e=datetime.now()
Frame4.grid(row = 1, column = 0)
Label1 = Label(Frame4, text = "Ravitaillement demarré ")
Label1.grid(row = 0, column = 0, columnspan = 2)
essvLabel = Label(Frame4, text = "Quelle voiture ? ")
essvEntry = Entry(Frame4)
essvLabel.grid(row = 1, column = 0)
essvEntry.grid(row = 1, column = 1)
essvEntry.focus()
#root.bind_all("<Return>", function)
esspLabel = Label(Frame4, text = "Quel pilote part ? ")
esspEntry = Entry(Frame4)
esspLabel.grid(row = 2, column = 0)
esspEntry.grid(row = 2, column = 1)
esspEntry.focus()
essqLabel = Label(Frame4, text = "Combien de litres ? ")
essqEntry = Entry(Frame4)
essqLabel.grid(row = 3, column = 0)
essqEntry.grid(row = 3, column = 1)
essqEntry.focus()
submitButton = Button(Frame4, text = "Sortie des stands", command = lambda: essenceResult(ess, ess_e, essvEntry, esspEntry, essqEntry))
submitButton.grid(row = 4, column = 0, columnspan = 2)
fenetre = Tk()
fenetre['bg']='grey'
# frame 1
Frame1 = Frame(fenetre, bg="green", borderwidth=1, relief=GROOVE)
Frame1.grid(row = 0, column = 0, padx=5, pady=5)
# frame 2
Frame2 = Frame(fenetre, bg="yellow", borderwidth=1, relief=GROOVE)
Frame2.grid(row = 0, column = 1, padx=5, pady=5)
# frame 3
Frame3 = Frame(fenetre, bg="purple", borderwidth=1, relief=GROOVE)
Frame3.grid(row = 0, column = 2, padx=5, pady=5)
Frame4 = Frame(fenetre)
Fenetre = Tk()
fenetre['bg']='grey'
# Ajout de labels
Button(Frame1, text="Essence", command=essence).pack(padx=300, pady=100)
Button(Frame2, text="Relais", command=relais).pack(padx=300, pady=100)
Button(Frame3, text="Code 60", command=code60).pack(padx=300, pady=100)
Here's the fixed code:
def essenceResult(ess, ess_e, ent1, ent2, ent3):
essv = ent1.get()
essp = ent2.get()
essq = ent3.get()
ess_s = datetime.now()
ess[0].append(ess_e), ess[1].append(essv), ess[2].append(essp), ess[3].append(essq), ess[4].append(ess_s)
resultLabel = Label(Frame4, text = str(ess))
resultLabel.grid(row = 5, column = 0, columnspan = 2)
def essence():
print("yr")
ess_e=datetime.now()
Frame4.grid(row = 1, column = 0)
Label1 = Label(Frame4, text = "Ravitaillement demarré ")
Label1.grid(row = 0, column = 0, columnspan = 2)
essvLabel = Label(Frame4, text = "Quelle voiture ? ")
essvEntry = Entry(Frame4)
essvLabel.grid(row = 1, column = 0)
essvEntry.grid(row = 1, column = 1)
essvEntry.focus()
esspLabel = Label(Frame4, text = "Quel pilote part ? ")
esspEntry = Entry(Frame4)
esspLabel.grid(row = 2, column = 0)
esspEntry.grid(row = 2, column = 1)
esspEntry.focus()
essqLabel = Label(Frame4, text = "Combien de litres ? ")
essqEntry = Entry(Frame4)
essqLabel.grid(row = 3, column = 0)
essqEntry.grid(row = 3, column = 1)
essqEntry.focus()
submitCommand = lambda event = None: essenceResult(ess, ess_e, essvEntry, esspEntry, essqEntry)
submitButton = Button(Frame4, text = "Sortie des stands", command = submitCommand)
Frame4.bind_all("<Return>", submitCommand)
submitButton.grid(row = 4, column = 0, columnspan = 2)
You also need to remove the extra Fenetre = Tk() after Frame4, as this will break it. (You can only have one Tk(), if you want more windows use Toplevel())The first problem is solved by adding Frame4.bind_all("<Return>", submitCommand). Now when you press enter it will run submitCommand, which will run essenceResult.
The second problem was using .get() on a datetime.datetime object. You can't use .get() because it isn't an entry. Instead, just have it as a parameter and don't change it. You only need .get() to get the values from a Tkinter Entry.
In this simple calculator GUI, I'm creating a frame template using classes. The frame has 2 labels, 2 entry boxes, and a button. I'd like the button to run a specific command depending on the function_call variable passed when initializing - but this doesn't work. The two_points function should be called for the first object, and one_point should be called for the second. How do I dynamically change which command is called based on which object I'm using? Thank you for taking the time to read this.
from tkinter import *
root = Tk()
root.title("Simple Slope Calculator")
class Slope_Calc:
# Variable info that changes within the frame
def __init__(self, master, num_1, num_2, frame_name, label_1_name, label_2_name, function_call):
self.num_1 = int(num_1)
self.num_2 = int(num_2)
self.frame_name = frame_name
self.label_1_name = label_1_name
self.label_2_name = label_2_name
self.function_call = function_call
# Frame template
self.frame_1 = LabelFrame(master, text = self.frame_name, padx = 5, pady = 5)
self.frame_1.grid(row = self.num_1, column = self.num_2, padx = 10, pady = 10)
self.label_1 = Label(self.frame_1, text = self.label_1_name)
self.label_1.grid(row = 0, column = 0)
self.entry_1 = Entry(self.frame_1)
self.entry_1.grid(row = 0, column = 1)
self.label_2 = Label(self.frame_1, text = self.label_2_name)
self.label_2.grid(row = 1, column = 0)
self.entry_2 = Entry(self.frame_1)
self.entry_2.grid(row = 1, column = 1)
self.calc_button = Button(self.frame_1, text = "Calculate", command = self.function_call) # This is what doesn't work
self.calc_button.grid(row = 1, column = 2, padx = 5)
# Strips string of spaces and parentheses
# Returns a list of relevant ordered pair
def strip_string(self, entry_num):
ordered_pair = entry_num.get().split(", ")
ordered_pair[0] = ordered_pair[0].replace("(", "")
ordered_pair[1] = ordered_pair[1].replace(")", "")
return(ordered_pair)
# Calculates slope based on one point and y-intercept
def one_point(self):
pair_1 = self.strip_string(self.entry_1)
b = int(self.entry_2.get())
m = (int(pair_1[1]) - b)/(float(pair_1[1]))
label_3 = Label(self.frame_1, text = "SLOPE-INTERCEPT EQUATION: y = " + str(m) + "x + " + str(b))
label_3.grid(row = 2, column = 0, columnspan = 2)
# Calculates slope based on two points given
def two_points(self):
pair_1 = self.strip_string(self.entry_1)
pair_2 = self.strip_string(self.entry_2)
m = (int(pair_2[1]) - int(pair_1[1]))/float(int(pair_2[0]) - int(pair_1[0]))
b = (int(pair_1[1])) - (m*int(pair_1[0]))
label_3 = Label(self.frame_1, text = "SLOPE-INTERCEPT EQUATION: y = " + str(m) + "x + " + str(b))
label_3.grid(row = 2, column = 0, columnspan = 2)
# Calling each object
two_p = Slope_Calc(root, 0, 0, "Two Points", "First Ordered Pair", "Second Ordered Pair", "two_points")
one_p = Slope_Calc(root, 0, 1, "One Point and Y-Intercept", "Ordered Pair", "Y-intercept", "one_point")
root.mainloop()
The command keyword argument of the Button constructor is supposed to be a function.
Here you give it instead a string which is the name of the method of self that should be called. So you must first get this method using setattr to be able to call it. This should do it:
def call():
method = getattr(self, self.function_call)
method()
self.calc_button = Button(
self.frame_1,
text = "Calculate",
command = call)
You then have an error in strip_string but that's another story.
this code is in referrence to a cricket scoring program
When a button is pressed in my program, it runs a validation based of the users input and if it goes through, it should open a new window. But every time I run the code, the window.
def team_names(team):
global team_amount
global team_name_input
global team_amount_test
team_name_input = Toplevel(master)
confirm_screen.withdraw()
enter_names = Label(team_name_input, text = "Enter amount of players in " + team).grid(row = 0, column = 1)
enter_names2 = Label(team_name_input, text="(Between 2 and 11)").grid(row=1, column=1)
team_amount_test = Entry(team_name_input, width = 20)
team_amount_test.grid(row = 2, column = 1)
submit_amount = Button(team_name_input, text="Submit", command= lambda:amount_validation(team_1_array)).grid(row=3, column=1) <--- Button to open new winodw
def amount_validation(team_array):
team_num = 1
team_amount = int(team_amount_test.get())
if team_num == 1:
current_team = team_1
elif team_num == 2:
current_team = team_2
#Validation
if team_amount < 2 or team_amount > 11:
error = Label(team_name_input, text = "Invalid amount, try again").grid(row = 4, column = 1)
elif team_amount > 2 or team_amount < 11:
player_num = 1
name_input_win = Toplevel(master) #Should open new winodw here
#name_input_win.geometry("200x150")
team_name_input.withdraw()
first = Label(name_input_win, text = "Enter player " + str(player_num) + " for " + str(current_team)).grid(row = 0, column = 1)
name_input = Entry(name_input_win)
name_input.grid(row = 1, column = 1)
name = str(name_input.get())
for i in range(0, player_num):
p = None
while not p or p in team_array:
#first = Label(name_input, text="Enter player " + str(player_num) + " for " + str(current_team)).grid(row=0,column=1)
if p in team_array:
error = Label(name_input, text = "Player already entered").grid(row = 2, column = 1)
team_array.append(p)
player_num = player_num + 1
Any help will be appriciated ^-^
I've made a simple gui age converter app but i want to change its bg color to black.
The problem is in the ttk frame.i don't know how to configure its bg color.
I have tried different methods but that didn't work.
i would be grateful if you guys could help.
here is the code
from tkinter import *
from tkinter import ttk
from PIL import Image
def calculate(*args):
try:
age_sec = int(age.get())
age_sec = age_sec * 12 * 365 * 24 * 60 * 60
age_seconds.set(age_sec)
except:
age_seconds.set('Either the field is empty or \n value is not numeric.')
root = Tk()
root.title("Converter")
root.configure(background="black")
mainframe = ttk.Frame(root, padding = "6 6 12 12")
mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
#mainframe['borderwidth'] = 2
#mainframe['relief'] = 'groove'
age = StringVar()
age_seconds = StringVar()
ttk.Label(mainframe, foreground = "#4D4E4F", text = "Enter your Age: ").grid(column = 1, row = 1, sticky = E)
age_entry = ttk.Entry(mainframe, width = 30, textvariable = age)
age_entry.grid(column = 2, row = 1, sticky = (W, E))
ttk.Label(mainframe, foreground = "#4D4E4F", text = "your age in seconds is ").grid(column = 1, row = 2, sticky = (E))
ttk.Label(mainframe, textvariable = age_seconds, background = "lightyellow", foreground = "#727475", width = 30).grid(column = 2, row = 2, sticky = W)
#Mouse Events...\\
butt_image = PhotoImage(file = 'images.gif')
ttk.Button(mainframe, compound = TOP, text = "Hit Now", image =butt_image, cursor = "hand2", width= 30, command = calculate).grid(column = 2, row = 4, sticky = W)
l2 = ttk.Label(mainframe,foreground = "#4D4E4F", text = "Mouse Events: ").grid(column = 1, row = 3, sticky = E)
l = ttk.Label(mainframe,background = "lightyellow", foreground = "#727475", text = 'Measurement is starting...', width = 30)
l.grid(column = 2, row = 3, sticky = W)
l.bind('<Enter>', lambda e: l.configure(text = 'Moved Mouse Inside'))
l.bind('<Leave>', lambda e: l.configure(text = 'Mouse Moved Out'))
l.bind('<1>', lambda e: l.configure(text = 'left Mouse clicked'))
l.bind('<Double-1>', lambda e: l.configure(text = 'Double clicked'))
l.bind('<B1-Motion>', lambda e: l.configure(text = 'Left button drag to %d, %d' %(e.x, e.y)))
image = PhotoImage(file = 'waves.gif')
ttk.Label(mainframe, compound = CENTER, text = "Image text", font = ('roman', 9, 'normal'), foreground ='green', image = image).grid(column = 3, row = 1, sticky = (N, E))
#if '__name__' == '__main__':
for child in mainframe.winfo_children(): child.grid_configure(padx = 15, pady = 15)
age_entry.focus()
root.bind('<Return>', calculate)
root.mainloop()
A ttk.Frame does not have a background / bg option. To change it you need to use style.
See ttk.Frame Info
If you don't really need to use a ttk.Frame you can just switch to a tkinter.Frame
I'm really hoping for some help on this as it has me absolutely stumped. I have the code working on its own as per below:
from tkinter import *
from PIL import ImageTk
dam_level = [75]
c = Canvas(width = 200, height = 235, relief = "sunken", borderwidth = 2)
c.grid(row = 11, rowspan = 8, column = 4, columnspan = 2)
c_width = 200
c_height = 250
y_stretch = 1.9
y_gap = 35
x_stretch = 15
x_width = 90
x_gap = 30
for x, y in enumerate(dam_level):
x0 = x * x_stretch + x * x_width + x_gap
y0 = c_height - (y * y_stretch + y_gap)
x1 = x * x_stretch + x * x_width + x_width + x_gap
y1 = c_height - y_gap
c.create_rectangle(x0, y0, x1, y1, fill = "#008ae8")
y = (str(y))
c.create_text(x0 + 10, y0, anchor = SW, text = (y, "%"))
c.create_text(x0 + 60, y1 + 5, anchor = N, text = "Catchment")
photo = ImageTk.PhotoImage(file =
"/Users/Name/Desktop/python3.4/water.png")
c.create_image(10, 10, image = photo, anchor = NW)
mainloop()
However when I put it in my main application in its own function (with the rest of my code), the image won't display. The graph and canvas displays, just not the water.png image. There's no error log or anything. The only change I make when I put this in my app is adding 'self' to this line. (And I remove the 'mainloop()' of course).
c = Canvas(self, width = 200, height = 235, relief = "sunken", borderwidth = 2)
Any suggestions would be greatly appreciated.
Thanks Bryan, for pointing me in the right direction.
Fixed with:
c.image = photo