我知道 StackOverflow 中有很多类似的主题,但没有一个答案能解决我的具体问题。
首先,我正在尝试使用 scatter 命令将来自不同类的二维数据点绘制到图中。该程序使用 matplotlib 事件,如 button_press_event 和 motion_notify_event,我假设应该在事件命令 plt.show() 之后立即使用。主要问题是,一旦某些任务完成了事件(即标记),我想更新整个图,但 plt.show() 阻止了继续程序的选项。实际上 plt.show() 应该阻止程序,直到程序的用户决定继续。有没有办法控制这个阻塞属性?
我尝试过 plt.ion()、plt.ioff()、plt.show(block=False)、plt.draw()、plt.pause(0.001)、带有 while 循环的全局变量等,但没有成功。程序以某种方式正确工作的唯一方法是当满足所谓的前向条件时在 button_press_event 内关闭所有图形,但是如果每次更新数据点时都关闭所有图形,则不是非常用户友好的解决方案。
这是代码的一瞥:
def draw_original_figure(random_sample, random_sample_label, random_sample_image, X_train_chosen, y_train_chosen, images_train_chosen, classes, accuracy, embedding, model, h=0.05):
global points1, im1, s_im1, xybox, x1, y1, fig1, classes1, points_to_plot, y_train_chosen1, accuracy1, random_sample1, embedding1, y_train_chosen1, h1, random_sample_label1, result1
fig1 = plt.gcf()
.
.
.
original_figure_plot()
fig1.canvas.mpl_connect('motion_notify_event', hover)
fig1.canvas.mpl_connect('button_press_event', click)
plt.show()
def hover(event):
# if the mouse is over the scatter points
if points1.contains(event)[0]:
# find out the index within the array from the event
inds = points1.contains(event)[1]["ind"]
ind = inds[0]
# get the figure size
w,h = fig1.get_size_inches()*fig1.dpi
ws = (event.x > w/2.)*-1 + (event.x <= w/2.)
hs = (event.y > h/2.)*-1 + (event.y <= h/2.)
# if event occurs in the top or right quadrant of the figure,
# change the annotation box position relative to mouse.
ab1.xybox = (xybox[0]*ws, xybox[1]*hs)
# make annotation box visible
ab1.set_visible(True)
# place it at the position of the hovered scatter point
ab1.xy =(x1[ind], y1[ind])
# set the image corresponding to that point
im1.set_data(s_im1[ind,:,:])
else:
#if the mouse is not over a scatter point
ab1.set_visible(False)
fig1.canvas.draw_idle()
def click(event):
# if the mouse is over the scatter points
if points1.contains(event)[0]:
# find out the index within the array from the event
inds = points1.contains(event)[1]["ind"]
ind = inds[0]
# if one specific point is chosen
if ind == len(x1)-1:
plt.scatter(x1[ind], y1[ind], s=25, marker='x', c='#556B2F')
q = question(True, ind)
# do nothing
if q == "":
original_figure_plot()
# quit the program
elif q == "q":
exit()
# continue the program without updating labels
elif q == "n":
result1 = copy.deepcopy(y_train_chosen1)
plt.close("all")
# continue the program after labels are updated
else:
result1 = copy.deepcopy(y_train_chosen1)
result1 = np.append(result1, [int(q)], axis=0)
plt.close("all")
else:
# if anyone else point is chosen
plt.scatter(x1[ind], y1[ind], s=8, c='k')
q = question(False, ind)
# do nothing
if q == "":
original_figure_plot()
# quit the program
elif q == "q":
exit()
# update labels
else:
y_train_chosen1[ind] = int(q)
original_figure_plot()
fig1.canvas.draw_idle()
可能最好使用其他库,例如 plotly 或 dash 但是如果您使用 matplotlib 事件,您真的不能在不关闭它的情况下更新图形吗?我可以提供所有项目文件,但我认为如果有解决方案,应该在这些函数内部完成。