Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如果图例位于轴之外,则在鼠标单击时注册双事件_Python_Python 2.7_Matplotlib - Fatal编程技术网

Python 如果图例位于轴之外,则在鼠标单击时注册双事件

Python 如果图例位于轴之外,则在鼠标单击时注册双事件,python,python-2.7,matplotlib,Python,Python 2.7,Matplotlib,我必须在一个绘图中绘制多个数据集。能够突出显示一个或多个图以进行比较非常有用。为此,每当直接选择一条线,或通过单击图例中的相应条目,我将在“:”(背景图)和“-”(高亮显示图)之间切换绘图的线条样式 在我尝试使用bbox\u to\u锚定将图例移到轴外之前,这一切都非常有效。在此之后,在图例线上单击一次鼠标会连续触发两次单击事件,从而取消切换效果 如何将图例放置在轴外,同时保留拾取事件的正确行为 再现问题的简化代码(单击绘图线可在“高亮显示”和“未高亮显示”之间切换,而单击图例线可在返回前一状态

我必须在一个绘图中绘制多个数据集。能够突出显示一个或多个图以进行比较非常有用。为此,每当直接选择一条线,或通过单击图例中的相应条目,我将在
“:”
(背景图)和
“-”
(高亮显示图)之间切换绘图的线条样式

在我尝试使用
bbox\u to\u锚定
将图例移到轴外之前,这一切都非常有效。在此之后,在图例线上单击一次鼠标会连续触发两次单击事件,从而取消切换效果

如何将图例放置在轴外,同时保留拾取事件的正确行为

再现问题的简化代码(单击绘图线可在“高亮显示”和“未高亮显示”之间切换,而单击图例线可在返回前一状态之前短暂切换绘图线):

导入pylab
进口numpy
#创建用于打印的数据
t=numpy.linspace(0,1.0100)
a=numpy.sin(2*numpy.pi*t)
#设置数字
图=pylab.图()
ax=pylab.子批次(111)
#情节图
行=[]
对于范围(5)中的i:
line=ax.plot(t,(i+1)*a,linestyle=':',picker=5,label='line%d'(i+1))
行。追加(行[0])#保存打印行
#创建图例
支腿=轴。图例(bbox_至_锚=(1.01,1),loc=2)未按预期工作
#leg=ax.legend()#有效!!
#获取图例行
leglines=leg.get_lines()
#设置图例线的事件
对于腿部线条中的线条:
线。设置_选择器(5)
#在图例线和打印线之间创建双向映射
line2leg=dict(拉链(线+腿线,腿线+线))
#定义事件函数
def onpick(事件):
thisline=event.artist
如果thisline.get_linestyle()==':':
打印“:->-”#用于调试
thisline.set_线条样式('-'))
line2leg[thisline]。设置_线型('-'))
其他:
打印“-->:”#用于调试
thisline.set_linestyle(“:”)
line2leg[thisline]。设置线条样式(“:”)
图canvas.draw()
#连接事件函数
图canvas.mpl\u connect('pick\u event',onpick)
pylab.show()

如果你是猴子补丁
艺术家。用以下选项选择:

matplotlib.artist.Artist.orig_pick = matplotlib.artist.Artist.pick
def nu_pick(self, me):
    print self
    matplotlib.artist.Artist.orig_pick(self, me)

matplotlib.artist.Artist.pick = nu_pick
您可以查看艺术家如何在拾取事件中重现。(每个
Artist
对象对其自身和所有子对象调用
pick
)。出于我不理解的原因,图例的绘图区域中每一行都有两个副本(当它位于内部和外部时,其行为会有所不同)

黑客解决方案的一种方法是只计算腿线被击中的次数,只切换奇数:

import pylab
import numpy

# Create data for plotting
t = numpy.linspace(0, 1.0, 100) 
a = numpy.sin(2*numpy.pi*t)

# Set up figure
fig = pylab.figure()
ax = pylab.subplot(111)

# Plot figures    
lines = []    
for i in range(5):
    line = ax.plot(t, (i+1)*a, linestyle=':', picker=5, label='line%d'%(i+1)) 
    lines.append(line[0]) # Save plot lines

# Create legend
leg = ax.legend(bbox_to_anchor=(1.01, 1), loc=2) # Does not work as expected
#leg = ax.legend() # Works!!

# Get legend lines
leglines = leg.get_lines() 
# Set event for legend lines
for line in leglines:
    line.set_picker(5)

