简体   繁体   中英

matplotlib PolygonSelector freezes when called in tkinter

I'm writing a script using tkinter and matplotlib for data processing, some parts of the code requires polygon selector to choose a region of interest. However, PolygonSelector fails to detect the motion of cursor.

It should be noted that this issue occurs when the interactive mode of matplotlib figure is on.

Simplified code and result are shown below:

#!/usr/bin/env python3
import matplotlib
matplotlib.use("TkAgg")
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.widgets import PolygonSelector

root = tk.Tk()

def draw():
    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.ion()    # interactive mode is on
    plt.show()

    def onselect(data_input):
        print(data_input)

    PS = PolygonSelector(ax, onselect)

tk.Button(root, text='draw', command=draw).pack()
root.mainloop()

This is the plot after clicking 'draw' button on tkinter GUI, the starting point of polygon stucks at (0,0), it is expected to move with cursor:

在此处输入图片说明

When I call draw() outside of tkinter, PolygonSelector works fine:

def draw():
    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.ion()    # interactive mode is on
    plt.show()

    def onselect(data_input):
        print(data_input)

    PS = PolygonSelector(ax, onselect)
    a = input()    # prevent window from closing when execution is done
draw()

在此处输入图片说明

The simple solution would be to make sure you make your Polygon Selector a global variable. This will keep the selector visually updating.

#!/usr/bin/env python3
import tkinter as tk
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.widgets import PolygonSelector
matplotlib.use("TkAgg")


root = tk.Tk()
ps = None

def draw():
    global ps
    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.ion()
    plt.show()
    ps = PolygonSelector(ax, on_select)


def on_select(data_input):
    print(data_input)

tk.Button(root, text='draw', command=draw).pack()
root.mainloop()

If you build this into a class then you can avoid the use of global and get the behavior you want by apply the Polygon Selector as a class attribute.

#!/usr/bin/env python3
import tkinter as tk
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.widgets import PolygonSelector
matplotlib.use("TkAgg")


class GUI(tk.Tk):
    def __init__(self):
        super().__init__()
        self.ps = None
        tk.Button(self, text='draw', command=self.draw).pack()

    def draw(self):
        fig = plt.figure()
        ax = fig.add_subplot(111)
        plt.ion()
        plt.show()
        self.ps = PolygonSelector(ax, self.on_select)

    def on_select(self, data_input):
        print(data_input)


if __name__ == "__main__":
    GUI().mainloop()

Results:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM