Python : Retrieve ttk.Frame size - python

I'm tring to get Frame's size - but no luck.
in code below- I got both answers ,"0" ( line marked with ***)
from tkinter import *
from tkinter import ttk
root = Tk()
w = '400'
h = '100'
root.geometry('{}x{}'.format(w, h))
root.configure(bg='lightgreen')
txt = StringVar()
txt.set("Hello")
testframe = ttk.Frame(root)
testframe.grid(row=0, column=1 )
label1 = ttk.Label(testframe, textvariable=txt)
label1.grid(row=0, column=0)
print(testframe["width"], testframe.cget("width")) ***This line
root.mainloop()

The update method needs to be called first, so as to have the widget rendered.
If it is not, then its width is equal to zero.
This is explained in this answer.
Now, the problem with testframe['width'] is that it's only a hint of the actual width of the widget, as explained in this answer.
The following code will ouput 32, as expected.
from tkinter import *
from tkinter import ttk
root = Tk()
w = '400'
h = '100'
root.geometry('{}x{}'.format(w, h))
root.configure(bg='lightgreen')
txt = StringVar()
txt.set("Hello")
testframe = ttk.Frame(root)
testframe.grid(row=0, column=1 )
label1 = ttk.Label(testframe, textvariable=txt)
label1.grid(row=0, column=0)
# Modified lines
testframe.update()
print(testframe.winfo_width())
root.mainloop()

The frame widget will not have a size until it gets mapped on screen. There is a Tk event raised when a widget is mapped so the right solution for this example is to bind the <Map> event for the frame and do the print statement in the event handler function.
def on_frame_mapped(ev):
print(ev.widget.winfo_width())
testframe.bind('<Map>', on_frame_mapped)

Related

if condition for sting get from entry to compare with given string

I am new in python
I wanted to make a program that when you write a specific string in entry it compares it with a string and get an output but it doesnt go well ,where is the mistake i have done?
from tkinter import *
from tkinter.ttk import *
app=Tk()
load = Entry(app, width=10)
loadvar = StringVar
z = loadvar.get()
if z == "winner"
Label(app,text="congrats",).grid(row=1,column=0)
app.mainloop()
from tkinter import *
from tkinter.ttk import *
app = Tk()
# Entry
loadvar = StringVar()
load = Entry(app, width=10, textvariable=loadvar)
load.grid(row=0, column=0)
load.focus()
def compare():
if loadvar.get() == "winner":
# Label
Label(app, text="congrats", ).grid(row=1, column=0)
# Button
Button(text="Compare", command=compare).grid(row=0, column=1)
app.mainloop()
In your code, you have not placed the Entry widget yet. Moreover, you should use Buttons and link them with the function you want so that you can carry it out each time you are using it. Otherwise, you are check if the text inside entry is equal to 'winner' even before typing into it.
loadvar = StringVar
This line must be before creating Entry and then put in "textvariable" attribute of the widget.

problem with GUI Buttons calling functions that prompt user input within the GUI and then display Output

