check a checkbox from a procedure
marcel gateau
I have a complex Igor panel, with many tabs, checkboxes, etc... Is it possible, from the procedure of one object in the panel, to check a checkbox and run the corresponding actions?
Hi Marcel,
Yes.
CheckBox theName value=1
//To remove mark
CheckBox theName value=0
You may need to further specify it if it is not on the target window.
win=winName Specifies which window or subwindow contains the named control. If not given, then the top-most graph or panel window or subwindow is assumed.
Note this only marks it and does not execute any code attached to it. Now if you have code within the checkbox control and you are using structure based control methods, it is a bit tricky to fire the code with out the user interacting. One way around it is to separate the functions from the interface code.
STRUCT WMCheckboxAction &cba
switch( cba.eventCode )
case 2: // mouse up
Variable checked = cba.checked
if (checked)
do_Something()
endif
break
case -1: // control being killed
break
endswitch
return 0
End
Function Do_Something()
Print "Hello World"
End
Andy
February 12, 2021 at 09:07 am - Permalink
Thanks, this is exactly what I needed. Luckily enough, the code for this CheckBox is separated from the interface code.
Great!
February 12, 2021 at 09:36 am - Permalink
I will enforce a bit more strongly the statement that Andy makes in passing. The robust way to do these things is using the window designation.
Also, if you are routinely having an action on one control cause a change in the state of another control, you may also want to use an administrative function that does an update on the state of the panel. This can especially come into play when you want to show/hide various controls depending on for example a pop menu or checkbox selection.
ControlInfo/W=$panelname chboxA
if (v_value)
Setvariable setvarA, win=$panelname, disable=1
...
else
Setvariable setvarA, win=$panelname, disable=0
...
endif
return 0
end
February 12, 2021 at 02:49 pm - Permalink
Thank you. This is something I am using a lot, although till now, everything is in a single (big) panel!
Marcel
February 13, 2021 at 08:15 am - Permalink
Note,
If the checkbox is linked to global variable:
CheckBox theName, win=$panelname, variable=root:myGlobalvariable
you should simply change value in that variable (myGlobalVariable = 1) and Checkbox will change without any other action. And if you have (as suggested above) do_Something() function, then call that one and you are done. No need to bother changing the checkbox in the panel itself.
February 13, 2021 at 10:52 am - Permalink
In reply to Note, If the checkbox is… by ilavsky
Hi,
What would be even better would be to tie it to wave point. When designing systems that will evolve over time I often put all the numeric settings into a wave with a dim labels. That way I have one declaration to do in a function and I can easily see the state of the system by looking at that wave in table. Typically I have one wave for numeric states and a second for text. This keeps things very clean with needing global variables. Alas in this case I can't tie the state a wave point. Just part of the wish list.
Andy
February 13, 2021 at 11:01 am - Permalink
Andy ... Can you give a minimum working example (MWE in the LaTeX stack exchange)? I am confused by what aspect of the control is being tied to a wave point. Specifically, are you tying each point in the wave to a different control on the panel?
February 13, 2021 at 12:17 pm - Permalink
In reply to Andy ... Can you give a… by jjweimer
Ji Jeff,
They are NOT tied a wave point, it is on the wish list.
Andy
February 13, 2021 at 12:55 pm - Permalink
My mistake. What I mean is, can you give an example of how tying the state of a control to a wave point WOULD work. I don't see what you have as a vision for this.
February 13, 2021 at 01:02 pm - Permalink
Hi Jeff,
I was thinking the same way you can in set variable control. See the set value line to pick a wave and its specific point.
This is an example from an experiment that controlled a phase lock loop amplifier, a Keithley meter, and some LED. I had all the system state information in one wave and used the row label dimensions to specify. That way with a single wave declaration I had full access and as I added more variables to control I didn't need to worry about messing up previous ones or declaring them in functions. Also with a simple table command I could see everything. Also I didn't need to a control info command to get a value. Imagine if you will that all controls could be easily tied to a couple of waves. PopUp menu could have string (S_Value) in a text wave and popup number (V_Value) in a variable wave. Check box could go to a variable wave. Radio buttons could be easily grouped,... The mind reels!
Andy
February 15, 2021 at 08:57 am - Permalink
I never realized this for set variables. Admittedly I am also not using dimension labels routinely as you are.
My one thought is that what you have done is replace global variables and strings by global waves. As an alternate approach with control panels, I have since been inclined to create a STRUCTURE and a STRUCTURE LOOKUP FUNCTION. Here is an example from my Image Tools package to read the desired load state.
Structure S_LoadSettings
variable what
variable source
variable allow16bit
variable red
...
EndStructure
// populate the structure
Function Sf_GetLoadSettings(ls)
STRUCT S_LoadSettings &ls
// load what?
ControlInfo/W=$k_fullpanel popupload_tab0
ls.what = v_value
// what type of image?
ControlInfo/W=$k_fullpanel checkgraw_tab0
ls.graw = v_value
// extract what?
ControlInfo/W=$k_fullpanel checkgred_tab0
ls.red = v_value
...
return 0
end
The advantage for me is that, as the package expands and other controls are added, I simply need to add a structure variable or string and define the lookup line in the main reading function. I can debug by setting a break-point at the BUTTON action and tracking whether the structure is properly populated.
I would not by this example in any way mean to open a Pandora's box as to which approach is "better", yours or mine. Having done a bit with dimension labels somewhere once or twice, I can see the positive reasons why all controls, not just setvariables, should be able to be defined by using them.
Thanks for the example!
February 15, 2021 at 01:54 pm - Permalink
And if you use a substructure for each control, you end up with something that works a bit like a window object. Then you look up a control value with something like mypanel.setvar0.value or mypanel.popup1.sval.
This is excerpted from some code that replaces an earlier version that used the wave-with-dimension-labels approach:
getControlValue("thePanel", "popImage", s.image)
getControlValue("thePanel", "popTraceRGB", s.trace)
getControlValue("thePanel", "popBGRGB", s.bg)
getControlValue("thePanel", "setvarRange", s.range)
getControlValue("thePanel", "checkGaps", s.gaps)
getControlValue("thePanel", "checkXY", s.XY)
getControlValue("thePanel", "setvarJump", s.jump)
getControlValue("thePanel", "setvarTraceName", s.tracename)
getControlValue("thePanel", "sliderFuzzy", s.fuzzy)
end
Structure PanelStatusStructure
STRUCT ControlValueStructure image, logX, logY, trace, bg, fuzzy, gaps, XY, jump, range, tracename
EndStructure
Structure ControlValueStructure
int16 type
variable value
string sval
STRUCT RGBAColor rgb
variable selcol
EndStructure
function getControlValue(string win, string controlName, STRUCT ControlValueStructure &s)
ControlInfo /W=$win $controlName
switch (abs(V_Flag))
case 3: // popup menu
s.rgb.red = V_Red
s.rgb.green = V_Green
s.rgb.blue = V_Blue
s.rgb.alpha = V_Alpha
case 2: // checkbox
case 4: // valdisplay
case 5: // SetVariable
case 7: // slider
case 8: // tab
s.type = v_flag
s.value = v_value
s.sval = s_value
break
case 11: // listbox
s.type = v_flag
s.value = v_value
s.sval = s_value
s.selcol = v_selcol
break
default:
s.type = v_flag
endswitch
end
I have been moving toward this sort of thing for user interface code that doesn't need to run especially quickly. I would imagine that populating the structure with multiple calls to controlinfo is much slower than looking up a wave once, so for something like storing parameters for background data acquisition this would be a bad idea.
February 16, 2021 at 12:05 am - Permalink
Hi,
I have been exploiting the use of data labels quite a bit because it in essence allows me to mix data types within waves. An example of some of the techniques (hacks) I play with data labels is in this post . I use it organize experimental runs by using the row labels as sample id. I would love to see further exploitation of data labels both rows and columns.
Andy
February 16, 2021 at 07:19 am - Permalink
In reply to Hi, What would be even… by hegedus
I agree with you, and I requested this feature long before I started working for WM for the same reason. It is on the official wish list (ticket #3154). Unfortunately it would require substantial changes to code that is already overly tedious.
I will add your "+1" to the feature request.
February 16, 2021 at 09:04 am - Permalink
In practice, I have variables or strings attached to the objects of a panel, then a procedure (called by each object) that writes all the corresponding parameters in a wave, which appears as a table with clear labels (the labels are written in another wave). This table gathers therefore all the information at one glance. It is saved on as a file to pass parameters to a data acquisition program (in Python).
February 16, 2021 at 09:16 am - Permalink