Moving Current Value#
The tkinter Scale has the ability to display a moving Label with the current
scale value. One might think of a Canvas with a moving value, but we shall
use an ordinary Label positioned according to the place layout manager.
The current Scale value is known, the main unknown is the
position of the display Label for any given Scale output, this should
correspond to the centre of the slider which is offset to be above the Scale.
Since both rel_min and rel_max are known it should be easy to calculate.
Just as with the
range values use a relative x value. As the cursor moves so the current
value in the display value should change - check what is
required by moving the tkinter Scale. To keep the display label
updated use the command option on the
Scale, this calls up a function that calculates the relative x and
simultaneously sets the display labels position and actual display value.
Otherwise linking the display label through a tkinter variable, but would show
a float number with umpteen decimal places.
Every slider movement triggers the function, so a continuously moving and
changing display results. Link the SpinBox and
Scale through a tkinter variable, then adjust the Spinbox's size to limit the
its display.
A simple function is used to calculate the relative x position:
def convert_to_relx(curr_val):
return ((curr_val - from_val) * (rel_max - rel_min) / (to_val - from_val) \
+ rel_min)
Another function changes the display label:
def display_value(value):
rel_x = convert_to_relx(float(value))
disp_lab.place_configure(relx=rel_x)
disp_lab.configure(text=f'{float(value):.{dig_val}f}')
Note
There are several methods to format text, the latest configuration
for Python 3.6 and above is the preferred method. Value (Scale actual
value) needs to be converted to a float. The digits option, dig_val
is related to the number of decimal places shown. Since a float
is being replaced the variable dig_val requires curly brackets.
Show/Hide Code 07ttk_tkinter_shift_value.py
import tkinter as tk
from tkinter import font
import tkinter.ttk as ttk
import numpy as np
from_val = -1
to_val = 1
len_val = 500
res_val = 0.10
tick_val = 0.10
dig_val = 2
bw_val = 1 # trough border width
slider_val = 36
sc_range = abs(to_val - from_val) # scale range
def selh(val):
sbh.config(text=round(float(scth.get())+0.0049,2))
root = tk.Tk()
root.geometry(str(len_val+150)+"x200+500+500")
s = ttk.Style()
s.theme_use('default')
def_font = font.nametofont('TkDefaultFont')
from_size = def_font.measure(from_val)
to_size = def_font.measure(to_val)
sch = tk.Scale(root, from_=from_val, to=to_val, label='Bogusstuinuous', orient='horizontal',
resolution=res_val, showvalue=1, tickinterval=tick_val, digits=dig_val,
length=len_val)
sch.grid(sticky='ew')
sep = ttk.Separator(root, orient='horizontal')
sep.grid(row=1, column=0, columnspan=2)
def convert_to_relx(curr_val):
return ((curr_val - from_val) * (rel_max - rel_min) / (to_val - from_val) \
+ rel_min)
def display_value(value):
# position (in pixel) of the center of the slider
rel_x = convert_to_relx(float(value))
disp_lab.place_configure(relx=rel_x)
my_precision = '{:.{}f}'.format
disp_lab.configure(text=my_precision(float(value), int(dig_val)))
slider = tk.StringVar()
slider.set('0.00')
scth = ttk.Scale(root, from_=from_val, to=to_val, length=len_val,
command=display_value)
scth.grid(row=2, column=0, sticky='ew', padx=5, pady=15)
rel_min = ((slider_val - from_size) / 2 + bw_val) / len_val
rel_max = 1 - (slider_val /2 - bw_val) / len_val
# using numpy arange instead of range so tick intervals less than 1 can be used
data = np.arange(from_val, to_val+tick_val, tick_val)
data = np.round(data,1)
range_vals = tuple(data)
len_rvs = len(range_vals)
for i, rv in enumerate(range_vals):
item = ttk.Label(root, text=rv)
item.place(in_=scth, bordermode='outside',
relx=(rel_min + i / (len_rvs - 1) * (rel_max - rel_min)) ,
rely=1, anchor='n')
disp_lab = ttk.Label(root, textvariable = slider)
disp_lab.place(in_=scth, bordermode='outside',
relx=0.5, rely=0, anchor='s')
display_value(scth.get())
sbh = ttk.Spinbox(root, from_=from_val, to=to_val, textvariable=slider,
width=5, increment=res_val)
sbh.grid(row=2, column=1)
root.mainloop()