Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用回调对多个tkinter CheckButton进行更改_Python_Python 3.x_Tkinter_Callback_Tkinter.checkbutton - Fatal编程技术网

Python 如何使用回调对多个tkinter CheckButton进行更改

Python 如何使用回调对多个tkinter CheckButton进行更改,python,python-3.x,tkinter,callback,tkinter.checkbutton,Python,Python 3.x,Tkinter,Callback,Tkinter.checkbutton,我有多个tk.checkbutton,单击(或更改)时应该共享同一个回调。复选框的变量(状态)应在状态更改时触发的回调中可用(并用于所有复选按钮)。有很多这样的文章,大多数都是关于状态变量的并行列表。因为我想避免使用单独的变量列表,因为checkboxex的数量可能会因数据更改而更改,所以我在两个版本中创建了自己的Checkbutton类,但这两个版本都有缺点,所以我需要一些建议 这两个类都包含一个state变量实例,用于保存状态(避免管理单独的状态变量列表),并在单击时触发操作。所以我的问题与

我有多个tk.checkbutton,单击(或更改)时应该共享同一个回调。复选框的变量(状态)应在状态更改时触发的回调中可用(并用于所有复选按钮)。有很多这样的文章,大多数都是关于状态变量的并行列表。因为我想避免使用单独的变量列表,因为checkboxex的数量可能会因数据更改而更改,所以我在两个版本中创建了自己的Checkbutton类,但这两个版本都有缺点,所以我需要一些建议

这两个类都包含一个state变量实例,用于保存状态(避免管理单独的状态变量列表),并在单击时触发操作。所以我的问题与回调有关

第一个类显示在这个最小化的运行示例中:

#!/usr/bin/env python3
from tkinter import *
import tkinter as tk
#-------------------------------------------------------------------------------
# myCheckButton: CheckButton containing state, that can be identified
#                in action(command) procedure
# Parameters:
# userdata: User defined, for example index of a database table row related to the CB
# action  : command to execute when clicked. Replaces command variable because
#           command does not provide the event information when called. Event
#           information is needed to get the checkbox data within action.
class myCheckButton(tk.Checkbutton):
  def __init__(self, parent, userdata, action, *args, **kwargs):
    # state holds the state of the CB (False = unchecked, True = checked)
    self.state = BooleanVar(value=False)
    # add the state variable to tk.Ckeckbutton args
    kwargs['variable'] = self.state
    # init tk.Checkbutton
    super().__init__(parent, *args, **kwargs)
    # bind action to myCheckButton using <Button-1> (left mouse button)
    self.bind('<Button-1>', action)
    # store userdata for usage in the action procedure
    self.userdata = userdata
#-------------------------------------------------------------------------------
def onCbClicked(event):
  # get the calling widget containing all data we need to know
  sender = event.widget
  # get the status of CB. "not" because action runs before status change
  status = not sender.state.get()
  # do something by using text, status and/or user defined variable
  if status == True:
    print("CB("  + sender["text"] + "): Data " + str(sender.userdata) + " is checked")
  else:
    print("CB("  + sender["text"] + "): Data " + str(sender.userdata) + " is unchecked")
#-------------------------------------------------------------------------------
# Main window defs
root = tk.Tk()
root.title("myCheckButton")
root.geometry('300x60')
# 1st instance of myCheckButton
mycb1 = myCheckButton(root, text="Test A", userdata=1, action=onCbClicked)
mycb1.grid(row=0, column=0)
# 2nd instance of myCheckButton
mycb2 = myCheckButton(root, text="Test B", userdata=2, action=onCbClicked)
mycb2.grid(row=1, column=0)
# just for example: Set state of mycb2 to true
mycb2.state.set(True)
root.mainloop()
即使这是我的首选解决方案: 通过对传递给跟踪回调的第一个参数进行eval来确定调用实例是否保存(假定传递给构造函数的是正确的名称)?有没有更好的方法来识别来电者?例如,通过以某种方式传递事件,以便能够识别与第一个解决方案类似的调用方

提前感谢您的帮助

