Reputation: 11640
I used to use digits
property of tk.Scale
to make sure the numbers in a Label
or Spinbox
show fixed number of decimal digits as the slider moves. Like 3.456, 4444.567, 5555555.678, ...
However, with ttk.Scale
digits
and resolution
are gone. I'm left with a long decimal number if a tk.DoubleVar
is used as the scale variable. So according to this post:
How to make ttk.Scale behave more like tk.Scale?
I'd have to code up my own number display scheme for the label, which seems crazy when I already work with a widget class. I have yet to see how to keep the DoubleVar for this because I'll need to change the string representation of it.
Is there an easier way to achieve what I want?
UPDATE:
Here is the code:
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
mainframe = tk.Frame(root)
# Model
input = tk.DoubleVar(value=0.)
spin = tk.Spinbox(mainframe, textvariable=input, wrap=True, width=10)
slide = ttk.Scale(mainframe, variable=input, orient='horizontal', length=200)
spin['to'] = 1.0
spin['from'] = 0.0
spin['increment'] = 0.01
slide['to'] = 1.0
slide['from'] = 0.0
# slide['digits'] = 4
# slide['resolution'] = 0.01
# Layout
weights = {'spin': 1, 'slide': 100}
mainframe.grid_rowconfigure(0, weight=1)
mainframe.grid_columnconfigure(0, weight=weights['spin'])
mainframe.grid_columnconfigure(1, weight=weights['slide'])
spin.grid(row=0, column=0, sticky='news')
slide.grid(row=0, column=1, sticky='news')
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
mainframe.grid(row=0, column=0)
root.mainloop()
As I drag the Scale, the decimal number suddenly becomes out of control.
Upvotes: 4
Views: 4354
Reputation: 123491
Here's a better solution than what was in my first (now deleted) answer which I feel is a much cleaner and better way to implement the functionality in an more object-oriented way — so doesn't require a hack like my original one did.
Instead it accomplishes what is needed by defining a ttk.Scale
subclass I named "Limiter
" which supports an additional keyword argument named precision
.
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
mainframe = tk.Frame(root)
# Model
class Limiter(ttk.Scale):
""" ttk.Scale sublass that limits the precision of values. """
def __init__(self, *args, **kwargs):
self.precision = kwargs.pop('precision') # Remove non-std kwarg.
self.chain = kwargs.pop('command', lambda *a: None) # Save if present.
super(Limiter, self).__init__(*args, command=self._value_changed, **kwargs)
def _value_changed(self, newvalue):
newvalue = round(float(newvalue), self.precision)
self.winfo_toplevel().globalsetvar(self.cget('variable'), (newvalue))
self.chain(newvalue) # Call user specified function.
# Sample client callback.
def callback(newvalue):
print('callback({!r})'.format(newvalue))
input_var = tk.DoubleVar(value=0.)
spin = tk.Spinbox(mainframe, textvariable=input_var, wrap=True, width=10)
slide = Limiter(mainframe, variable=input_var, orient='horizontal', length=200,
command=callback, precision=4)
spin['to'] = 1.0
spin['from'] = 0.0
spin['increment'] = 0.01
slide['to'] = 1.0
slide['from'] = 0.0
# slide['digits'] = 4
# slide['resolution'] = 0.01
# Layout
weights = {'spin': 1, 'slide': 100}
mainframe.grid_rowconfigure(0, weight=1)
mainframe.grid_columnconfigure(0, weight=weights['spin'])
mainframe.grid_columnconfigure(1, weight=weights['slide'])
spin.grid(row=0, column=0, sticky='news')
slide.grid(row=0, column=1, sticky='news')
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
mainframe.grid(row=0, column=0)
root.mainloop()
Upvotes: 6