1

The following code adds point on canvas by left click, draws a polyline with the drawn points by right click and also draws a sliding point on the lines while a cursor is moving. The only problem is that the execution stops pretty soon after "sliding" because of the title reason. How can I overcome this problem and slide as much as wanted?

import matplotlib.pyplot as plt


class DumbyRemove:
    def __init__(self):
        pass

    def remove(self):
        pass

the_points = list()
drawn_points = list()
moving_point = DumbyRemove()


def draw_polyline():
    global the_points, drawn_points
    if len(the_points) < 2:
        return
    start_point = the_points[0]
    for end_point in the_points[1:]:
        xs = (start_point[0], end_point[0])
        ys = (start_point[1], end_point[1])
        start_point = end_point
        line = plt.Line2D(xs, ys, marker='.', color=(0.7, 0.3, 0.3))
        plt.gcf().gca().add_artist(line)
    drawn_points = drawn_points + the_points
    the_points = list()
    plt.show()


def button_press_callback(event):
    global the_points

    if event.button == 1:
        the_points.append((event.xdata, event.ydata))
        p = plt.Line2D((event.xdata, event.xdata), (event.ydata, event.ydata), marker='o', color='r')
        plt.gcf().gca().add_artist(p)
        plt.show()
    else:
        draw_polyline()


def handle_motion(event):
    global moving_point
    if len(drawn_points) < 2:
        return
    x = event.xdata
    start_point = drawn_points[0]
    for end_point in drawn_points[1:]:
        start_x, start_y = start_point
        end_x, end_y = end_point
        if end_x < start_x:
            end_x, start_x = start_x, end_x
            end_y, start_y = start_y, end_y
        if start_x <= x <= end_x:
            d = end_x - start_x
            lam = (x - start_x) / d
            y = start_y * (1 - lam) + end_y * lam
            moving_point.remove()
            moving_point = plt.Line2D((x, x), (y, y), marker='o', color='r')
            plt.gcf().gca().add_artist(moving_point)
            break
        start_point = end_point
    plt.show()

fig = plt.gcf()
fig.add_subplot(111, aspect='equal')

fig.canvas.mpl_connect('button_press_event', button_press_callback)
fig.canvas.mpl_connect('motion_notify_event', handle_motion)

plt.show()

Traceback:

Exception in Tkinter callback
    x = self.convert_xunits(self._x)
    File "C:\Python27\lib\site-packages\matplotlib\artist.py", line 186, in convert_xunits
    ax = getattr(self, 'axes', None)
RuntimeError: maximum recursion depth exceeded while calling a Python object
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1536, in __call__
    return self.func(*args)
  File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 605, in destroy
    Gcf.destroy(self._num)
  File "C:\Python27\lib\site-packages\matplotlib\_pylab_helpers.py", line 60, in destroy
    manager.canvas.mpl_disconnect(manager._cidgcf)
  File "C:\Python27\lib\site-packages\matplotlib\backend_bases.py", line 2366, in mpl_disconnect
    return self.callbacks.disconnect(cid)
  File "C:\Python27\lib\site-packages\matplotlib\cbook.py", line 552, in disconnect
    del functions[function]
  File "C:\Python27\lib\weakref.py", line 327, in __delitem__
    del self.data[ref(key)]
RuntimeError: maximum recursion depth exceeded
7
  • Please post the full error message with stack trace? Does execution really stop after sliding (as you state) or during sliding (as you imply). I'm not clear on what is recurring. Commented Sep 2, 2016 at 17:06
  • @Prune I've added the end of error message. the errors show up during "sliding", that it is. I think it's easy to make an experiment on a machine and see :) Commented Sep 2, 2016 at 18:43
  • Do I read this correctly? None of your code appears in the call stack!? Commented Sep 2, 2016 at 18:49
  • @Prune exactly. none Commented Sep 2, 2016 at 18:50
  • Crud. Tkinter internals are not in my skill set. Can you slap a debugger on this or insert print statements to find where it's going? My first hypothesis is that holding down the mouse button causes spamming events until the stack of unresolved calls gets too deep. Commented Sep 2, 2016 at 18:54

1 Answer 1

5

Okey, fellas, I got it. The problem was due to intensive use of plt.show() in the event handler. Replacing it with event.canvas.draw() does the job.

Sign up to request clarification or add additional context in comments.

2 Comments

I can confirm this solution worked for me as well, where I was calling plt.show() in handler for any mouse event. Changing to event.canvas.draw() solved the problem.
for me event.canvas.draw() didn't draw anything. I had to use figure.canvas.draw()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.