简体   繁体   English

如何等待用户单击 IPython Notebook 中图形中的一个点?

[英]How to wait for the user to click a point in a figure in IPython notebook?

I took the following steps to setup an IPython backend in Google Colab notebook:我采取了以下步骤在 Google Colab notebook 中设置 IPython 后端:

!pip install ipympl
from google.colab import output
output.enable_custom_widget_manager()  

Then I log the (x,y) location of the user's click on a figure:然后我记录用户点击图形的 (x,y) 位置:

%matplotlib ipympl
import matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

def onclick(event):
    ix, iy = event.xdata, event.ydata
    print(ix, iy)

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

I need the code to wait here until the user selects at least one data point.我需要代码在这里等待,直到用户选择至少一个数据点。 However, the code will run if I have another command in the same notebook, for example:但是,如果我在同一个笔记本中有另一个命令,代码将运行,例如:

print ('done!')

will run without waiting for the user to pick a data point.将在不等待用户选择数据点的情况下运行。 I tried using this before:我之前尝试过使用它:

plt.waitforbuttonpress()
print('done!')

However, the compiler gets stuck at plt.waitforbuttonpress() and it doesn't let the user click the figure.但是,编译器会卡在 plt.waitforbuttonpress() 处,并且不允许用户单击图形。 Thanks for your help谢谢你的帮助

You could, instead of putting the code you want to run after a button_press_event , after the event listener, you could instead put it in the onclick function.您可以不将要运行的代码放在button_press_event之后,而是放在事件侦听器之后,而是将其放在onclick函数中。 Something like this:像这样:

%matplotlib ipympl
import matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

def onclick(event):
    ix, iy = event.xdata, event.ydata
    print(ix, iy)
    print('done!')

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

Or:要么:

%matplotlib ipympl
import matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

def after_onclick():
    print('done!')
def onclick(event):
    ix, iy = event.xdata, event.ydata
    print(ix, iy)
    after_onclick()

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

The reason for this is because mpl_connect works rather oddly (see this question ).这样做的原因是因为mpl_connect工作起来很奇怪(见这个问题)。 Instead of waiting for the event to be registered and pausing the code execution, it will run the entire file but keep the event listener open.它不会等待事件被注册并暂停代码执行,而是运行整个文件但保持事件侦听器打开。

The problem with this way is that it will run the code every time the event is registered.这种方式的问题是每次注册事件时都会运行代码。

If that is not what you want and you only want it to run once try this:如果那不是您想要的,并且您只希望它运行一次,请尝试以下操作:

%matplotlib ipympl
import matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

def after_onclick():
    print('done')
    fig.canvas.mpl_disconnect(cid)
def onclick(event):
    ix, iy = event.xdata, event.ydata
    print(ix, iy)
    after_onclick()

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

This version adds fig.canvas.mpl_disconnect(cid) so that the code will only run once.该版本添加了fig.canvas.mpl_disconnect(cid)以便代码只运行一次。

If instead of Colab you are running a normal notebook locally eg in VSCode, you can also use figure.ginput(n=1) to wait for a user click in a blocking way.如果您在本地运行普通笔记本而不是 Colab,例如在 VSCode 中,您还可以使用figure.ginput(n=1)以阻塞方式等待用户点击。

fig, ax = plt.subplots()

clicks = fig.ginput(n=1)
print('Done:', clicks)

Output:输出:

Done: [(9.070766129032256, 0.17960461218983856)]

Tested this on Jupyter + VSCode and it works, creating a window for you to click on.在 Jupyter + VSCode 上对此进行了测试并且它有效,创建了一个供您单击的窗口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM