根据来自另一个滑块matplotlib

时间:2019-12-13 19:40:09

标签: python matplotlib widget

我绘制一条原点为(0,0)且第二点为(10,yval)的线,并使用滑块定义一条线的角度,并以此角度计算一个新的“ yval”并重新绘制线。效果很好。

我添加了第二个滑块,以便用户可以定义“角度”(第一个滑块)或“ yval”(第二个滑块)。当一个或另一个值更改时,我希望另一个滑块的值更改。

部分有效。如果我先移动角度滑块,一切都会很棒。但是,当我尝试移动yval滑块时,它冻结了。如果我重新运行代码并首先移动yval滑块,那么一切都很好。但是,当我尝试移动角度滑块时,它再次冻结。

这让我感到很困惑,感谢您能提供的任何帮助。

谢谢。

我的代码是:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation
from matplotlib.widgets import Slider  # import the Slider widget

## def update(val): 
def update(val):
    global old_Angle, old_yval

# Define incoming values
    new_Angle = svalue_a.val
    new_yval = svalue_y.val
    Bx = 10

# Determine which slider changed
    if (new_Angle != old_Angle):
        old_Angle = new_Angle
        By = 10*np.tan(new_Angle * torad)
        # Reseat the yval slider due to change in angle slider
        slider2_ax.clear() #Clear the axis
        svalue_y.__init__(slider2_ax, 'yval', 0, 25, valinit=By)
    else:
        old_yval = new_yval
        new_Angle = np.arctan(new_yval/10)/torad
        By = new_yval
        # Reseat the angle slider due to change in yval slider
        slider_ax.clear() #Clear the axis
        svalue_a.__init__(slider_ax, 'angle', 20, 60, valinit=new_Angle)

    line.set_xdata((0, Bx))
    line.set_ydata((0, By))

    old_yval = By
    old_Angle = new_Angle

    fig.canvas.draw_idle()      

#Define and plot the triangle
def plot_triangle():
    plt.axes() #Select the main axis
    WAngle = 20.
    xmax = 10
    ymax = 10
    x1 = 0
    y1 = 0
    x2 = xmax
    y2 = y1
    x3 = xmax
    y3 = x3*np.tan(WAngle * torad)
    points = [[x1,y1],[x2,y2],[x3,y3]]
    plt.xlim(x1,xmax)
    plt.ylim(y1,ymax)
    polygon = plt.Polygon(points, facecolor='0.9', edgecolor='0.5')
    plt.gca().add_patch(polygon)

# ############################################
#            Main program
# ############################################
fig, main_ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)

#Some constants
torad = np.pi/180

# Initial values
old_Angle = 30

# Plot a triangle
plttri = plot_triangle()

#Now define the line and plot it
Bx = 10
By = Bx*np.tan(old_Angle * torad)
old_yval = By
line = plt.Line2D((0,Bx),(0,By))  #(x1,x2),(y1,y2)  
plt.gca().add_line(line)    

# Slider info
#[left, bottom, wide, high]
slider_ax = plt.axes([0.25, 0.15, .5, .03])
slider2_ax = plt.axes([0.25, 0.10, .5, .03])    
svalue_a = Slider(slider_ax, 'angle', 20, 60, valinit=old_Angle)    
svalue_y = Slider(slider2_ax, 'yval', 5, 17, valinit=old_yval)

svalue_a.on_changed(update)
svalue_y.on_changed(update)

plt.show()

2 个答案:

答案 0 :(得分:0)

一旦我在函数本身中向函数update添加了函数调用,它就可以正常工作。

def update(val):
global old_Angle, old_yval


new_Angle = svalue_a.val
new_yval = svalue_y.val
Bx = 10


if (old_yval != new_yval) : 
    old_yval = new_yval
    new_Angle = np.arctan(new_yval/10)/torad
    By = new_yval
    # Reseat the angle slider due to change in yval slider
    slider_ax.clear() #Clear the axis
    svalue_a.__init__(slider_ax, 'angle', 20, 60, valinit=new_Angle)

if (old_Angle != new_Angle):
    old_Angle = new_Angle
    By = 10*np.tan(new_Angle * torad)
    # Reseat the yval slider due to change in angle slider
    slider2_ax.clear() #Clear the axis
    svalue_y.__init__(slider2_ax, 'yval', 0, 25, valinit=By)


line.set_xdata((0, Bx))
line.set_ydata((0, By))

old_yval = By
old_Angle = new_Angle

fig.canvas.draw_idle()

svalue_a.on_changed(update)  #THIS LINE
svalue_y.on_changed(update)  #AND THIS LINE

使用此行代码可以实现所需的功能,但是关于滑块的外观还有其他一些小问题,这不应该成为问题。

此外,您不需要使用变量plttri来存储函数plot_triangle()的返回值,因为该函数没有返回值。

编辑:我还要重新考虑对两个基本上做相同事情的滑块的需要。我不知道您的特定用例,也不知道为什么要用它来做,但值得研究。

答案 1 :(得分:0)

与其重新初始化滑块,不如尝试更改init的值并重置滑块。那对我有用。

################################################
svalue_y.valinit = By
svalue_y.reset()
##################################################        
#slider2_ax.clear() #Clear the axis
#svalue_y.__init__(slider2_ax, 'yval', 0, 25, valinit=By)
    else:
old_yval = new_yval
new_Angle = np.arctan(new_yval/10)/torad
By = new_yval
# Reseat the angle slider due to change in yval slider
##################################################        
svalue_a.valinit = new_Angle
svalue_a.reset()
##################################################        
#slider_ax.clear() #Clear the axis
#svalue_a.__init__(slider_ax, 'angle', 20, 60, valinit=new_Angle)