Продолжить программу после команды plt.show (), не закрывая все окна - PullRequest
0 голосов
/ 14 мая 2019

Я знаю, что в 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 или dash, но правда ли, что вы не можете обновить рисунок, не закрывая его, если используете события matplotlib ?? Я могу предоставить все файлы проекта, но я думаю, что если есть решение, оно должно быть сделано внутри этих функций.

1 Ответ

0 голосов
/ 15 мая 2019

Потребовался целый день, чтобы найти ответ, но вот он!

Теперь я использую plt.show () в интерактивном режиме с командой plt.ion () и блокирую вручную с помощью команд fig.canvas.start_event_loop () и fig.canvas.stop_event_loop ().Чтобы быть честным, было удивительно трудно найти решение этой проблемы, но урок усвоен.

рисунок matplotlib не продолжает выполнение программы после события закрытия, вызванного внутри приложения tk

...