Подождите, пока пользователь не нажмет кнопку на рисунке Matplotlib, чтобы продолжить программу - PullRequest
1 голос
/ 26 мая 2019

Я работаю над интерактивной программой, которая ставит точки на фигуре Matplotlib. Программа позволяет пользователю перемещать эти точки с их исходных позиций с помощью мыши. Когда пользователь доволен новыми точками, программа продолжается.

Поскольку мой программный проект большой и охватывает гораздо больше, я разделил его на несколько файлов. Вот они:

  • functions.py
import numpy as np
import settings

def update(val):

    settings.ct_plt.set_xdata(settings.x)
    settings.ct_plt.set_ydata(settings.y)

    settings.f_img.canvas.draw_idle()

def reset(event):

    settings.x = settings.x0.copy()
    settings.y = settings.y0.copy()

    settings.ct_plt.set_xdata(settings.x)
    settings.ct_plt.set_ydata(settings.y)

    settings.f_img.canvas.draw_idle()

def button_press_callback(event):
    'whenever a mouse button is pressed'

    if event.inaxes is None:
        return
    if event.button != 1:
        return

    settings.pind = get_ind_under_point(event)

def button_release_callback(event):
    'whenever a mouse button is released'

    if event.button != 1:
        return

    settings.pind = None

def get_ind_under_point(event):
    'get the index of the vertex under point if within epsilon tolerance'

    tinv = settings.ax_img.transData 

    xr = np.reshape(settings.x,(np.shape(settings.x)[0],1))
    yr = np.reshape(settings.y,(np.shape(settings.y)[0],1))
    xy_vals = np.append(xr,yr,1)
    xyt = tinv.transform(xy_vals)
    xt, yt = xyt[:, 0], xyt[:, 1]
    d = np.hypot(xt - event.x, yt - event.y)
    indseq, = np.nonzero(d == d.min())
    ind = indseq[0]

    if d[ind] >= settings.epsilon:
        ind = None

    return ind

def motion_notify_callback(event):
    'on mouse movement'

    if settings.pind is None:
        return
    if event.inaxes is None:
        return
    if event.button != 1:
        return

    settings.x[settings.pind] = event.xdata 
    settings.y[settings.pind] = event.ydata 

    settings.ct_plt.set_xdata(settings.x)
    settings.ct_plt.set_ydata(settings.y)

    settings.f_img.canvas.draw_idle()

def centhappy(event):

    settings.happy_pos = True
  • settings.py
import numpy as np
from matplotlib import pyplot as plt

def init():

    global happy_pos
    global x, y
    global x0, y0
    global epsilon
    global pind
    global f_img, ax_img
    global ct_plt
    global img

    img = np.array([])

    # initial positions
    x0 = np.arange(0.,300.,30.)
    y0 = np.arange(0.,300.,30.)

    x = x0.copy()
    y = y0.copy()

    f_img, ax_img = plt.subplots(1, 1)

    ct_plt, = ax_img.plot(x,y,color='r',linestyle='none',marker='x',markersize=8)

    pind = None #active point
    epsilon = 5 #max pixel distance

    happy_pos = False
  • main.py
import numpy as np
import matplotlib.image as mpim
import time
from matplotlib.widgets import Button
from matplotlib import pyplot as plt

import functions as fct
import settings

settings.init()

settings.img = mpim.imread('pattern.png')

settings.ax_img.imshow(settings.img)

axres = plt.axes([0.1, 0.1, 0.12, 0.02])
bres = Button(axres, 'Reset')
bres.on_clicked(fct.reset)

axres_b = plt.axes([0.1, 0.3, 0.12, 0.02])
bres_b = Button(axres_b, 'happy')
bres_b.on_clicked(fct.centhappy)

settings.f_img.canvas.mpl_connect('button_press_event', fct.button_press_callback)
settings.f_img.canvas.mpl_connect('button_release_event', fct.button_release_callback)
settings.f_img.canvas.mpl_connect('motion_notify_event', fct.motion_notify_callback)

while not settings.happy_pos:
    time.sleep(5)

coord = np.column_stack((settings.x,settings.y))

np.savetxt('my_file.dat',coord)

Моя проблема связана с ожидающей частью программы. Следует дождаться, чтобы глобальная переменная settings.happy_pos стала true. Вот почему я использовал эту команду time.sleep(5). Я также попробовал:

input("press enter if you are happy with your points")

Но, в любом случае, фигура даже не создается и программа не отвечает. (Программа работает без этой части ожидания / ввода); У вас есть идеи, как это решить? Должен ли я использовать потоки?

PS: я дал здесь случайное изображение, которое я использовал в этом примере для моего вопроса.

...