What is `mode` argument of `trace_add` method in tkinter - python

The documentation states:
Mode: It is one of “array”, “read”, “write”, “unset”, or a list or tuple of such strings. but I'm not sure I understand what it means.
I'm using trace_add to call a function whenever my object tk.StringVar changes value and I'm using the mode write without really understanding why.
EDIT: what I find online is only about the deprecated method trace; nothing about the method trace_add.

Using the value "write" means you want the callback to be called whenever the variable is written (ie: changed; when the set method is called).
Using the value "read" means you want the callback to be called whenever the variable is read (ie: the get method is called).
Using the value "unset" means you want the callback to be called whenever the variable is unset. In the case of tkinter, this happens when the variable is deleted.
The canonical tcl documentation for "array" says: "Invoke commandPrefix whenever the variable is accessed or modified via the array command". Tkinter doesn't directly give access to tcl's array command, so this one isn't very useful in tkinter.

Related

Python - accessing variable that is needed for function defined in different moduel

I have saved a defined function within a module, which I have then imported into a new script.
Within this function, the variable master (a pandas dataframe) is queried. However, master is not one of the arguments in the function and is a dataframe I am hoping to access regardless of the script.
When trying to use the aforementioned function in my new script, I get the following error:
NameError: name 'master' is not defined
But when I enter master into the console, it prints with no problem or error.
I think it is something to do with local and global variables, but I am new to Python and am struggling to understand how I can fix the error.
Within this function, the variable master (a pandas dataframe) is queried. However, master is not one of the arguments in the function
Then update your function to take it as an argument. You can't use a global here, since (if I understand correctly), your "master" variable is defined in your script and the function in a module that's imported by the script. In this case explicitely passing "master" to your function is the only way to make it available since Python has no true "global" namespace ("global" in Python actually means "module level").
And that's a GoodThing actually because it's the only sane way to structure your program. As a general rule, globals (mutable globals that is) are evil, they make your code brittle, untestable, unmaintainable and unpredictable.

Nuke ChannelMask_Knob required argument

I am trying to figure out what the required string argument for the nuke.ChannelMask_Knob() function corresponds to. On some other knob constructors the first argument seems to be the name/label, but that does not seem to be the case for the ChannelMask_Knob...
I have looked at the Nuke Python API, but I am unsure how to follow it back to the appropriate function definition to answer my question. My line of thinking is that this has to do with the init function which is overridden by the ChannelMask_Knob class, but the parameter list according to the API is just "..." which I believe means it has to do with a builtin function. Since I can't see the body of the init function, I have no idea what that argument is used for, thus my problem...
Here is an example of my issue:
test_knob = nuke.ChannelMask_Knob("required_argument")
node.addKnob(test_knob)
This works just fine, but I would like to know what the "required_argument" is used for since it is apparently not the name or label for the knob.
You must intentionally leave a blank space for parameter in ChannelMask_Knob('') method. It doesn't work. But for assigning a name and a label you need to use .setName('name') and .setLabel('label') methods respectively. It works fine.
Here is a code:
import nuke
noop = nuke.nodes.NoOp()
### maskKnob = nuke.ChannelMask_Knob('name', 'label', False)
maskKnob = nuke.ChannelMask_Knob('')
maskKnob.setName('name')
maskKnob.setLabel('label')
noop.addKnob(maskKnob)
For selection of channel in this dropdown menu it's better to use the following method:
nuke.selectedNode().knob('name').setValue('alpha')
nuke.selectedNode().knob('name').setValue('disparity')

What are the arguments to Tkinter variable trace method callbacks?

Python has classes for Tkinter variables StringVar(), BooleanVar(), etc. These all share the methods get(), set(string), and trace(mode, callback). The callback function passed as the second argument to trace(mode, callback) is passed four arguments, self, n, m, x.
For an example of a BooleanVar() these appear to be '', 'PYVAR0', 'w'.
The third argument x appears to be the mode that triggered the trace, in my case the variable was changed. However, what is the first variable that appears to be an empty string? What is the second, if I had to guess I'd say some internal name for the variable?
The first argument is the internal variable name. You can use this name as an argument to the tkinter getvar and setvar methods. If you give your variable a name (eg: StringVar(name='foo')) this will be the given name, otherwise it will be a name generated for you by tkinter (eg: PYVAR0)
If the first argument represents a list variable (highly unlikely in tkinter), the second argument will be an index into that list. If it is a scalar variable, the second argument will be the empty string.
The third argument is the operation, useful if you are using the same method for reading, writing and/or deleting the variable. This argument tells you which operation triggered the callback. It will be one of "read", "write", or "unset".
Tkinter is a python wrapper around a tcl/tk interpreter. The definitive documentation for variable traces can be found here: http://tcl.tk/man/tcl8.5/TclCmd/trace.htm#M14. Though, this only documents how the internal trace works, the tkinter wrapper sometimes massages the data.
The first argument is the name of the variable, but is not "useless" since you can set it when you declare the variable, e.g.:
someVar = IntVar(name="Name of someVar")
When you check the first argument in the trace callback it will equal "Name of someVar". Using the name to distinguish between variables, you can then bind the same handler to trace changes to any number of variables, rather than needing a separate handler for each variable.

How do I send multiple arguments when binding a widget to a function in python 2.7.2

Just wondering, How do I bind an entry field to (with the return key) a function that requires 2 arguments counting event as one of them without lambda or classes, just one function and 2 arguments:
def function(event,entry):#entry is the widget to be focused. also, entry is just a place holder NOT A WIDGET. entry MUST be specified. it cannot be removed.
entry.focus()
entry1.bind("<Return>",function(None,entry2))
When entry1 is binded, the function that it is bound to executes right when it is binded and then it ignores all other input. It lets me put characters into the field, but when I hit return, it does not go through and focus the second entry. If I remove None as one of the arguments it gives me an error that only one of two required arguments are defined, it doesn't matter what I put in place of None, it still doesn't work. How do I make it work without classes or an anonymous function?
When you write function(None,entry2) you /are/ calling it right away -- the function probably returns None, so essentially what you are doing is:
function(None, entry2)
entry1.bind("<Return>", None)
What you are probably looking for is this:
entry1.bind("<Return>", lambda e: function(entry2))
This generates a function (note: generates the function, but doesn't call it) that takes one parameter (the event, "e") and ignores it
When you then hit the return key, this generated function will be called, and in turn it will call function(entry2)
The answer is to use lambda. For a good explanation see Tkinter Callbacks on effbot.org
Without a full example, it's difficult to provide a full answer. However there is one common error that is easily fixed: the second argument to bind should be a function name, not a function call.
If you change the bind statement to:
entry1.bind("<Return>", function)
the function will be called when the Return event is triggered instead of when you execute the bind statement.

Eclipse + PyDev define function based on function call

I have noticed a particular feature in Visual Studio and I am wondering if this feature is also available in Eclipse + PyDev.
In Visual Studio, if one were to type a function call and that particular function does not already exist, VS would show a code error and give an option to generate a new empty function matching the signature provided in the function call.
In other words, same I am working in a particular Python function or class and I realize I need a new function to process some string. In my current function I type processString(myString), which returns an error because the processString function does not currently exist. Is there some way to then click on the processString function call and create a new block in my module:
def processString(myString):
pass
Thanks in advance for your help.
Thank you #Eric Wilson.
If I type the function call processString(myString) then hit 'CTRL+1' the code completion/template window appears offering me the option to create a new class, method, assign to a field, or assign to a variable.
This was exactly what I was looking for.

Categories