繁体   English   中英

如何使用复选按钮激活和停用功能?

[英]How to activate and deactivate a function using a checkbutton?

我想激活和停用一种通过按下按钮来选择图像的感兴趣区域(ROI)的方法。 我使用了一个检查按钮,如果按下该按钮,则返回10 应该打开或关闭的功能是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以及何时不执行任何操作。 谢谢!

您似乎完全是从此处复制了部分代码,却不了解不同部分的功能。 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)因为您不需要要将任何内容绑定到按键,您想绑定到被单击的复选按钮。
您可以通过两种方式做到这一点,或者在CheckButton使用command=toggle_selector (请注意,在这种情况下,您需要在Checkbutton之前定义函数),或者通过跟踪变量,如switch_variable.trace("w", toggle_selector)

然后,在toggle_selector函数中,检查event.key in ['Q', 'q'] 这是没有意义在这种情况下,它的代码示例中使用,因为这可以让你打开和关闭与功能qa按键,但你不希望这样。 您唯一需要检查的是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()

由于toggle_selector()已经用于基于按下的键来启用/禁用RectangleSelector ,因此ROIBtncommand选项也可以使用它。

以下是根据您的代码修改的代码:

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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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