2014-05-16 20 views
9

Dựa trên this solution, tôi muốn tạo thanh trượt chỉ cho phép giá trị được chỉ định, thanh trượt cũng là thanh trượt riêng biệt chỉ di chuyển nếu một điểm mới được chọn (về cơ bản là phiên bản trượt của nút radio). Ví dụ: nếu tôi nhấp vào gần nhưng không chính xác trên điểm hiện tại, thanh trượt sẽ không thay đổi và cốt truyện không được vẽ lại.Thanh trượt rời trong tiện ích matplotlib

Tôi nhận được khá nhiều việc, nhưng kết quả bị trễ sau: nếu tôi nhấp xen kẽ giữa 1 và 10 trong ví dụ bên dưới, thanh trượt sẽ cập nhật chính xác, nhưng điểm di chuyển luôn nhảy về giá trị trước đó. Làm thế nào tôi có thể sửa chữa nó:

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib.widgets import Slider 

class ChangingPlot(object): 
    def __init__(self): 
     self.draw_counter = 0 
     x = np.logspace(0, 1, 10) 

     self.fig, self.ax = plt.subplots() 
     self.sliderax  = self.fig.add_axes([0.2, 0.02, 0.6, 0.03],axisbg='yellow') 
     self.slider  = DiscreteSlider(self.sliderax,'Value', 0, 10,\ 
              allowed_vals=x, valinit=x[0]) 

     self.slider.on_changed(self.update) 

     self.ax.plot(x, x, 'ro') 
     self.dot, = self.ax.plot(x[0], x[0], 'bo', markersize=18) 
     self.text = self.ax.text(2,8,str(self.draw_counter)) 

    def update(self, value): 
     self.draw_counter += 1 
     self.dot.set_data([[value],[value]]) 
     self.text.set_text(str(self.draw_counter)+' draws, value = '+str(value)) 

    def show(self): 
     plt.show() 

class DiscreteSlider(Slider): 
    """A matplotlib slider widget with discrete steps.""" 
    def __init__(self, *args, **kwargs): 
     """ 
     Identical to Slider.__init__, except for the new keyword 'allowed_vals'. 
     This keyword specifies the allowed positions of the slider 
     """ 
     self.allowed_vals = kwargs.pop('allowed_vals',None) 
     self.previous_val = kwargs['valinit'] 
     Slider.__init__(self, *args, **kwargs) 
     if self.allowed_vals==None: 
      self.allowed_vals = [self.valmin,self.valmax] 

    def set_val(self, val): 
     discrete_val = self.allowed_vals[abs(val-self.allowed_vals).argmin()] 
     xy = self.poly.xy 
     xy[2] = discrete_val, 1 
     xy[3] = discrete_val, 0 
     self.poly.xy = xy 
     self.valtext.set_text(self.valfmt % discrete_val) 
     if self.drawon: 
      self.ax.figure.canvas.draw() 
     self.val = val 
     if self.previous_val!=discrete_val: 
      self.previous_val = discrete_val 
      if not self.eventson: 
       return 
      for cid, func in self.observers.iteritems(): 
       func(discrete_val) 

p = ChangingPlot() 
p.show() 
+1

Cám ơn chia sẻ này. Tôi chỉ phải thay đổi dòng 'self.val = val' thành' self.val = discrete_val' trong hàm 'set_val'. – rerx

+0

@JohnSmith Điều này rất tiện lợi! Cũng chính xác những gì tôi (và có lẽ là những người khác) cần thiết. Bạn nên áp dụng các sửa chữa mà HYRY đề nghị và gửi này như là một yêu cầu kéo đến repo matplotlib github. – tel

Trả lời

5

dụ Rất thoải mái, Bạn cần phải gọi Figure.canvas.draw() để reflush màn hình:

def update(self, value): 
    self.draw_counter += 1 
    self.dot.set_data([[value],[value]]) 
    self.text.set_text(str(self.draw_counter)+' draws, value = '+str(value)) 
    self.fig.canvas.draw() # <--- Add this line 
+0

Tuyệt vời, đã hiệu quả. Cảm ơn! –

Các vấn đề liên quan