当鼠标移动到另一个时,如何更新一个图?

时间:2017-11-02 14:43:14

标签: python python-3.x events matplotlib

我想在补充图中绘制数据,这对应于主图中鼠标悬停的当前X值。

我编码了

import math

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(dpi=100, figsize=(5, 5))
x = np.arange(0, 6, 0.1)
plt.plot(x, np.sin(x), 'r')

fig2, ax2 = plt.subplots(dpi=100, figsize=(5, 5))


def plot_ray(angle, y):
    circle = plt.Circle((0, 0), 1, color='b', fill=False)
    length = y / math.sin(angle)
    line = plt.Line2D([0, length * math.cos(angle)], [0, length * math.sin(angle)])
    ax2.clear()
    ax2.set_xlim(-2, 2)
    ax2.set_ylim(-2, 2)
    ax2.add_artist(circle)
    ax2.add_artist(line)


def mouse_move(event):
    x = event.xdata
    y = event.ydata
    if x is not None and y is not None:
        angle = x
        plot_ray(angle, y)


cid = fig.canvas.mpl_connect('motion_notify_event', mouse_move)

plt.show(block=True)

不幸的是,ax2行为不可预测。我在鼠标悬停时没有更新,直到我点击fig2窗口。或者它没有更新,直到我在pycharm中设置或释放断点。

enter image description here

如何编码正确的行为?

1 个答案:

答案 0 :(得分:1)

更改后你忘了刷新第二个数字。最后添加fig2.canvas.draw_idle()

def mouse_move(event):
    x = event.xdata
    y = event.ydata
    if x is not None and y is not None:
        angle = x
        plot_ray(angle, y)
        fig2.canvas.draw_idle()

请注意,这会在每个mouse_move事件中创建新的圆圈和艺术家,这样效率很低。您宁愿一次创建这些艺术家,只更新他们的属性。

以下运行得更顺利。

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(dpi=100, figsize=(5, 5))
x = np.arange(0, 6, 0.1)
plt.plot(x, np.sin(x), 'r')

fig2, ax2 = plt.subplots(dpi=100, figsize=(5, 5))

circle = plt.Circle((0, 0), 1, color='b', fill=False)
ax2.add_artist(circle)
line, = ax2.plot([],[])
ax2.set_xlim(-2, 2)
ax2.set_ylim(-2, 2)

def plot_ray(angle, y):
    length = y / np.sin(angle)
    line.set_data([0, length * np.cos(angle)], [0, length * np.sin(angle)])

def mouse_move(event):
    x = event.xdata
    y = event.ydata
    if x is not None and y is not None:
        angle = x
        plot_ray(angle, y)
        fig2.canvas.draw_idle()


cid = fig.canvas.mpl_connect('motion_notify_event', mouse_move)

plt.show(block=True)