Я создал интерактивный график с помощью Python, используя matplotlib, и хочу вызвать его, поместив его в функцию. Все работает, пока я не поместил весь свой код в функцию make_plot(). Запуск кода без функции make_plot() дает мне именно то, что я хочу. Почему он больше не работает внутри другой функции (я просто теряю интерактивную функциональность)?
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np
def make_plot():
def button_clicked(event):
global line_plotted
if line_plotted:
ax1.lines[1].remove()
line_plotted = False
else:
ax1.plot(line[0], line[1], color='r', linestyle='--')
line_plotted = True
fig.canvas.draw()
plt.ion()
x = np.linspace(0, 4*np.pi, 500)
y = np.sin(x)
line = [0, 4 * np.pi], [1, 1]
fig = plt.figure(figsize=(15,5))
ax1 = fig.add_subplot()
ax1.plot(x,y)
ax1.plot(line[0], line[1], color='r', linestyle='--')
line_plotted = True
button_ax = plt.axes([0.8, 0.05, 0.1, 0.075])
button = Button(button_ax, 'Show red line')
button.on_clicked(button_clicked)
plt.show()
make_plot()
Я попытался поместить функцию button_clicked(event) вне функции make_plot(), но это не помогло.
что такое Button? это от matplotlib.widgets? Пожалуйста, включите импорт, чтобы мы знали, какие библиотеки вы используете.
Что решило мою конкретную проблему, так это изменить глобальный -> нелокальный и добавить строку «x = input()» ниже «plt.show()». Это дает мне желаемый результат, когда я запускаю программу с терминала (на Mac просто набираю «python <имя файла>»). Но когда я запускаю код напрямую из Spyder, он все равно не работает. Теперь мне было бы просто интересно, почему он работает с терминала, а не со Spyder.
Теперь кажется, что это было сделано неправильно. Использование команды input() только для удержания функции кажется «дешевым трюком»…
Если у вас есть еще вопрос, задайте еще вопрос. В вашем первоначальном вопросе ничего не говорилось о Spyder, поэтому вы не можете рассчитывать на ответы о Spyder. И на ваш новый вопрос, возможно, уже был дан ответ; воспользуйтесь поиском этого сайта.
Да, технически, на мой первоначальный вопрос не был дан ответ... Почему я теряю интерактивную функциональность при помещении кода внутрь функции?






global line_plotted
-->
nonlocal line_plotted
После перемещения всего кода внутри функции line_plotted не находится на глобальном уровне, ключевое слово nonlocal используется для ссылки на переменную в ближайшей области видимости.
Обновлено: полный код
запустите в pycharm и spyder, все они интерактивны — нажмите кнопку.
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np
matplotlib.use("TkAgg")
def make_plot():
def button_clicked(event):
nonlocal line_plotted
if line_plotted:
ax1.lines[1].remove()
line_plotted = False
else:
ax1.plot(line[0], line[1], color = "r", linestyle = "--")
line_plotted = True
fig.canvas.draw()
plt.ion()
x = np.linspace(0, 4 * np.pi, 500)
y = np.sin(x)
line = [0, 4 * np.pi], [1, 1]
fig = plt.figure(figsize=(15, 5))
ax1 = fig.add_subplot()
ax1.plot(x, y)
ax1.plot(line[0], line[1], color = "r", linestyle = "--")
line_plotted = True
button_ax = plt.axes([0.8, 0.05, 0.1, 0.075])
button = Button(button_ax, "Show red line")
button.on_clicked(button_clicked)
plt.show(block=True)
make_plot()
При внесении этого изменения сюжет по-прежнему не является интерактивным.
Я тестирую полный код, запускаю его в pycharm и spyder. Некоторые различия с вашим исходным кодом.
Да, это оно. matplotlib.use("TkAgg") в моем случае не нужен, но блок=True внутри plt.show() заставляет его работать по мере необходимости. Спасибо!
Строка
global line_plottedпредполагает, что есть еще код, который вы нам не показываете. Предположительно, проблема в том, что в вашей функции изменяются глобальные переменные. Пожалуйста, отредактируйте и поделитесь минимально воспроизводимым примером.