问题
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