Using Matplotlib Slider and key_release_event concurrently

自古美人都是妖i 提交于 2019-12-11 03:19:48

问题


I am using Matplotlib (with 'tkAgg' backend) to display an image from a sequence of images.

I have a Slider widget setup to allow me to scroll through the image sequence - moving the slider changes which image is being displayed.

I also have an mpl_connect set to listen for key_relese_events specifically from the left and right arrow keys which calls the same on_change() method to either advance to the next image or show the previous image.

Both of these are working fine independent of eachother: when the program opens the slider is set to show to first image in the stack. I can then move the slider back and forth to show different images as well as press right or left to move back or forth by one image.

My only qualm/question is that when I use the arrow keys to advance images the slider value doesn't change at all. So if you advance say 20 images forward by pressing right arrow 20 times, the correct image will be displayed and the plot titles change appropriately however the slider still shows the initial value or whatever value it was at when you pressed the arrow keys.

Is there any way to set the value of the Slider widget and have the screen update to show the correct value. I believe (yet to fully test it) that you can access the value of the slider as myslider.val - however setting that value seems to have no link to what is being displayed graphically even after calling matplotlib.pyplot.draw()

TL;DR Is there a way to have the Slider value that is displayed in the figure be tied to a local variable so that when that variable changes (new image being displayed) the Slider will change accordingly?

This is really only for aesthetic value as I previously mentioned that both of my controls for advancing the images work independent of eachother

Here are some snippets of my code (in no particular order) cut form my source. I hope its clear enough what the functions are doing-

def on_change(val):
    """
    This function updates the LEEM image based on the slider value, val
    This function is also called to update the image when an arrow key release is detected
    """
    global curimg

    curimg = energy_to_filenumber(round(val, 1))
    img = all_dat[0:imheight-1, 0:imwidth-1,
                  curimg]
    leemax.set_title("LEEM Image: " + str(elist[
        int(energy_to_filenumber(round(val, 1)))]) + ' eV')
    leemax.imshow(img, cmap=cm.Greys_r)
    pylab.draw()

def arrow_key_image_control(event):
    """
    This function takes an event from an mpl_connection
    and listens for key release events specifically from
    the keyboard arrow keys (left/right) and uses this
    input to advance/reverse to the next/previous image.
    """
    global curimg

    minindex = 0
    maxindex = all_dat.shape[2] - 1
    if event.key == 'left':
        if curimg - 1 >= minindex:
            curimg -= 1
            on_change(filenumber_to_energy(curimg))

        else:
            pass
    elif event.key == 'right':
        if curimg + 1 <= maxindex:
            curimg += 1
            on_change(filenumber_to_energy(curimg))

        else:
            pass
    else:
        pass


sld_ax = fig.add_axes([0.2, 0.025, 0.75, 0.02])
imsld = Slider(sld_ax, "Electron Energy",
                   elist[0], elist[len(elist)-1], elist[0], valfmt='%1.1f')
imsld.on_changed(on_change)
id2 = fig.canvas.mpl_connect('key_release_event', arrow_key_image_control)

回答1:


Thanks to @tcaswell for the comment with the solution

There is an undocumented method in the Slider class slider.set_val() which accomplishes exactly what I needed - it sets the slider values to a given value and then updates the figure containing the slider so the change is visible.



来源:https://stackoverflow.com/questions/27871206/using-matplotlib-slider-and-key-release-event-concurrently

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!