Search code examples
pythonuser-interfacetkinterinstance-variables

Setting a Tkinter variable throws the " TypeError: set() missing 1 required positional argument: value'" error message


A Tkinter GUI where a bunch of 'visual effect' classes call a control panel generator which produces a panel made up of widgets associated with the effect's parameters to modify the image on screen interactively.

tkvars = [tk.IntVar, tk.DoubleVar, tk.BooleanVar, tk.StringVar] # Available Tk variable types

Each variable-to-be goes through this loop to get the correct type of tk variable for its intended widget.

val = the value I want to set the variable to. The type of Tk variable required for that widget is based on the type of that value.

**if** ftype == 1:  ## CHECKBOX
    wvar = tkvars[2]     # Returns a BooleanVar
    wvar.**set**(val)
    **return** wvar          # Returns a Tk var of the correct type set to the correct value

**elif** ftype == 2:  ## RADIO
    wvar = tkvars[0]    # Returns an IntVar
    wvar.set(val)
    self._radiovar.**append**(wvar)
    **return** wvar          # Returns a Tk var of the correct type set to the correct value

**elif** ftype == 3:  ## SLIDERS
    if **str**(type(val)) in vartype: vix = vartype.**index**(str(type(val)))
    # The above line figures which type (int, float)  is required
    wvar = tkvars[vix]
    **print**(">>>>>>>>>>>>>>>SLIDER", tkvars[vix], vix, wvar, val)
    wvar.**set**(val)
    **return** wvar         # Throws an error message:
                        # ***TypeError: set() missing 1 required positional argument: value*'**

Problem is, the printout reveals that I'm attempting to set a Tk variable of the right type with the correct value, but that I now need two arguments for the Tk.variable**.set()** method.

First time I get that, and I have dozens of effect classes set up and working in the GUI. Here's the full traceback message:

Traceback (most recent call last):
  File "C:\Users\miche\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1702, in __call__
    return self.func(*args)
  File "D:/_DOCS/_CODE/ImProc/__PXL/PXL_5.py", line 10473, in clickend
    res = f.dialog()
  File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_classesA.py", line 119871, in dialog
    ShapesFx.pages
  File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_dialogs.py", line 6941, in __init__
    super(Dbuilder, self).__init__(parent, fields, caller, pages, isXpand, title)
  File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_dialogs.py", line 732, in __init__
    self.initial_focus = self.body(body)
  File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_dialogs.py", line 7024, in body
    wvar = self.getvars(parentframe, fix, item)
  File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_dialogs.py", line 7227, in getvars
    wvar.set(val)
**TypeError: set() missing 1 required positional argument: 'value'**


Solution

  • Consider this code:

    tkvars = [tk.IntVar, tk.DoubleVar, tk.BooleanVar, tk.StringVar] 
    

    You are creating a list of classes, not variables.

    The reason for the error is that you are calling the method on the class rather than an instance of the class. Like all python classes, when you call the method on an instance python will automatically pass in the value for self. Since you aren't calling the set method on an instance, your val is being passed to the self parameter, and thus there is no argument being passed as the value.

    If you wish to put the class of variable in your list (as opposed to instances of the class), you need to instantiate the class before setting the value. For example:

    if ftype == 1:  ## CHECKBOX
    
        cls = tkvars[2]   # returns the variable class
        wvar = cls()      # instantiates the class
        wvar.set(val)     # sets the value of the instance
        return wvar       # returns the instance
    

    Note: you can set the value at the time of instantiation to save one line of code:

    wvar = cls(value=val)
    

    If you don't need a new variable instantiated each time this code runs, you can instantiate the classes when you initialize the list:

    tkvars = [tk.IntVar(), tk.DoubleVar(), tk.BooleanVar(), tk.StringVar()]