Wait till the user click a button in a Matplotlib figure to continue the program

跟風遠走 提交于 2019-12-11 04:56:23

问题


I'm working on an interactive program which put points on a Matplotlib figure. The program lets the user move these points from their original positions with the mouse. When the user is happy on the new point positions, the program continues.

Because my program project is big and covers much more than that, I have split it in several files. Here are they :

  • 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)

My problem comes from the wait part of the program. It should wait that the global variable settings.happy_pos become true. That's why I have used this time.sleep(5) command. I have also tried :

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

But, in any case, the figure is not even created and the program is not responding. (The program works without this wait/input part); Do you have any idea how to solve this ? Should I use threading ?

PS : I have given here the random image I have used in this example for my question.

来源:https://stackoverflow.com/questions/56312631/wait-till-the-user-click-a-button-in-a-matplotlib-figure-to-continue-the-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!