SetVariable with string
cgilbri
With the Prep4AnalyseGBC function, my aim is to allow the user to create the definition for a string variable (sID) which is then passed to a series of other routines that I have not shown. My problem is with the SetVariable operation. When I enter text into the control panel, my expectation is that this will become the definition for sID. The information that is available in the igor manual (page III-377) about using SetVariable in this way implies to me that the text entered to the control panel should be passed to the parameter varStr in my action procedure, Prep4AnalyseGBC_svWaveID.
However, this is not happening, because the procedure fails at run time and sID comes out as a null string. Can anyone elaborate a little on how SetVariable is supposed to work in this case or point me to a few pages in the manual where more information is available?
Structure strAnalyseGBC
String sID
EndStructure
Function Prep4AnalyseGBC()//(vVoltageAmplitude4TPParameters, sFirstDF, sLastDF)
//Variable vVoltageAmplitude4TPParameters
//String sFirstDF, sLastDF
NewDataFolder/O root:tmp_PauseforPrepDF
String/G root:tmp_PauseforPrepDF:sID = ""
//STRUCT strAnalyseGBC Prep4
DoWindow/K tmp_PauseforPrep
NewPanel/K=2 /W=(90,300,420,460)/N=tmp_PauseforPrep as "Enter wave info"
SetVariable svWaveID, title="Wave ID", fsize=14, pos={50,25}, size={150,50}, value=_STR:"", proc=Prep4AnalyseGBC_svWaveID
PauseForUser tmp_PauseforPrep
SVAR sID_G = root:tmp_PauseforPrep:sID
//sID receives an alternative designation as a global string variable.
String sID = sID_G
//sID as a global variable is copied to a local string.
KillDataFolder root:tmp_PauseforPrep
//Print Prep4.sID
Print sID
End
Function Prep4AnalyseGBC_svWaveID (svWaveID, varNum, varStr, varName) : SetVariableControl
String svWaveID, varStr, varName
Variable varNum
//STRUCT strAnalyseGBC Prep4_svWaveID
String/G root:tmp_PauseforPrepDF:sID = varStr
//Prep4_svWaveID.sID = varStr
DoWindow/K tmp_PauseforPrep
End
String sID
EndStructure
Function Prep4AnalyseGBC()//(vVoltageAmplitude4TPParameters, sFirstDF, sLastDF)
//Variable vVoltageAmplitude4TPParameters
//String sFirstDF, sLastDF
NewDataFolder/O root:tmp_PauseforPrepDF
String/G root:tmp_PauseforPrepDF:sID = ""
//STRUCT strAnalyseGBC Prep4
DoWindow/K tmp_PauseforPrep
NewPanel/K=2 /W=(90,300,420,460)/N=tmp_PauseforPrep as "Enter wave info"
SetVariable svWaveID, title="Wave ID", fsize=14, pos={50,25}, size={150,50}, value=_STR:"", proc=Prep4AnalyseGBC_svWaveID
PauseForUser tmp_PauseforPrep
SVAR sID_G = root:tmp_PauseforPrep:sID
//sID receives an alternative designation as a global string variable.
String sID = sID_G
//sID as a global variable is copied to a local string.
KillDataFolder root:tmp_PauseforPrep
//Print Prep4.sID
Print sID
End
Function Prep4AnalyseGBC_svWaveID (svWaveID, varNum, varStr, varName) : SetVariableControl
String svWaveID, varStr, varName
Variable varNum
//STRUCT strAnalyseGBC Prep4_svWaveID
String/G root:tmp_PauseforPrepDF:sID = varStr
//Prep4_svWaveID.sID = varStr
DoWindow/K tmp_PauseforPrep
End
If you want to store the value in a global variable you need to write:
value=root:tmp_PauseforPrep:sID
However using the internal storage is better because it avoids the need to create a global variable.
July 28, 2014 at 06:35 pm - Permalink
- You don't need an action procedure just to pass the value to some global string. You should tell
SetVariable
which string to use upon its creation and the variable control will always automatically update. That's what thevalue
parameter is for.- With the newer Igor versions it became even more unfavorable to use global variables for this. Better not hardcode these ugly things into your code and clutter your experiment. You can use
value=_STR:stuff
to attach this stuff directly to the particular control (i.e., its window- and even control-specific). Extract the value usingControlInfo
only when needed (opposed to having the stuff lying around all the time.Edit: Ooops, too slow this time ... OK, here's a bonus comment:
It seems that you are working with folders (a lot?). You might want to look into data folder references (DFREFs) before its too late to clean up all the clutter.
July 28, 2014 at 07:01 pm - Permalink
i.e. whatever is entered into the text box in the panel (tmp=PauseforPrep) that appears.
String sID
EndStructure
Function Prep4AnalyseGBC()//(vVoltageAmplitude4TPParameters, sFirstDF, sLastDF)
//Variable vVoltageAmplitude4TPParameters
//String sFirstDF, sLastDF
NewDataFolder/O root:tmp_PauseforPrepDF
//String/G root:tmp_PauseforPrepDF:sID
String sID
//STRUCT strAnalyseGBC Prep4
DoWindow/K tmp_PauseforPrep
NewPanel/K=2 /W=(90,300,420,460)/N=tmp_PauseforPrep as "Enter wave info"
SetVariable svWaveID, title="Wave ID", fsize=14, pos={50,25}, size={150,50}, value=_STR:"", proc=Prep4AnalyseGBC_svWaveID
PauseForUser tmp_PauseforPrep
ControlInfo svWaveID
sID = s_value
//SVAR sID_G = root:tmp_PauseforPrep:sID
//sID receives an alternative designation as a global string variable.
//String sID = sID_G
//sID as a global variable is copied to a local string.
KillDataFolder root:tmp_PauseforPrepDF
//Print Prep4.sID
Print sID
End
Function Prep4AnalyseGBC_svWaveID (svWaveID, varNum, varStr, varName) : SetVariableControl
String svWaveID, varStr, varName
Variable varNum
//STRUCT strAnalyseGBC Prep4_svWaveID
//ControlInfo svWavelD
//print s_value
//Prep4_svWaveID.sID = s_value
//varStr = s_value
//print varStr
//String/G root:tmp_PauseforPrepDF:sID = varStr
//print sID
DoWindow/K tmp_PauseforPrep
End
July 30, 2014 at 09:08 am - Permalink
That's because you are killing the SetVariable control, by killing the panel, before you call ControlInfo.
Here is a way to achieve what you want.
STRUCT WMButtonAction &ba
switch(ba.eventCode)
case 2: // mouse up
ControlInfo/W=tmp_PauseforPrep svWaveID
String/G root:gPauseForUserOutput = S_value // Create global variable to store output
KillWindow tmp_PauseforPrep
break
endswitch
return 0
End
Function CreatePanel()
NewPanel /N=tmp_PauseforPrep /K=2 /W=(90,300,420,460) as "Enter wave info"
SetVariable svWaveID, title="Wave ID", fsize=14, pos={50,25}, size={150,50}, value=_STR:""
Button ContinueButton,pos={120,121},size={70,20},proc=ContinueButtonProc,title="Continue"
EndMacro
Function Demo()
CreatePanel()
PauseForUser tmp_PauseforPrep
SVAR output = root:gPauseForUserOutput // Access global variable to get output
Print output
End
July 30, 2014 at 09:36 am - Permalink
August 1, 2014 at 09:48 am - Permalink
There are two forms for the action procedure. The form that takes a ctrlName parameter is antiquated. The form that takes a reference to a structure is recommended.
August 1, 2014 at 12:57 pm - Permalink
Function Readjust_4Area(ba1) : ButtonControl
STRUCT WMButtonAction &ba1
switch(ba1.eventCode)
case 2: // mouse up
ControlInfo/W=PauseforReadjustment vMeasureArea
if (V_Flag == 0)
Variable/G root:gPauseForUserReadjust1 = 1
Variable/G root:gPauseForUserReadjust2 = 0
endif
KillWindow PauseforReadjustment
break
endswitch
//return 0
End
Function Readjust_4NoArea(ba2) : ButtonControl
STRUCT WMButtonAction &ba2
switch(ba2.eventCode)
case 2: // mouse up
ControlInfo/W=PauseforReadjustment vDoNotMeasureArea
if (V_Flag == 0)
Variable/G root:gPauseForUserReadjust2 = 2
Variable/G root:gPauseForUserReadjust1 = 0
endif
KillWindow PauseforReadjustment
break
endswitch
//return 0
End
Function CreateReadjustPanel(sGraphName)
String sGraphName
NewPanel/N=PauseforReadjustment/K=2 /W=(90,300,420,460) as "Cursor B readjustment panel"
DoWindow/C PauseforReadjustment
AutoPositionWindow/E/M=1/R=$sGraphName
DrawText 21,20,"Adjust cursor B for best area measurement"
Button button1,pos={65,35},size={220,10}, proc=Readjust_4Area,title= "Cursor B ready"
Button button2,pos={65,60},size={220,10},proc= Readjust_4NoArea, title= "Don't measure area"
EndMacro
Function Readjust_vReturn2BaseLoc (sGraphName)
String sGraphName
CreateReadjustPanel(sGraphName)
PauseForUser PauseforReadjustment, $sGraphName
NVAR vMeasureArea = root:gPauseForUserReadjust1
NVAR vDoNotMeasureArea = root:gPauseForUserReadjust2
if (vMeasureArea == 1)
return vMeasureArea
elseif (vDoNotMeasureArea == 2)
return vDoNotMeasureArea
endif
Printf "Results = %g\r and %g\r", vMeasureArea, vDoNotMeasureArea
End
<\igor>
August 6, 2014 at 10:54 am - Permalink
That's because your function returns before the Printf statement.
This statement makes no sense because you have no control named vDoNotMeasureArea:
Same for vMeasureArea.
You don't need to call ControlInfo for a button. The mere fact that your button action procedure was called means that the button was clicked.
August 6, 2014 at 12:42 pm - Permalink
STRUCT WMButtonAction &ba1
switch(ba1.eventCode)
case 2: // mouse up
Variable/G root:gPauseForUserReadjust1 = 1
Variable/G root:gPauseForUserReadjust2 = 0
KillWindow PauseforReadjustment
break
endswitch
return 0
End
Function Readjust_4NoArea(ba2) : ButtonControl
STRUCT WMButtonAction &ba2
switch(ba2.eventCode)
case 2: // mouse up
Variable/G root:gPauseForUserReadjust2 = 2
Variable/G root:gPauseForUserReadjust1 = 0
KillWindow PauseforReadjustment
break
endswitch
return 0
End
Function CreateReadjustPanel(sGraphName)
String sGraphName
NewPanel/N=PauseforReadjustment/K=2 /W=(90,300,420,460) as "Cursor B readjustment panel"
DoWindow/C PauseforReadjustment
AutoPositionWindow/E/M=1/R=$sGraphName
DrawText 21,20,"Adjust cursor B for best area measurement"
Button button1,pos={65,35},size={220,10}, proc=Readjust_4Area,title= "Cursor B ready"
Button button2,pos={65,60},size={220,10},proc= Readjust_4NoArea, title= "Don't measure area"
EndMacro
Function Readjust_vReturn2BaseLoc (sGraphName)
String sGraphName
CreateReadjustPanel(sGraphName)
PauseForUser PauseforReadjustment, $sGraphName
NVAR vMeasureArea = root:gPauseForUserReadjust1
NVAR vDoNotMeasureArea = root:gPauseForUserReadjust2
//Printf "Results = %g\r and %g\r", vMeasureArea, vDoNotMeasureArea
End
<\igor>
August 7, 2014 at 02:40 am - Permalink
PauseForUser
statement. You are using sGraphName as the target, and to cite the manualAugust 7, 2014 at 06:27 am - Permalink
But I should be able to click between the two windows without a problem - that is what is implied by the statement you cite from the manual. What happens now is that I can click on either window once execution pauses, but as soon as I click on the 'target window' I get stuck on it and cannot click on the panel (which seems to be locked in the background).
August 7, 2014 at 01:00 pm - Permalink
August 11, 2014 at 03:26 am - Permalink