【问题标题】:Problem with plotting a dot on click with matplotlib使用 matplotlib 单击时绘制点的问题
【发布时间】:2021-06-07 17:01:43
【问题描述】:

我刚开始学习 python 和交互式绘图,欢迎任何帮助。

此代码的目的是单击十个按钮之一以选择 -5 和 5 之间的值,然后通过单击主轴上的任意位置来显示该值,然后从这些点生成电场图。问题是,当我单击任何按钮时,图表中间会绘制一个点。 如果我正确理解发生了什么,onclick 函数会将每个按钮的轴解释为主轴的一部分。 有人可以帮我解决这个问题吗?


import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.widgets import Button

fig, ax= plt.subplots(figsize=(8,8))

axButton1=plt.axes([0,0.90,0.1,0.07])
btn1= Button(axButton1,label='-5')

axButton2=plt.axes([0.1,0.90,0.1,0.07])
btn2= Button(axButton2,label='-4')

axButton3=plt.axes([0.2,0.90,0.1,0.07])
btn3= Button(axButton3,label='-3')

axButton4=plt.axes([0.3,0.90,0.1,0.07])
btn4= Button(axButton4,label='-2')

axButton5=plt.axes([0.4,0.90,0.1,0.07])
btn5= Button(axButton5,label='-1')

axButton6=plt.axes([0.5,0.90,0.1,0.07])
btn6= Button(axButton6,label='1')

axButton7=plt.axes([0.6,0.90,0.1,0.07])
btn7= Button(axButton7,label='2')

axButton8=plt.axes([0.7,0.90,0.1,0.07])
btn8= Button(axButton8,label='3')

axButton9=plt.axes([0.8,0.90,0.1,0.07])
btn9= Button(axButton9,label='4')

axButton10=plt.axes([0.9,0.90,0.1,0.07])
btn10= Button(axButton10,label='5')

q=0

def neg5(event):
    global q
    q=-5
    
btn1.on_clicked(neg5)

def neg4(event):
    global q
    q=-4
    
btn2.on_clicked(neg4)

def neg3(event):
    global q
    q=-3
    
btn3.on_clicked(neg3)

def neg2(event):
    global q
    q=-2
    
btn4.on_clicked(neg2)

def neg1(event):
    global q
    q=-1
    
btn5.on_clicked(neg1)

def pos1(event):
    global q
    q=1
    
btn6.on_clicked(pos1)

def pos2(event):
    global q
    q=2
    
btn7.on_clicked(pos2)

def pos3(event):
    global q
    q=3
    
btn8.on_clicked(pos3)

def pos4(event):
    global q
    q=4
    
btn9.on_clicked(pos4)

def pos5(event):
    global q
    q=5
    
btn10.on_clicked(pos5)


plt.subplots_adjust(top=0.77, bottom=0.05)
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])

charges=[]

def onclick(event):
    global charges
    M=(event.xdata, event.ydata)
    print('button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
          (event.button, event.x, event.y, event.xdata, event.ydata))
    charges.append(M)
    print(charges)
    ax.add_artist(mpl.patches.Circle(M, 0.3, color='r', ec='black', lw=1.5))
    ax.text(event.xdata,event.ydata,str(q), size='20', color='w', zorder=2, horizontalalignment = 'center', verticalalignment = 'center')
    fig.canvas.draw()
    


cid = fig.canvas.mpl_connect('button_press_event', onclick)

plt.show()

【问题讨论】:

  • 请同时添加您的导入。像这样,很难让它为其他人运行。
  • 哦,是的,对不起,我忘了

标签: python matplotlib button plot


【解决方案1】:

您可以使用event.inaxes 来检查事件的来源。 这是一个示例实施。我还使用工厂稍微清理了q setter 函数。类似的东西也适用于按钮的创建,然后您可以循环执行所有操作而无需太多重复。我鼓励你尝试一下。

import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.widgets import Button

fig, ax= plt.subplots(figsize=(8,8))

axButton1=plt.axes([0,0.90,0.1,0.07])
btn1= Button(axButton1,label='-5')

axButton2=plt.axes([0.1,0.90,0.1,0.07])
btn2= Button(axButton2,label='-4')

axButton3=plt.axes([0.2,0.90,0.1,0.07])
btn3= Button(axButton3,label='-3')

axButton4=plt.axes([0.3,0.90,0.1,0.07])
btn4= Button(axButton4,label='-2')

axButton5=plt.axes([0.4,0.90,0.1,0.07])
btn5= Button(axButton5,label='-1')

axButton6=plt.axes([0.5,0.90,0.1,0.07])
btn6= Button(axButton6,label='1')

axButton7=plt.axes([0.6,0.90,0.1,0.07])
btn7= Button(axButton7,label='2')

