1

我编写了一个代码来注册使用ginput在绘图窗口中单击的 x 值,它工作正常并且仅在您在窗口内单击时注册。

然后,我想使用我所做的 matplotlib 小部件添加一些控制按钮,并且它们与这些方法也可以正常工作,到目前为止一切都很好......

但是,我的问题是,当我单击按钮时,按钮的坐标也由 ginput 注册,这是我不想要的。有什么办法可以防止这种情况发生吗?使按钮区域对 ginput 无效或以某种方式检测到并拒绝这些点击?

我也很高兴使用 ginput 的替代方法,我并不真正喜欢任何特定的方法(我对 python 中的 GUI 非常陌生,只想建立一个简单的例子)。

这是我的可重现示例,单击测试按钮还会在列表中添加行:-(

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

class Index:
    def test(self, event):
        print ("test")

# fake data
x=np.arange(30)
y=x**2
times=[]

fig,ax=plt.subplots()

ax.plot(x,y)
callback = Index()
buttonname=['test']
colors=['white']
idx=[0.2]
bax,buttons={},{}

# set up list of buttons.
for i,col,button in zip(idx,colors,buttonname):
  bax[button] = plt.axes([0.92, i, 0.07, 0.07])
  buttons[button] = Button(bax[button],button,color=col,hovercolor='green')
  buttons[button].on_clicked(getattr(callback,button))

# register click on plot
while True:
     pts=plt.ginput(1)
     print ("pts is",pts)
     timebegin=pts[0][0]
     times.append(timebegin)
     ax.axvline(x=timebegin)
     print ("adding",timebegin)
     print ("all ",times)
     plt.pause(0.05)

示例截图:

在此处输入图像描述

编辑:我暂时想到了一个软糖,在按钮方法中我添加了一个弹出以从时间列表中删除条目并取消绘制线条(我还将时间和线条声明为全局),它可以工作但是它很笨重而且不是很优雅,因为程序画错了线,然后又把它删除了,呃。

# in the main code I now append the ax.axvline to a list "lines"
def test(self,event):
    times.pop()
        times.pop()
        lines.pop().remove()
4

2 回答 2

1

避免该问题的一种方法是不使用按钮来终止输入,而是使用与鼠标按钮或回车键一起使用的函数mouse_stop参数(在此处ginput描述)。然后可以在绘图中添加一个文本来为用户显式地显示这个方法……交互性不如按钮,但它可以工作。

于 2021-04-27T10:05:39.650 回答
1

你可以times.append(nan)在回调中做,所以如果times[-1]nanpop()它并忽略点击。注册按钮事件有一些延迟,所以pause()在检查times[-1].

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

times = []

# on click event, append nan
class Index:
    def test(self, event):
        global times
        times.append(np.nan)
        print('test')

fig, ax = plt.subplots()
x = np.arange(30)
y = x**2
ax.plot(x, y)

callback = Index()
bax = fig.add_axes([0.92, 0.2, 0.07, 0.07])
button = Button(bax, 'Test', color='white', hovercolor='green')
button.on_clicked(callback.test)

while True:
    pts = plt.ginput(1)

    # allow callback to finish (duration may need to be adjusted)
    plt.pause(0.15)

    # ignore if newest element is nan
    if times and np.isnan(times[-1]):
        print(f'ignoring {times[-1]}')
        times.pop()
    else: # otherwise store and plot
        timebegin = pts[0][0]
        print(f'adding {timebegin}')
        times.append(timebegin)
        ax.axvline(x=timebegin)

    print(f'times = {times}')
    plt.pause(0.05)
于 2021-04-28T06:43:07.977 回答