<p>由于缩放小部件命令回调函数在缩放小部件发生更改时被调用,因此回调必须“关闭”,因为小部件被设置为避免调用回调函数的无限序列,因为小部件1的更改会影响小部件2&;3. </p>
<pre><code>import tkinter as tk
root = tk.Tk()
top_frame = tk.Frame(root, padx = 10, pady = 10 ).grid()
root.title('3 Scales')
top_frame = tk.Frame(root, padx = 10, pady = 10 ).grid()
# Column headers
for col, txt in enumerate([ 'Note 1', 'Silence', 'Sustain' ]):
tk.Label( text = txt).grid( row = 0, column = col )
# Create & grid Scale widgets
note1_weight = tk.Scale(top_frame, from_= 1, to= 0, resolution = 0.01 )
note1_weight.grid(column=0, row=2)
silence_weight = tk.Scale(top_frame, from_= 1, to= 0, resolution = 0.01 )
silence_weight.grid(column=1, row=2)
sustain_weight = tk.Scale(top_frame, from_= 1, to= 0, resolution= 0.01 )
sustain_weight.grid(column=2, row=2)
# Initialise the widgets
note1_weight.set(0.34)
silence_weight.set(0.33)
sustain_weight.set(0.33)
# Container for the command functions
# Filled after make_command is defined.
command_func = [ 0 ] * 3
def commands_activate():
""" makes all the command functions active """
note1_weight.config( command = command_func[0] )
silence_weight.config( command = command_func[1] )
sustain_weight.config( command = command_func[2] )
def commands_deactivate():
""" Stops all the command functions being called """
note1_weight.config( command = "" )
silence_weight.config( command = "" )
sustain_weight.config( command = "" )
def make_command( other0, other1 ):
""" Generates a command function thar updates the 'other' two Scale widgets.
Using the closure avoids writing 3 almost identcal functions
"""
def cmd( pos ):
""" A command callback function which updates widgets
other0 and other1 as the current widget changes.
"""
commands_deactivate()
# Stop the .set(..) in this function triggering further calls to cmd
########################################################################
# This section of code performs the sum == 1.0 calculations
# It can be changed to allocate the diff as required.
# Here it prorates the difference from 1.0 across the other two widgets
diff = 1.0 - float(pos)
v0 = max( other0.get(), 0.0001) # If both v0 and v1 == 0.0 there's no prorating
v1 = max( other1.get(), 0.0001) # so ensure v0 and v1 are never precisely zero.
fact = diff / ( v0 + v1 )
other0.set( v0 * fact )
other1.set( v1 * fact )
########################################################################
commands_activate()
# Then reactivate the commands
return cmd
# Generate the three command functions
command_func[0] = make_command( silence_weight, sustain_weight )
command_func[1] = make_command( note1_weight, sustain_weight )
command_func[2] = make_command( note1_weight, silence_weight )
# Activate the command functions before mainloop
commands_activate()
root.mainloop()
</code></pre>