axButton8=plt.axes([0.7,0.90,0.1,0.07])
btn8= Button(axButton8,label='3')

axButton9=plt.axes([0.8,0.90,0.1,0.07])
btn9= Button(axButton9,label='4')

axButton10=plt.axes([0.9,0.90,0.1,0.07])
btn10= Button(axButton10,label='5')

q=0

#generator function for q setters
def valueSetterFuncGen(val): 
    def func(event):
        global q
        q = val
    return func

btn1.on_clicked(valueSetterFuncGen(-5))
btn2.on_clicked(valueSetterFuncGen(-4))
btn3.on_clicked(valueSetterFuncGen(-3))
btn4.on_clicked(valueSetterFuncGen(-2))
btn5.on_clicked(valueSetterFuncGen(-1))
btn6.on_clicked(valueSetterFuncGen(1))
btn7.on_clicked(valueSetterFuncGen(2))
btn8.on_clicked(valueSetterFuncGen(3))
btn9.on_clicked(valueSetterFuncGen(4))
btn10.on_clicked(valueSetterFuncGen(5))


plt.subplots_adjust(top=0.77, bottom=0.05)
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])

charges=[]

def onclick(event):
    if event.inaxes==ax:
        global charges
        M=(event.xdata, event.ydata)
        print('button=%d, x=%d, y=%d, xdata=%f, ydata=%f, ax = %s' %
              (event.button, event.x, event.y, event.xdata, event.ydata, event.inaxes==ax))
        charges.append(M)
        print(charges)
        ax.add_artist(mpl.patches.Circle(M, 0.3, color='r', ec='black', lw=1.5))
        ax.text(event.xdata,event.ydata,str(q), size='20', color='w', zorder=2, horizontalalignment = 'center', verticalalignment = 'center')
        fig.canvas.draw()
    


cid = fig.canvas.mpl_connect('button_press_event', onclick)

plt.show()

--- 剧透 ---

解决办法

import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.widgets import Button

fig, ax= plt.subplots(figsize=(8,8))


#factory function for q setters
def valueSetterFuncGen(val): 
    def func(event):
        global q
        q = val
    return func


btns = []
for i in range(10):
    axButton_=plt.axes([i/10.,0.90,0.1,0.07])
    l = ''
    if i-5 < 0:
        l = int(i-5)
    else:
        l = int(i-4)
    # if we are already looping, a button factory would not make things easier 
    btn_= Button(axButton_,label=str(l))
    btn_.on_clicked(valueSetterFuncGen(l))
    btns.append(btn_)

plt.subplots_adjust(top=0.77, bottom=0.05)
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
q=0
charges=[]

def onclick(event):
    if event.inaxes==ax:
        global charges
        M=(event.xdata, event.ydata)
        print('button=%d, x=%d, y=%d, xdata=%f, ydata=%f, ax = %s' %
              (event.button, event.x, event.y, event.xdata, event.ydata, event.inaxes==ax))
        charges.append(M)
        print(charges)
        ax.add_artist(mpl.patches.Circle(M, 0.3, color='r', ec='black', lw=1.5))
        ax.text(event.xdata,event.ydata,str(q), size='20', color='w', zorder=2, horizontalalignment = 'center', verticalalignment = 'center')
        fig.canvas.draw()
    


cid = fig.canvas.mpl_connect('button_press_event', onclick)

plt.show()

【讨论】:

  • 感谢您的解决方案!实际上,使用生成器生成 q 值要方便得多,我会尝试对按钮执行相同的操作。感谢您的帮助,祝您有美好的一天!
【解决方案2】:

欢迎,欢迎使用 Python。

我确定我没有最好的答案,因为我没有使用 canvas.mpl_connect,但我相信我有一个适合你的解决方案。

将所有 onclick(events) 放在 if 语句下,以便单击按钮(子图,而不是主轴)不会触发所有内容:

def onclick(event):
    if issubclass(event.inaxes.__class__, mpl.axes.SubplotBase):
        global charges
        M=(event.xdata, event.ydata)
        print('button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
              (event.button, event.x, event.y, event.xdata, event.ydata))
        charges.append(M)
        print(charges)
        ax.add_artist( mpl.patches.Circle(M, 0.3, color='r', ec='black', lw=1.5) )
        ax.text(event.xdata,event.ydata,str(q), size='20', color='w', zorder=2, horizontalalignment = 'center', verticalalignment = 'center')
        fig.canvas.draw()

【讨论】:

  • 非常感谢,这正是我所需要的。祝你有美好的一天!
猜你喜欢
  • 1970-01-01
  • 2017-06-07
  • 2020-07-28
  • 1970-01-01
  • 2019-06-26
  • 1970-01-01
  • 2022-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多