I cannot get the user input within the GUI
from tkinter import *
from tkinter import ttk
import math
I create main frame with buttons Rectangle,Triangle and use pack() to show it.
I also create two frames with Entry but I don't use pack() to show it.
When I click Rectangle or Triangle then it runs function which uses pack_forget() to remove main frame from window, and it uses .pack() two show one of frame with Entry.
This frame has button Calc which uses your function to calculate result - but it gets values from Entry and it displays result in Label.
It has also button Back which removes this frame and it shows main frame again.
I use current to remember current visible frame.
from tkinter import *
from tkinter import ttk
import math
# ---
def change_frame(new_frame):
global current
# hide current frame
current.pack_forget()
# show new frame
current = new_frame
current.pack()
def show_main_frame():
change_frame(main_frame)
def show_rectangle_frame():
change_frame(rectangle_frame)
def show_triangle_frame():
change_frame(triangle_frame)
# ---
def calc_rectangle():
try:
l = float(rectangle_entry1.get())
w = float(rectangle_entry2.get())
arear=(l * w)
print(arear)
rectangle_result['text'] = str(arear)
except ValueError:
pass
def calc_triangle():
try:
b = float(triangle_entry1.get())
h = float(triangle_entry2.get())
areat=(0.5* b * h )
print(areat)
triangle_result['text'] = str(areat)
except ValueError:
pass
#-----
window = Tk()
window.title("Area Calculator")
#window.geometry("290x120")
main_frame = Frame(window)
main_frame.pack()
button = Button(main_frame, text="Rectangle", command=show_rectangle_frame)
button.pack()
button = Button(main_frame, text="Triangle", command=show_triangle_frame)
button.pack()
current = main_frame
# --- frame without .pack() ---
rectangle_frame = Frame(window)
rectangle_result = Label(rectangle_frame, text="")
rectangle_result.pack()
l = Label(rectangle_frame, text="Enter Length:")
l.pack()
rectangle_entry1 = Entry(rectangle_frame)
rectangle_entry1.pack()
l = Label(rectangle_frame, text="Enter Width:")
l.pack()
rectangle_entry2 = Entry(rectangle_frame)
rectangle_entry2.pack()
b = Button(rectangle_frame, text="Calc", command=calc_rectangle)
b.pack()
b = Button(rectangle_frame, text="BACK", command=show_main_frame)
b.pack()
# --- frame without .pack() ---
triangle_frame = Frame(window)
triangle_result = Label(triangle_frame, text="")
triangle_result.pack()
l = Label(triangle_frame, text="Enter base:")
l.pack()
triangle_entry1 = Entry(triangle_frame)
triangle_entry1.pack()
l = Label(triangle_frame, text="Enter Height:")
l.pack()
triangle_entry2 = Entry(triangle_frame)
triangle_entry2.pack()
b = Button(triangle_frame, text="Calc", command=calc_triangle)
b.pack()
b = Button(triangle_frame, text="BACK", command=show_main_frame)
b.pack()
# ---
window.mainloop()
Using lambda you can do
command=lambda:change_frame(rectanlge_frame)
and then you don't need function show_rectanlge_frame
The same with second frame.
There is more complex version created by Bryan Oakley which uses classes Page(Frame) and sometimes you can see these classes in questions on Stackoverflow.

my tkinter doesnt show up anything i have coded

i wrote this code, but when i run it it doesnt show any error, but the app is blank can you please show where i have done the mistake. Thank You
from tkinter import *
import csv
import os
os.chdir(r"C:\Users\Umer Selmani\Desktop\prog.practice\MP1")
root=Tk()
class Diet:
def __init__(self,Tops,Lefts, Rights):
self.Tops=Frame(root,width= 200,height=200).pack(side=TOP)
self.Lefts=Frame(root,width= 200,height=200).pack(side=LEFT)
self.Rights=Frame(root,width= 200,height=200).pack(side=RIGHT)
self.label1=Label(Tops,font=("ariel","bold" ,20),text="Sehir Cafeteria",
bg="darkblue").grid(row=0,columns=0)
root.mainloop()
You need to do
diet = Diet()
diet.pack()
You don't need to pass Tops, Lefts & Rights to the __init__() function if they are the frames you want to display. They are created in __init__().
The pack() function returns None which means you don't keep a reference to the respective frames. I have corrected this in my example.
To display the frames defined in the Diet class you must first create an instance.
I have color-coded the frames so they are visible.
from tkinter import *
class Diet:
def __init__(self):
self.Tops = Frame(root, width=400, height=200, bg='tan')
self.Tops.pack(side=TOP)
self.Tops.pack_propagate(False)
self.Lefts = Frame(root, width= 200, height=200, bg='salmon')
self.Lefts.pack(side=LEFT)
self.Rights = Frame(root, width= 200, height=200, bg='bisque')
self.Rights.pack(side=RIGHT)
self.label1 = Label(self.Tops, font="ariel 20 bold",
text="Sehir Cafeteria", bg="darkblue")
self.label1.pack(fill='x')
# Grid() will shrink the self.Tops frame to exactly
# fit the label.
root = Tk()
diet = Diet() # Create an instance of Diet.
root.mainloop()
Additional explanation
Different return values from widget creation depending on how the code is written depends on how information is passed between objects:
# The first code:
self.Tops = Frame(root, width=400, height=200, bg='tan')
# Creates a Frame and associates it with the name "self.Tops"
self.Tops.pack(side=TOP)
# uses the geometry manager pack to display the frame "self.Tops"
# The method call returns the value: None
# self.Tops is still referencing the frame
# The second code does the same thing but in a single compound statement
self.Tops = Frame(root, width=400, height=200, bg='tan').pack(side=TOP)
# Creates a frame and passes a reference to that frame to pack.
# Pack displays the label on the window and returns the value: None
# This value is given the reference "self.Tops"
Try running the code below and examine the console printout.
from tkinter import *
root = Tk()
label_a = Label(root, text='A')
return_a = label_a.pack()
print('label_a:', label_a)
print('return_a:', return_a)
label_b = Label(root, text='B').pack()
print('label_b:', label_b)
root.mainloop()
Hope this makes things clearer.