# Create a 2 way mapping between legend lines <-> plot lines    
line2leg = dict(zip(lines+leglines, leglines+lines))
count_dict = dict((l, 0) for l in lines )
# Define event function
def onpick(event):
    thisline = event.artist
    print event
    print thisline
    if thisline in lines:
        print 'lines'
        count_dict[thisline] = 0
    elif thisline in leglines:
        print 'leglines'
        thisline = line2leg[thisline]
        count_dict[thisline] += 1
    print 'added'
    if (count_dict[thisline] % 2) == 1:
        print count_dict[thisline]
        return
    print 'tested'
    if thisline.get_linestyle()==':':
        print ": -> -" # For debugging
        thisline.set_linestyle('-')
        line2leg[thisline].set_linestyle('-')
    else:
        print "- -> :" # For debugging
        thisline.set_linestyle(':')
        line2leg[thisline].set_linestyle(':')
    fig.canvas.draw()

# connect event function    
fig.canvas.mpl_connect('pick_event', onpick)
pylab.show()
导入pylab
进口numpy
#创建用于打印的数据
t=numpy.linspace(0,1.0100)
a=numpy.sin(2*numpy.pi*t)
#设置数字
图=pylab.图()
ax=pylab.子批次(111)
#情节图
行=[]
对于范围(5)中的i:
line=ax.plot(t,(i+1)*a,linestyle=':',picker=5,label='line%d'(i+1))
行。追加(行[0])#保存打印行
#创建图例
支腿=轴。图例(bbox_至_锚=(1.01,1),loc=2)未按预期工作
#leg=ax.legend()#有效!!
#获取图例行
leglines=leg.get_lines()
#设置图例线的事件
对于腿部线条中的线条:
线。设置_选择器(5)
#在图例线和打印线之间创建双向映射
line2leg=dict(拉链(线+腿线,腿线+线))
count_dict=dict((l,0)表示行中的l)
#定义事件函数
def onpick(事件):
thisline=event.artist
打印事件
打印这行
如果此行在行中:
打印“行”
计数dict[thisline]=0
elif此行以leglines表示:
打印“leglines”
thisline=line2leg[thisline]
计数dict[thisline]+=1
打印“已添加”
如果(计数[thisline]%2)==1:
打印计数记录[此行]
返回
打印“已测试”
如果thisline.get_linestyle()==':':
打印“:->-”#用于调试
thisline.set_线条样式('-'))
line2leg[thisline]。设置_线型('-'))
其他:
打印“-->:”#用于调试
thisline.set_linestyle(“:”)
line2leg[thisline]。设置线条样式(“:”)
图canvas.draw()
#连接事件函数
图canvas.mpl\u connect('pick\u event',onpick)
pylab.show()
(我把我所有的去窃听声明都留在了里面)


非常确定这是一个bug,如果你不想在github上创建问题,我会的。

我深入到传奇艺术家中发现,当传奇设置了bbox_to_锚定时,传奇的子树中有两条传奇线

我用我的解决方案询问了这个问题,在那里我观察了一个新的mouseevent,并跟踪了已经被我的回调处理过的艺术家

如果有人认为有一种更优雅的方式来处理这个“功能”,我会征求意见


我不确定这是一个错误。但是,在图例中,子行保存在.lines属性中,并且深入到packing box数据结构中,这似乎是独一无二的—get_children方法可以找到这两个。幸运的是,它们是相同的对象,而不是副本,因此我可以检查是否有一行已经处理。

另一种类似于tcaswell的解决方案计数事件的方法。只有3行添加到原始。它使用python的函数属性

def onpick(event):
    if onpick.count % 2 == 0:    #### LINE ADDED ####  
        # on the pick event, find the orig line corresponding to the
        # legend proxy line, and toggle the visibility
        legline = event.artist
        origline = lined[legline]
        vis = not origline.get_visible()
        origline.set_visible(vis)
        # Change the alpha on the line in the legend so we can see what lines
        # have been toggled
        if vis:
            legline.set_alpha(1.0)
        else:
            legline.set_alpha(0.2)
        fig.canvas.draw()
    onpick.count += 1    #### LINE ADDED ####

onpick.count = 0    #### LINE ADDED ####

这很奇怪。看起来同一个pick事件被处理了两次,而不是生成了两个事件,这让我觉得这是一个bug@tcaswell如何判断它是相同的拾取事件还是生成了两个相同类型的事件?如果在
onpick
中添加
print event
行,则它们在打印时具有相同的内存地址,我会让这个问题继续讨论一段时间,看看是否有其他人可以为github上的discussionCreated问题添加有用的内容。我认为这是legend创建代码中的一个bug。它应该只需要艺术家画一次就可以了
def onpick(event):
    if onpick.count % 2 == 0:    #### LINE ADDED ####  
        # on the pick event, find the orig line corresponding to the
        # legend proxy line, and toggle the visibility
        legline = event.artist
        origline = lined[legline]
        vis = not origline.get_visible()
        origline.set_visible(vis)
        # Change the alpha on the line in the legend so we can see what lines
        # have been toggled
        if vis:
            legline.set_alpha(1.0)
        else:
            legline.set_alpha(0.2)
        fig.canvas.draw()
    onpick.count += 1    #### LINE ADDED ####

onpick.count = 0    #### LINE ADDED ####