Tkinter - Printnig return function in a label - python

i don't really undestand, why the "results" label is not updating when i click on the button.
If someone can help me to understand!
Thank You
from tkinter import *
from tkinter import ttk
def add_function():
results.config(n1.get() + n2.get())
root = Tk()
root.geometry("500x100") # Size of the window
root.title("Add Calculator") # Title of the window
main_frame = ttk.Frame(root, padding="3 3 12 12")
main_frame.grid(column=0, row=0, sticky=(N,S,E,W))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
n1 = DoubleVar()
n1_entry = Entry(main_frame, width= 10, textvariable= n1)
n1_entry.grid(column=2, row=1, sticky=(N))
symbol_add = Label(main_frame, text="+")
symbol_add.grid(column=3, row=1, sticky=(N))
n2 = DoubleVar()
n2_entry = Entry(main_frame, width= 10, textvariable= n2)
n2_entry.grid(column=4, row=1, sticky=(N))
symbol_equal = Button(main_frame, width=10, text="=", command= add_function )
symbol_equal.grid(column=5, row=1, sticky=(N))
results = Label(main_frame, text=add_function(), background="#C0C0C0")
results.grid(column=6, row=1, sticky=(N))
root.mainloop()
I've tryed different variant, but it's either i have an error, or the label is printing a random number even before i modify the entry.

It is because you don't update the label. Returning something from a button command is pointless because the caller isn't your code. It's called from mainloop and mainloop doesn't know what to do with the return code.
To update the label you must call the configure method:
results.configure(text=n1.get() + n2.get())

Related

Ttk label not displaying TextVar

I'm making a GUI with Tkinter (Tcl/Tk version 8.6.12) on Python 3.9. Up until now, I mostly had experience with pure Tk, but wanted to try Ttk out. My problem is that running:
someText = tk.StringVar(value="Some Text")
ttk.Label(mainframe, textvariable=someText).grid(column=0, row=0, sticky=(W, E))
does reserve some space for the string, but doesn't display it. When using the tk.Label class, it works like a charm...
What am I doing wrong, or is the ttk.Label class broken?
EDIT: here is my full MNWE (I wrapped everything in a function because I will need to integrate everything with some other code I have already written and this is the best way I've found to do it):
from tkinter import *
from tkinter import ttk
def generateGUI():
# Generates the main window
root = Tk()
root.title("Some interesting title")
root.resizable(FALSE, FALSE)
# Adds a frame for themed tk
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1) # setup the frame to scale with the window horizontally
root.rowconfigure(0, weight=1) # setup the frame to scale with the window vertically
# Creates a canvas
canv = Canvas(mainframe, bg="green")
canv.grid(column=0, row=0, sticky=(N, E, S, W))
# Sets some information panel up
info = ttk.Frame(mainframe)
info.grid(column=1, row=0, sticky=(N, E))
title = StringVar(value="<title>")
text1 = StringVar(value="<text1>")
text2 = StringVar(value="<text2>")
text3 = StringVar(value="<text3>")
# Adds the different labels
ttk.Label(info, font=25, textvariable=title).grid(column=0, row=0, sticky=N, columnspan=2)
ttk.Label(info, text="Info 1: ").grid(column=0, row=1, sticky=W)
ttk.Label(info, text="Info 2: ").grid(column=0, row=2, sticky=W)
ttk.Label(info, text="Info 3: ").grid(column=0, row=3, sticky=W)
ttk.Label(info, textvariable=text1).grid(column=1, row=1, sticky=E)
ttk.Label(info, textvariable=text2).grid(column=1, row=2, sticky=E)
ttk.Label(info, textvariable=text3).grid(column=1, row=3, sticky=E)
for child in mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
return root
gui = generateGUI()
gui.mainloop()
Your instance of StringVar is a local variable. Make it/them an instance variable if you're using classes, or a global variable if not.
def generateGUI():
global title
...
title = StringVar(value="<title>")
ttk.Label(info, font=25, textvariable=title)
This example code is working. You need to import ttk and change remove sticky.
why_no_sticky - good example on the link how grid works.
from tkinter import ttk
import tkinter as tk
mainframe = tk.Tk()
someText = tk.StringVar(value="Some Text")
label1 = ttk.Label(mainframe, textvariable=someText)
label1.grid(column=0, row=0)
mainframe.mainloop()

How can I put a ttk.LabelFrame inside a ttk.PanedWindow?