编辑:

根据acw1668的提示,我将myCheckButton类从第一个解决方案更改为:

class myCheckButton(tk.Checkbutton):
  def __init__(self, parent, userdata, action, *args, **kwargs):
    # state holds the state of the CB (False = unchecked, True = checked)
    self.state = BooleanVar(value=False)
    # add the state variable to tk.Ckeckbutton args
    kwargs['variable'] = self.state
    # init tk.Checkbutton
    super().__init__(parent, *args, **kwargs)
    # bind action to myCheckButton using <Button-1> (left mouse button)
    self.bind('<Button-1>', action)
    # store userdata for usage in the action procedure
    self.userdata = userdata
    # store action
    self.action = action
    # add widget property
    self.widget = self
  def set(self, status):
    # only when status changes:
    if status != self.state.get():
      # callback before status change
      self.action(self)
      # change status
      self.state.set(status)

我还是有点困惑,但这是你想要的吗:

from tkinter import Tk, Checkbutton


root = Tk()

c = Checkbutton(root, text='Apple')
c.pack()
c.bind('<Button-1>', lambda e: print(e.widget))

root.mainloop()
你只需要找到一种调用这些函数的方法

完整的代码示例:

from tkinter import Tk, Checkbutton, Button, IntVar


def toggle(widget):
    state = var.get()
    if state == 0:
        print('off')
    if state == 1:
        print('on')
    print(widget)


def check():
    c.deselect()
    c.invoke()


def uncheck():
    c.select()
    c.invoke()


root = Tk()

var = IntVar()

c = Checkbutton(root, text='Apple', variable=var, command=lambda: toggle(c))
c.pack()

Button(root, text='On', command=check).pack()
Button(root, text='Off', command=uncheck).pack()

root.mainloop()

请注意,仅使用
时,使用按钮会触发checkbox命令。选择
/
。取消选择
不会这样做

,据我所知,您想自动为复选框分配回调吗?这也是唯一的?为什么不在循环中创建它们?(第二个类)不,我想在回调中获得一种保存方式,以找出在跟踪回调中哪个checkbox实例触发了调用。在首选示例#2中,我找到了一种方法,但我想知道是否有更好的方法来实现这一点。您可以在第一个解决方案中定义函数
set()
,更新
self.state
,并调用回调。然后使用此函数,而不是调用
.state.set(…)
@acw1668,谢谢您的提示。这对我来说是一个遗漏的暗示。我更新(编辑)了我的初始请求。绑定函数已包含在我的第一个代码中。它在我单击复选按钮时起作用,但在状态以编程方式更改时不起作用。@Armin我编辑了我的代码。您可以使用
.invoke()
模拟用户交互,并在必须将其设置为相反状态之前切换复选框,因为invoke会将其设置为与其状态相反的状态。因为它模拟了用户交互,所以它也会触发事件(或者至少应该是这样)@Armin做了更多的编辑,因为设计有点不完整。谢谢,这也是一个很好的方法。唯一的问题是:如果有更多的checkbutton使用相同的命令=toggle,我如何知道在回调中切换哪个checkbutton?使用.bind(…)执行.invoke()时不会调用回调。使用命令=。。。不提供包含导致事件的小部件的事件参数。@Armin I再次编辑代码(第二个(示例))以包含此类功能
from tkinter import Tk, Checkbutton


root = Tk()

c = Checkbutton(root, text='Apple')
c.pack()
c.bind('<Button-1>', lambda e: print(e.widget))

root.mainloop()
from tkinter import Tk, Checkbutton, Button, IntVar


def toggle(widget):
    state = var.get()
    if state == 0:
        print('off')
    if state == 1:
        print('on')
    print(widget)


def check():
    c.deselect()
    c.invoke()


def uncheck():
    c.select()
    c.invoke()


root = Tk()

var = IntVar()

c = Checkbutton(root, text='Apple', variable=var, command=lambda: toggle(c))
c.pack()

Button(root, text='On', command=check).pack()
Button(root, text='Off', command=uncheck).pack()

root.mainloop()