[Tutor] Tkinter, the correct way

Alan Gauld alan.gauld at yahoo.co.uk
Fri Feb 10 10:40:37 EST 2023


On 10/02/2023 09:00, Phil wrote:

> Is this code the correct modern way?

There is no such thing. Thre are many styles of tkinter programming.
"Correctness" is largely subjective (assuming the code works of course!)

> I don't notice any difference If I omit the frame padding and grid options.

That normally only makes a difference when you resize a window
near its limits(small or large).

> VS Code issues warnings to do with import * 

Sensibly so. I don't think any production Tkinter code
should use import *. The style i normally see is

import tkinter as tk

or similar.

> and value_label = etc is a function without a return. 

Again, correctly. The return from ttk.Label().grid() is
None so assigning it to a variable is pointless.

> Finally, moving the scale with the arrow keys show integers but moving 
> the scale with the mouse cause the scale value to be a long floating 
> point number. How might I have the value variable be an integer when the 
> mouse is moved?

Need to read the docs(and/or Tcl/Tk code?) for the Scale widget.

> from tkinter import *
> from tkinter import ttk
> 
> class ScaleDemo:
> 
>      def __init__(self, root):
> 
>          root.title("Scale Demo")
> 
>          frame = ttk.Frame(root, padding="3 3 12 12")
>          frame.grid(column=0, row=0, sticky=(N, S, E, W))
> 
>          root.columnconfigure(0, weight=1)
>          root.rowconfigure(0, weight=1)
> 
>          self.value = DoubleVar()

This might be the root of your problem. What happens if
you use an IntVar instead of a DoubleVar? But double makes
more sense for a Scale if you can set intermediate points.

>          slider = ttk.Scale(
>              frame,
>              from_=0,
>              to=100,
>              orient='horizontal',  # vertical
>              command=self.slider_changed,
>              variable=self.value)

I would have thought you might want to keep hold of the slider so

self.slider = ...

> 
>          slider.grid(column=2, row=1, sticky=(E, W))
> 
>          value_label = ttk.Label(frame, textvariable=self.value).grid(
>              column=2, row=2, sticky=(W, E))

And this shouldn't work. grid() returns None.
Hence your warning from VS.

OTOH you don;t stre the value outside __init__() and never
use it inside so its totally irrelevant!

>          ttk.Button(frame, text="Exit", command=root.destroy).grid(
>              column=3, row=3, sticky=W)

This is the more normal approach with no variable used.


>          for child in frame.winfo_children():
>              child.grid_configure(padx=5, pady=5)

I'm not sure about this but it doesn't look right to me.
I prefer to have all the options supplied per widet even
if its slightly more typing (probably less in this case!)
My reasoning is that I look for the options where the
widget is created, putting some of them in a loop
which affects every widget sounds like a debugging
nightmare to me!

> 
>          slider.focus()
> 
>      def slider_changed(self, event):
>          #print('value changed')
>          print(f'{self.value.get():,.1f}')

Is this the bit where you get the int/double issue?
If so I suspect the arrow keys move the slider in unit amounts hence
integers and the mouse moves it in a contuinuous manner and returns
doubles. ie What I'd expect. But I've never used a ttk.slider so
don't know.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos





More information about the Tutor mailing list