I'm initiating in ttk and I keep getting this error while trying to add a LabelFrame inside a PanedWindow. Happens on line 46 (self.pwEntries.add(self.lfEntries)):
_tkinter.TclError: wrong # args: should be ".!frame.!panedwindow.!panedwindow add window"
As I've no idea how to solve it I would really appreciate some help, please...
My code goes like this:
from tkinter import *
from tkinter import ttk
class CalcVendGame:
def __init__(self, root):
root.title("Calcula Venda Games")
self.mainframe = ttk.Frame(root, padding="3 3 12 12")
self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
self.pwRoot = ttk.PanedWindow(self.mainframe, orient=VERTICAL)
self.pwEntries = ttk.PanedWindow(self.pwRoot, orient=HORIZONTAL)
self.lfEntries = ttk.LabelFrame(self.pwEntries, labelanchor='nw').grid(
column=0, row=0, sticky=(N, W))
ttk.Label(self.lfEntries, text="Valor em Dólar de cada cópia:", padding="5").grid(
column=2, row=1, sticky=E)
self.CopiaEmDolar = StringVar()
cpEmDol_entry = ttk.Entry(
self.lfEntries, width=7, textvariable=self.CopiaEmDolar)
cpEmDol_entry.grid(column=3, row=1, sticky=W)
ttk.Label(self.lfEntries, text="Ex: \"19.99\"", padding="5").grid(
column=4, row=1, sticky=W)
ttk.Label(self.lfEntries, text="Quantidade de cópias vendidas:", padding="5").grid(
column=2, row=2, sticky=E)
self.CopiasVendidas = StringVar()
cpVend_entry = ttk.Entry(
self.lfEntries, width=7, textvariable=self.CopiasVendidas)
cpVend_entry.grid(column=3, row=2, sticky=W)
ttk.Button(self.lfEntries, text="Calcular").grid(
column=4, row=3, sticky=W)
self.pwEntries.add(self.lfEntries)
self.pwPC = ttk.PanedWindow(self.pwRoot, orient=HORIZONTAL)
self.pwSteam = ttk.PanedWindow(self.pwPC, orient=VERTICAL)
self.lfSteam = ttk.LabelFrame(self.pwSteam, padding=(
5), text='Steam', labelanchor='nw')
ttk.Label(self.lfSteam, text="Cut 35%", padding="5").grid(
column=0, row=0, sticky=W)
ttk.Separator(self.lfSteam, orient=HORIZONTAL)
self.pwPatreon = ttk.PanedWindow(self.pwRoot, orient=VERTICAL)
self.pwPC.add(self.pwSteam)
self.pwPC.add(self.pwPatreon)
self.pwMobile = ttk.PanedWindow(self.pwRoot, orient=HORIZONTAL)
# self.pwRoot.add(self.lfEntries)
self.pwRoot.add(self.pwEntries)
self.pwRoot.add(self.pwPC)
self.pwRoot.add(self.pwMobile)
root = Tk()
CalcVendGame(root)
root.mainloop()
Also, this code give me no errors but results on a blank window:
from tkinter import *
from tkinter import ttk
master = Tk()
mainframe = ttk.Frame(master, padding="3 3 10 10")
p = ttk.Panedwindow(mainframe, orient=VERTICAL)
# two panes, each of which would get widgets gridded into it:
f1 = ttk.Labelframe(p, text='Pane1', width=100, height=100)
ttk.Label(f1, text="Valor em Dólar de cada cópia:", padding="5")
f2 = ttk.Labelframe(p, text='Pane2', width=100, height=100)
ttk.Label(f2, text="Quantidade de cópias vendidas:", padding="5")
p.add(f1)
p.add(f2)
master.mainloop()
You forgot to use any layout manager on the widgets. Below is an updated code using pack():
from tkinter import *
from tkinter import ttk
master = Tk()
mainframe = ttk.Frame(master, padding="3 3 10 10")
mainframe.pack()
p = ttk.Panedwindow(mainframe, orient=VERTICAL)
p.pack()
# two panes, each of which would get widgets gridded into it:
f1 = ttk.Labelframe(p, text='Pane1', width=100, height=100)
ttk.Label(f1, text="Valor em Dólar de cada cópia:", padding="5").pack()
f2 = ttk.Labelframe(p, text='Pane2', width=100, height=100)
ttk.Label(f2, text="Quantidade de cópias vendidas:", padding="5").pack()
p.add(f1)
p.add(f2)
master.mainloop()

How to stop automatic resizing of frames

