在执行plt.show()命令后继续执行程序,而不关闭所有窗口

时间:2019-05-14 13:53:41

标签: python matplotlib interactive-mode

我知道StackOverflow中有很多类似的主题,但是没有一个答案可以解决我的特定问题。

首先,我正在尝试使用散点图绘制来自不同类的二维数据点。该程序使用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或破折号之类的其他库,但是,如果您使用的是matplotlib事件,那么在不关闭图形的情况下就无法更新图形是真的吗?我可以提供所有项目文件,但我认为,如果有解决方案,则应在这些功能内完成。

1 个答案:

答案 0 :(得分:0)

花了整整一天的时间才能找到答案,但是,答案就在这里!

我现在在plt.ion()交互模式下使用plt.show(),并使用fig.canvas.start_event_loop()和fig.canvas.stop_event_loop()命令手动进行阻止。坦白说,很难找到解决这个问题的方法,但是我们已经吸取了教训。

matplotlib figure does not continue program flow after close event triggered inside tk app