Как активировать и деактивировать функцию с помощью кнопки? - PullRequest
0 голосов
/ 20 декабря 2018

Я хочу активировать и деактивировать метод выбора области интереса (ROI) изображения нажатием кнопки.Я использовал флажок, который возвращает 1 или 0, если она нажата или нет.Функция, которая должна быть включена или выключена - это matplotlibs RectangleSelector .Пока нажатие кнопки ROI вообще ничего не делает.

import sys
if sys.version_info[0] < 3:
    import Tkinter as Tk
else:
    import tkinter as Tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from numpy.random import rand
from matplotlib.widgets import RectangleSelector

root = Tk.Tk()
root_panel = Tk.Frame(root)
root_panel.pack(side="top", fill="both", expand="no")

fig = Figure()
ax = fig.add_subplot(111)
img = ax.imshow(rand(10, 5), extent=(1, 2, 1, 2), picker=True)
ax.axis([0, 3, 0, 3])

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

# ROI BUTTON
switch_variable = Tk.IntVar()
ROIBtn = Tk.Checkbutton(master=root_panel, text='ROI', indicatoron=False, 
variable=switch_variable)
ROIBtn.pack(side=Tk.LEFT)

def onselect(eclick, erelease):
    global switch_variable
    if switch_variable.get() == 1:
        x1, y1 = eclick.xdata, eclick.ydata
        x2, y2 = erelease.xdata, erelease.ydata
        global roi
        roi = (x1,y1,x2,y2)
        roi = list(map(int, roi))
        global cropped
        cropped = img[int(roi[1]):int(roi[3]), int(roi[0]):int(roi[2])]
        ax.clear
        ax.imshow(cropped)
        fig.canvas.draw()

def toggle_selector(event):
    global switch_variable
    if switch_variable.get() == 1:
        if event.key in ['Q', 'q'] and toggle_selector.RS.active:
            print('RectangleSelector deactivated.')
            toggle_selector.RS.set_active(False)
        if event.key in ['A', 'a'] and not toggle_selector.RS.active:
            print('RectangleSelector activated.')
            toggle_selector.RS.set_active(True)

if switch_variable.get() == 1:
    toggle_selector.RS = RectangleSelector(ax, onselect, drawtype='box')
    fig.canvas.mpl_connect('key_press_event', toggle_selector)

root.mainloop()

Я хотел бы знать, как мне использовать switch_variable, чтобы сообщить моей программе, когда использовать onselect икогда это ничего не должно делать.Спасибо!

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Поскольку toggle_selector() уже используется для включения / выключения RectangleSelector в зависимости от нажатой клавиши, его также можно использовать с параметром command из ROIBtn.

Ниже приведен модифицированный кодосновываясь на вашем:

import sys
try:
    import Tkinter as Tk
except:
    import tkinter as Tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from numpy.random import rand
from matplotlib.widgets import RectangleSelector

root = Tk.Tk()
root_panel = Tk.Frame(root)
root_panel.pack(side="top", fill="both", expand="no")

fig = Figure()
ax = fig.add_subplot(111)
img = ax.imshow(rand(10, 5), extent=(1, 2, 1, 2), picker=True)
ax.axis([0, 3, 0, 3])

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

def onselect(eclick, erelease):
    x1, y1 = eclick.xdata, eclick.ydata
    x2, y2 = erelease.xdata, erelease.ydata
    try:
        cropped = img[y1:y2, x1:x2] # this raises TypeError: 'AxesImage' object is not subscriptable
        ax.clear()
        ax.imshow(cropped)
        fig.canvas.draw()
    except Exception as e:
        print('Error:', e)

# must set default value of event argument,
# otherwise problem when triggered by ROIBtn
def toggle_selector(event=None):
    #print('toggle_selector:', event.key if event else switch_variable.get())
    active = None
    if event:
        # triggered by keypressed
        if event.key in 'Qq':
            if selector.active: active = 0
        elif event.key in 'Aa':
            if not selector.active: active = 1
    else:
        # triggered by ROIBtn
        active = switch_variable.get()
    if active is not None:
        switch_variable.set(active) # update ROIBtn
        selector.set_active(active == 1)
        print('RectangleSelector {}activated.'.format('' if active == 1 else 'de'))