I have three frames, but when a new label appears the frames automatically readjust to a new size. How do I stop the readjustment and have the size of each frame set and immutable.
#Import tkinter to make gui
from tkinter import *
from tkinter import ttk
import codecs
#Program that results when user attempts to log in
def login(*args):
file = open("rot13.txt", "r")
lines = file.readlines()
uname = user.get()
pword = pw.get()
for i in lines:
x = i.split()
if codecs.encode(uname,'rot13') == x[0] and codecs.encode(pword,'rot13') == x[1]:
result.set("Successful")
break;
else:
result.set("Access Denied")
root = Tk()
root.title("Login")
#Configures column and row settings and sets padding
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe['borderwidth'] = 5
mainframe['relief'] = "solid"
mainframe.grid(column=1, row=1, columnspan=3, rowspan=2)
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
mainframe2 = ttk.Frame(root, padding="3 3 12 12")
mainframe2['borderwidth'] = 5
mainframe2['relief'] = "solid"
mainframe2.grid(column=1, row=3, columnspan=1, rowspan=3)
mainframe2.columnconfigure(0, weight=1)
mainframe2.rowconfigure(0, weight=1)
mainframe3 = ttk.Frame(root, padding="3 3 12 12")
mainframe3['borderwidth'] = 5
mainframe3['relief'] = "solid"
mainframe3.grid(column=2, row=5)
mainframe3.columnconfigure(0, weight=1)
mainframe3.rowconfigure(0, weight=1)
#anchors for widgets
user = StringVar()
pw = StringVar()
result = StringVar()
#Asks user input
user_entry = ttk.Entry(mainframe, width=20, textvariable=user)
user_entry.grid(column=2, row=1, sticky=(W, E))
pw_entry = ttk.Entry(mainframe, width=20, textvariable=pw)
pw_entry.grid(column=2, row=2, sticky=(W, E))
#Labels to make user-friendly and able to understand
ttk.Label(mainframe, text="Username ").grid(column=1, row=1, sticky=W)
ttk.Label(mainframe, text="Password ").grid(column=1, row=2, sticky=W)
ttk.Label(mainframe2, text="").grid(column=1, row=3, sticky=W)
ttk.Label(mainframe2, text="Result").grid(column=1, row=4, sticky=W)
ttk.Label(mainframe2, text="").grid(column=1, row=5, sticky=W)
#Button to log in
ttk.Button(mainframe3, text="Login", command=login).grid(column=3, row=5, sticky=(W,E))
#Makes a spot to put in result
ttk.Label(mainframe2, textvariable=result).grid(column=2, row=4, sticky=(W, E))
#Opens up with item selected and allows you to enter username without having to click it
user_entry.focus()
#Runs calculate if click enter
root.bind('<Return>', login)
root.mainloop()
Here is the before and after picture of the results:
As you can see the frames change sizes after the program runs its course. How do i stop this re-size and stick to a predetermined size?
The simplest solution in this specific case is to give the label with the text a fixed width. When you specify a fixed width for a label, tkinter will do it's best to honor that width (though a lot depends on how you place it on the screen with pack, place or grid).
ttk.Label(..., width=12).grid(...)
Another solution is to turn off geometry propagation, which means you're responsible for giving the frame an explicit width and height:
mainframe2 = ttk.Frame(..., width=200, height=100)
...
mainframe2.grid_propagate(False)
I do not recommend turning geometry propagation off. Tkinter is usually very good at computing the right size for widgets, and this usually results in very poor behavior if you change fonts, screen resolutions, or root window sizes.
Just add a width option to ttk.Label(mainframe2, textvariable=result).grid(column=2, row=4, sticky=(W, E)):
So it will become like this:
ttk.Label(mainframe2, textvariable=result, width=20).grid(column=2, row=4, sticky=(W, E))

Resizing window doesn't resize contents in tkinter