Create scrollbar only when text length greater than text area

Here is some simple code:
from tkinter import *
from tkinter import ttk
rootwin = Tk()
roomtext = Text(rootwin)
roomtext.pack(side = 'left', fill = "both", expand = True)
rtas = ttk.Scrollbar(roomtext, orient = "vertical", command = roomtext.yview)
rtas.pack(side = "right" , fill = "both")
roomtext.config(yscrollcommand = rtas.set)
rootwin.mainloop()
As such, a default scrollbar appears straight away.
How is it possible to make the scrollbar appear once text entered is greater than text area?
So when I run code, first, scrollbar must not show. Then when enough text is entered scrollbar shows (i.e. text in roomtext longer than roomtext area).
Maybe this code is what you are looking for (changed pack to grid as I'm more familiar with it... You should be able to revert that easily if you want):
from tkinter import *
from tkinter import ttk
rootwin = Tk()
roomtext = Text(rootwin)
roomtext.grid(column=0, row=0)
def create_scrollbar():
if roomtext.cget('height') < int(roomtext.index('end-1c').split('.')[0]):
rtas = ttk.Scrollbar(rootwin, orient = "vertical", command = roomtext.yview)
rtas.grid(column=1, row=0, sticky=N+S)
roomtext.config(yscrollcommand = rtas.set)
else:
rootwin.after(100, create_scrollbar)
create_scrollbar()
rootwin.mainloop()
It checks if it needs to create a scrollbar 10 times every second.
With some additional changes you can even make it remove the scrollbar when no longer needed (text too short):
from tkinter import *
from tkinter import ttk
rootwin = Tk()
roomtext = Text(rootwin)
roomtext.grid(column=0, row=0)
rtas = ttk.Scrollbar(rootwin, orient = "vertical", command = roomtext.yview)
def show_scrollbar():
if roomtext.cget('height') < int(roomtext.index('end-1c').split('.')[0]):
rtas.grid(column=1, row=0, sticky=N+S)
roomtext.config(yscrollcommand = rtas.set)
rootwin.after(100, hide_scrollbar)
else:
rootwin.after(100, show_scrollbar)
def hide_scrollbar():
if roomtext.cget('height') >= int(roomtext.index('end-1c').split('.')[0]):
rtas.grid_forget()
roomtext.config(yscrollcommand = None)
rootwin.after(100, show_scrollbar)
else:
rootwin.after(100, hide_scrollbar)
show_scrollbar()
rootwin.mainloop()

can we code time in text widget?

Is it possible to code time HH:MM:SS using text widget?
I know we can do this with label widget. My code deals with text widget and want to display time at any corner on the TKinter window.
If possible how to delete and insert the text using label widgets. Text widget has the following methods default.
delete(startindex [,endindex])
This method deletes a specific character or a range of text.
insert(index [,string]...)
This method inserts strings at the specified index location.
In my code the text has to be deleted and inserted all the time.
thanks.
delete from 1.0 to end.
import datetime
text.delete('1.0', 'end')
text.insert('end', datetime.datetime.now().strftime('%H:%M:%S')) # text.insert('end', label['text'])
label['text'] = datetime.datetime.now().strftime('%H:%M:%S')
Display Entry on bottom right
import datetime
from Tkinter import * # from tkinter import * # Python 3.x
root = Tk()
root.geometry('500x500')
frame = Frame(root)
frame.pack(side=BOTTOM, fill=BOTH)
entry = Entry(frame)
entry.pack(side=RIGHT)
entry.insert(END, datetime.datetime.now().strftime('%H:%M:%S'))
root.mainloop()
def __init__(self):
tk.Tk.__init__(self)
self.geometry("1360x750")
frameLabel = tk.Frame(self)
self.text = tk.Text(frameLabel)
frameLabel.pack(side=BOTTOM, fill=BOTH)
self.text.pack(side=RIGHT)
self.text.insert('end', 'TEST')
self.queue = Queue.Queue()
thread = SerialThread(self.queue)
thread.start()
self.process_serial()
UPDATE2
import datetime
from Tkinter import * # from tkinter import * # Python 3.x
root = Tk()
root.geometry('500x500')
frame = Frame(root)
frame.pack(side=BOTTOM, fill=BOTH)
label = Label(frame)
label.pack(side=RIGHT)
label['text'] = datetime.datetime.now().strftime('%H:%M:%S')
root.mainloop()

Categories

Resources