2

Inside the call-back associated with a matplotlib.widgets.Slider instance, I want to modify the Slider valmin, valmax and val attributes, and then re-draw the Slider. When I try to re-draw it, nothing happens.

Before the call-back completes, I call plt.draw() and, while the rest of the plot is correctly updated, the Slider looks the same as before. I also tried calling draw() on the Axes of the Slider, and again no visible change.

How can I force a re-draw of the Slider instance after changing its attributes?

Thansk!

UPDATE

Here a small program that demonstrates the issue (with a crude dialog). The wanted behavior is that by clicking on a different value of the radio button, the slider changes range of values, current value and label. What happens instead is that when clicking on "Gradient" the slider stops responding (cannot be dragged anymore), and when clicking on "Gradient" or "Channel" the slider is not updated, in spite of a call to plt.draw()

from matplotlib import pyplot as plt
from matplotlib import gridspec
from matplotlib.widgets import Slider, RadioButtons

# Set the grid
grid = gridspec.GridSpec(2, 1, height_ratios=[1, 2])

# Plot the sliders
axes_slider = plt.subplot(grid[0, 0])
slider = Slider(axes_slider, 'Channel', valmin=0, valmax=255, valinit=128)

# Plot the radio buttons
axes_button = plt.subplot(grid[1, 0])
button = RadioButtons(axes_button, ('Gradient', 'Channel'), active=1)

plt.tight_layout(h_pad=0)
plt.subplots_adjust(left=.2, right=.9)

def update(_):
    take_gradient = True if button.value_selected == 'Gradient' else False
    if take_gradient:
        slider.valmin = -1
        slider.valmax = 1
        slider.val = 0
        slider.label= 'Gradient'
        slider.valinit = 0
    else:
        slider.valmin = 0
        slider.valmax = 255
        slider.val = 128
        slider.label = 'Channel'
        slider.valinit = 128
    plt.draw()

# Register call-backs with widgets
slider.on_changed(update)
button.on_clicked(update)

plt.show()
4

1 回答 1

2

滑块本身是一个托管和管理一些参数的类。它没有绘制方法。

也就是说,仅设置滑块的参数是不够的,您还需要更新滑块所在的轴。最后,这一切都归结为执行滑块正在执行初始化的步骤,因此您可以简单地调用silder的__init__函数。

我强烈建议使用两种不同的功能,一种用于更改单击按钮时调用的滑块,另一种用于调整滑块值时应该发生的事情。

这是一个工作示例:

from matplotlib import pyplot as plt
from matplotlib import gridspec
from matplotlib.widgets import Slider, RadioButtons

# Set the grid
grid = gridspec.GridSpec(2, 1, height_ratios=[1, 2])

# Plot the sliders
axes_slider = plt.subplot(grid[0, 0])
slider = Slider(axes_slider, 'Channel', valmin=0, valmax=255, valinit=128)

# Plot the radio buttons
axes_button = plt.subplot(grid[1, 0])
button = RadioButtons(axes_button, ('Gradient', 'Channel'), active=1)

plt.tight_layout(h_pad=0)
plt.subplots_adjust(left=.2, right=.9)

def buttonupdate(val):
    if val == "Gradient":
        axes_slider.clear()
        slider.__init__(axes_slider, 'Gradient', valmin=-1, valmax=1, valinit=0)        
    else:
        axes_slider.clear()
        slider.__init__(axes_slider, 'Channel', valmin=0, valmax=255, valinit=128) 
    plt.gcf().canvas.draw_idle()

def sliderupdate(val):
    if slider.label.get_text() == 'Gradient':
        #do something depending on gradient value
        pass
    else:
        #do something depending on channel value
        pass

# Register call-backs with widgets
slider.on_changed(sliderupdate)
button.on_clicked(buttonupdate)

plt.show()
于 2017-04-22T10:08:59.430 回答