I'm making my first GUI application and I've run into a silly problem. Resizing the main window doesn't resize its contents and leaves blank space. I've read the TKDocs and they only say you should use sticky and column/row weight attributes but I don't really understand how they work.
Here's my code (only the part covering widgets, if you think problem isn't here I'll post the rest of it):
from tkinter import *
from tkinter import ttk
root = Tk()
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)
player1 = StringVar()
player2 = StringVar()
player1.set('Player 1')
player2.set('Player 1')
timer=StringVar()
running=BooleanVar()
running.set(0)
settimer = ttk.Entry(mainframe, width=7, textvariable=timer)
settimer.grid(column=2, row=1, sticky=(N, S))
ttk.Button(mainframe, text="Start", command=start).grid(column=2, row=2, sticky=(N, S))
ttk.Label(mainframe, textvariable=player1, font=TimeFont).grid(column=1, row=3, sticky=(W, S))
ttk.Label(mainframe, textvariable=player2, font=TimeFont).grid(column=3, row=3, sticky=(E, S))
for child in mainframe.winfo_children():
child.grid_configure(padx=80, pady=10)
root.mainloop()
Thanks for your time!
Maybe this will help you in the right direction. Be sure to configure column/row weights at each level.
import tkinter.ttk
from tkinter.constants import *
class Application(tkinter.ttk.Frame):
#classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
app = cls(root)
app.grid(sticky=NSEW)
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
root.resizable(True, False)
root.mainloop()
def __init__(self, root):
super().__init__(root)
self.create_variables()
self.create_widgets()
self.grid_widgets()
self.grid_columnconfigure(0, weight=1)
def create_variables(self):
self.player1 = tkinter.StringVar(self, 'Player 1')
self.player2 = tkinter.StringVar(self, 'Player 2')
self.timer = tkinter.StringVar(self)
self.running = tkinter.BooleanVar(self)
def create_widgets(self):
self.set_timer = tkinter.ttk.Entry(self, textvariable=self.timer)
self.start = tkinter.ttk.Button(self, text='Start', command=self.start)
self.display1 = tkinter.ttk.Label(self, textvariable=self.player1)
self.display2 = tkinter.ttk.Label(self, textvariable=self.player2)
def grid_widgets(self):
options = dict(sticky=NSEW, padx=3, pady=4)
self.set_timer.grid(column=0, row=0, **options)
self.start.grid(column=0, row=1, **options)
self.display1.grid(column=0, row=2, **options)
self.display2.grid(column=0, row=3, **options)
def start(self):
timer = self.timer.get()
self.player1.set(timer)
self.player2.set(timer)
if __name__ == '__main__':
Application.main()

Tkinter and ttk python2.7

i found this code online and i wanted to try it out because im trying to figure out how to have my label to change while i type things into my messagebox. I tried the getmethod but i have been struggling with using it. So i found this code and when i tried it i get the error that ttk is undefined but it clearly is.
from Tkinter import *
from ttk import *
def calculate(*args):
try:
value = float(feet.get())
meters.set((0.3048 * value * 10000.0 + 0.5)/10000.0)
except ValueError:
pass
root = Tk()
root.title("Feet to Meters")
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)
feet = StringVar()
meters = StringVar()
feet_entry = ttkEntry(mainframe, width=7, textvariable=feet)
feet_entry.grid(column=2, row=1, sticky=(W, E))
ttk.Label(mainframe, textvariable=meters).grid(column=2, row=2, sticky=(W, E))
ttk.Button(mainframe, text="Calculate", command=calculate).grid(column=3, row=3, sticky=W)
ttk.Label(mainframe, text="feet").grid(column=3, row=1, sticky=W)
ttk.Label(mainframe, text="is equivalent to").grid(column=1, row=2, sticky=E)
ttk.Label(mainframe, text="meters").grid(column=3, row=2, sticky=W)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
feet_entry.focus()
root.bind('<Return>', calculate)
root.mainloop()
Traceback (most recent call last):
File "tk8.py", line 15, in
mainframe = ttk.Frame(root, padding="3 3 12 12")
NameError: name 'ttk' is not defined
So i found this code and when i tried it i get the error that ttk is
undefined but it clearly is.
You're star-importing from the module, though, using from ttk import *, so the name ttk doesn't refer to anything. For example, from math import * would bring sin, cos, etc., all into your namespace but the name math would still be undefined. The code works for me if I switch the imports to
from Tkinter import *
import ttk
and add the missing . from ttk.Entry in this line:
feet_entry = ttk.Entry(mainframe, width=7, textvariable=feet)
You are looking for the trace_variable method. Here is a fixed version:
from Tkinter import Tk, StringVar
import ttk
def calculate(*args):
try:
value = float(feet.get())
meters.set('%g' % (0.3048 * value))
except ValueError:
if not feet.get():
meters.set('')
root = Tk()
root.title("Feet to Meters")
feet = StringVar()
feet.trace_variable('w', calculate)
meters = StringVar()
main = ttk.Frame(root)
main.grid(sticky='nsew')
ttk.Label(main, text="Feet:").grid(row=0, sticky='e')
feet_entry = ttk.Entry(main, width=7, textvariable=feet)
feet_entry.grid(row=0, column=1, sticky='ew')
feet_entry.focus()
ttk.Label(main, text="Meters:").grid(row=1, sticky='e')
ttk.Label(main, textvariable=meters).grid(row=1, column=1, sticky='ew')
root.mainloop()

Categories

Resources