# ROI BUTTON
switch_variable = Tk.IntVar()
# set command option to toggle_selector()
ROIBtn = Tk.Checkbutton(master=root_panel, text='ROI', indicatoron=False, variable=switch_variable, command=toggle_selector)
ROIBtn.pack(side=Tk.LEFT)

selector = RectangleSelector(ax, onselect, drawtype='box')
selector.set_active(switch_variable.get())
fig.canvas.mpl_connect('key_press_event', toggle_selector)

root.mainloop()
0 голосов
/ 20 декабря 2018

Вы, кажется, скопировали часть своего кода именно с здесь , не понимая, что делают разные части.Функция toggle_selector делает именно то, что вы хотите, но вам нужно запустить ее в нужное время, и вам нужно проверить состояние, которое вы хотите.

Первое, что вам нужно понять, это то, что всето, что не входит в функцию, будет выполнено только один раз, когда инициируется GUI.Поскольку switch_variable инициируется со значением 0, ваш код пропустит часть кода if switch_variable.get() == 1: и никогда не будет переоцениваться.

Вам необходим toggle_selector.RS = RectangleSelector(ax, onselect, drawtype='box'), чтобы инициировать RectangleSelector, но вам не нужен fig.canvas.mpl_connect('key_press_event', toggle_selector), потому что вы не хотите привязывать что-либо к нажатию клавиши, вы хотите привязать к проверяемой кнопке.
Вы можете сделать это двумя способами, либо с помощью command=toggle_selector в вашем CheckButton (имейте в виду, что в этом случае вам нужно определить функцию перед Checkbutton) или проследить переменную как switch_variable.trace("w", toggle_selector).

Затем в функции toggle_selectorесть чек на event.key in ['Q', 'q'].Это не имеет смысла в этом случае, это используется в примере кода, потому что это позволяет вам включать и выключать функцию клавишами q и a, но вы этого не хотите.Единственное, что вам нужно проверить, это то, что switch_variable содержит значение 1 или 0.

. Если сложить все вместе, то получится:

import sys
if sys.version_info[0] < 3:
    import Tkinter as Tk
else:
    import tkinter as Tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from numpy.random import rand
from matplotlib.widgets import RectangleSelector

def onselect(eclick, erelease):
    if switch_variable.get() == 1:
        x1, y1 = eclick.xdata, eclick.ydata
        x2, y2 = erelease.xdata, erelease.ydata
        roi = (x1,y1,x2,y2)
        roi = list(map(int, roi))
        cropped = img[int(roi[1]):int(roi[3]), int(roi[0]):int(roi[2])]
        ax.clear
        ax.imshow(cropped)
        fig.canvas.draw()

def toggle_selector(*args):
    if switch_variable.get() == 0:
        print('RectangleSelector deactivated.')
        toggle_selector.RS.set_active(False)
    elif switch_variable.get() == 1:
        print('RectangleSelector activated.')
        toggle_selector.RS.set_active(True)

root = Tk.Tk()
root_panel = Tk.Frame(root)
root_panel.pack(side="top", fill="both", expand="no")

fig = Figure()
ax = fig.add_subplot(111)
rand_img = rand(10, 5)
img = ax.imshow(rand_img, extent=(1, 2, 1, 2), picker=True)
ax.axis([0, 3, 0, 3])

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

# ROI BUTTON
switch_variable = Tk.IntVar()
ROIBtn = Tk.Checkbutton(master=root_panel, text='ROI', indicatoron=False, variable=switch_variable, command=toggle_selector)
ROIBtn.pack(side=Tk.LEFT)

toggle_selector.RS = RectangleSelector(ax, onselect, drawtype='box')
toggle_selector()

root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...