Page 1 of 2

Help needed for a list of radio buttons

Posted: 26 Jul 2014, 23:49
by DyNama
Hi gang, newbie's first question here, and my first try at a GUI.

This group of radio buttons returns the number but I need the word that was selected. This works--hurray!--to pick a color from a list and have it typed into notepad but these If statements look clumsy.

I thought maybe an array (Blue, Green, Orange, Purple, Yellow, White, Passthru) using the radio button number as the index would work but I couldn't find the correct syntax for the Send. Can someone please tell me what's the best way to do this?

Code: Select all

!F3::  ;alt+F3
   Gui, New
   Gui, Add, Radio, vBatt, &Blue 1500mah
   Gui, Add, Radio,, &Green 1300mah
   Gui, Add, Radio,, &Orange 1300mah
   Gui, Add, Radio,, &Purple 1300mah
   Gui, Add, Radio,, &Yellow 2200mah
   Gui, Add, Radio,, &White 1600mah
   Gui, Add, Radio,, P&assthru
   Gui, Add, Button, Default, Submit
   Gui, Show,, Choose Battery
   return
   GuiClose:
   ButtonSubmit:
   Gui, Submit
   If Batt = 1
      Batt = Blue
   If Batt = 2
      Batt = Green
   If Batt = 3
      Batt = Orange
   If Batt = 4
      Batt = Purple
   If Batt = 5
      Batt = Yellow
   If Batt = 6
      Batt = White
   If Batt = 7
      Batt = Passthru
   WinActivate, Untitled - Notepad
   Send %Batt%
   return

Re: Help needed for a list of radio buttons

Posted: 27 Jul 2014, 01:02
by Blackholyman
array example

Code: Select all

Radio := ["Blue", "Green", "Orange", "Purple", "Yellow", "White", "Passthru"]

!F3::  ;alt+F3
Gui, New
Gui, Add, Radio, vBatt, &Blue 1500mah
Gui, Add, Radio,, &Green 1300mah
Gui, Add, Radio,, &Orange 1300mah
Gui, Add, Radio,, &Purple 1300mah
Gui, Add, Radio,, &Yellow 2200mah
Gui, Add, Radio,, &White 1600mah
Gui, Add, Radio,, P&assthru
Gui, Add, Button, Default, Submit
Gui, Show,, Choose Battery
return

GuiClose:
ButtonSubmit:
Gui, Submit
WinActivate, Untitled - Notepad
Send % radio[batt]
return
Hope it helps

Re: Help needed for a list of radio buttons

Posted: 27 Jul 2014, 01:39
by DyNama
That is much more attractive, Blackholyman! I could've sworn i tried Send % radio[batt] but I guess not. Thanx!

I wonder if, to avoid the possibility of associating the radio button with the wrong array entry, the GUI could reference the array too?

Gui, Add, Radio, vBatt, % radio[1] 1500mah
Gui, Add, Radio,, % radio[2] 1300mah
Gui, Add, Radio,, % radio[3] 1300mah
Gui, Add, Radio,, % radio[4] 1300mah
Gui, Add, Radio,, % radio[5] 2200mah
Gui, Add, Radio,, % radio[6] 1600mah
Gui, Add, Radio,, % radio[7]

I tried this and it works! but I have to give up the &keyboard focus key, and the power rating gets cut off.

My first GUI and the first time I got an array to work! Thanx, Blackholyman!

Re: Help needed for a list of radio buttons

Posted: 27 Jul 2014, 02:14
by Blackholyman
Great

the % is used to Force an expression and therefore you need to enclose strings in double quotes % radio[1] " 1500mah"

and you can use regex to remove the & from the button text before you send it

Code: Select all

Radio := ["&Blue", "&Green", "&Orange", "&Purple", "&Yellow", "&White", "P&assthru"]

!F3::  ;alt+F3
Gui, New
Gui, Add, Radio, vBatt, % radio[1] " 1500mah"
Gui, Add, Radio,, % radio[2] " 1300mah"
Gui, Add, Radio,, % radio[3] " 1300mah"
Gui, Add, Radio,, % radio[4] " 1300mah"
Gui, Add, Radio,, % radio[5] " 2200mah"
Gui, Add, Radio,, % radio[6] " 1600mah"
Gui, Add, Radio,, % radio[7]
Gui, Add, Button, Default, Submit
Gui, Show,, Choose Battery
return

GuiClose:
ButtonSubmit:
Gui, Submit
WinActivate, Untitled - Notepad
Send % RegExReplace(radio[batt], "&", "")
return
Hope it helps

Re: Help needed for a list of radio buttons

Posted: 27 Jul 2014, 12:12
by DyNama
That is marvelous, Blackholyman! I know little about RegEx so that never would've occurred to me. And I tried concatenation dot . with the power rating but never thought of quotes. I've spent hours triyng to get AHK syntax right! Thanx for your help, and this learning experience!

Re: Help needed for a list of radio buttons

Posted: 29 Jul 2014, 14:15
by DyNama
Ok, so here's another question. Suppose i add some more batteries to the list? is there a way i can just add the new entries to the array and the radio button group be populated by counting the elements and sequentially stepping thru the array?

[Later] I figured out how to do that except for how to count how many items are in the array. I still don't know how to do that (Battery.maxindex?) , but i figured out how to make it loop until it gets to a blank array item.

I also have it cut off the array item at the 1st space to Send (here to Notepad, actually to a battery log in Evernote) so the power rating, which is just for my information, and to flesh out the box cuz it's pretty tiny on my 17" laptop, can be part of each item in the array.

So here's my "masterpiece" so far. Thanx for your help, Blackholyman, it encouraged me to keep fiddling with it! This may come in very handy for other future lists.

Code: Select all

!F3::  ;alt+F3
Battery :=["&Blue 1500mah" 
	, "&Green 1300mah" 
	, "&Orange 1300mah" 
	, "&Purple 1300mah" 
	, "&Yellow 2200mah" 
	, "&White 1600mah" 
	, "P&assthru " 
	, "&LtBlue 350mah"
	, "&Fuchsia 1600mah"
	, "&Stripey 2200mah"]

   Gui, New
   Gui, Add, Radio, vBatt, % Battery[1]
   Arraycount := 2
   Loop  ;number of items in array - 1
	{
		Gui, Add, Radio,, % Battery[Arraycount]
		Arraycount := ++Arraycount
	}	until Battery[Arraycount] = ""
   Gui, Add, Button, Default, Submit
   Gui, Show,, Choose Battery
return

   GuiClose:
   ButtonSubmit:
   Gui, Submit
   DetectHiddenWindows On
   WinActivate ahk_class Notepad
;   Send !n{space} ;alt-n: my AHK routine that sends the date
   Entry := RegExReplace(Battery[batt], "&", "")
   Entry := Substr(Entry, 1, Instr(Entry, " ")-1)
   Send %Entry%
return

Re: Help needed for a list of radio buttons

Posted: 29 Jul 2014, 18:46
by FanaticGuru
Here is a little bit different approach that allows for better formatting and possible better usage of the data by separating the color and amps so they are not stored in one string.

Code: Select all

Batteries := [	 {"&Blue":"1500mah"}
				,{"&Green":"1300mah"}
				,{"&Orange":"1300mah"}
				,{"&Purple":"1300mah"}
				,{"&Yellow":"2200mah"}
				,{"&White":"1600mah"}
				,{"P&assthru":" "}
				,{"&LtBlue":"350mah"}
				,{"&Fuchsia":"1600mah"}
				,{"&Stripey":"2200mah"}]
!F3::
	Gui, New
	for key, Battery in Batteries
		for Color, Amp in Battery
		{
			if !Label
			{
				Gui, Add, Radio, vRadio_Battery, % Color
				Label := true
				continue
			}
			Gui, Add, Radio,yp+20, % Color
		}
	Gui, Add, Text, ym-20   
	for key, Battery in Batteries
		for Color, Amp in Battery
			Gui, Add, Text, x80 yp+20, % Amp
	Gui, Add, Button, Default, &Submit
	Gui, Show,, Choose Battery
return

GuiClose:
GuiEscape:
ExitApp

ButtonSubmit:
	Gui, Submit
	for Color, Amp in Batteries[Radio_Battery]
		MsgBox % RegExReplace(Color,"&") "`t" Amp
	ExitApp
return
FG

Re: Help needed for a list of radio buttons

Posted: 29 Jul 2014, 20:45
by DyNama
FanaticGuru wrote:Here is a little bit different approach that allows for better formatting and possible better usage of the data by separating the color and amps so they are not stored in one string.
OMG, that is beautiful, FG! Now what exactly is that, and where do i read AHK help on it?

I'm assigning it a hotkey for the routine to be easily available so i commented out the ExitApp in the ButtonSubmit: subroutine, but when i pressed the hotkey a second time, the GUI appeared but the colors and amps were off by a line and it returns the color chosen the 1st time not the 2nd. i tried adding Color := to clear the previous run but that didn't do it. what do i need to clear to run the program more than once? For now i'll replace that ExitApp with Reload.

Re: Help needed for a list of radio buttons

Posted: 29 Jul 2014, 22:03
by toralf
Instead of ExitApp use GUI,Destroy.

Re: Help needed for a list of radio buttons

Posted: 29 Jul 2014, 22:58
by DyNama
toralf wrote:Instead of ExitApp use GUI,Destroy.
thanx, toralf! Forgive my ignorance about GUI, though, i replaced both ExitApps with Gui, Destroy but it didn't work any better the 2nd time.

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 10:49
by toralf
This worked for me. The line Gui, New cause some problem. Don't know why, maybe a bug. I'll pots a simplified version in the bug forum.

Code: Select all

Batteries := [   {"&Blue":"1500mah"}
                ,{"&Green":"1300mah"}
                ,{"&Orange":"1300mah"}
                ,{"&Purple":"1300mah"}
                ,{"&Yellow":"2200mah"}
                ,{"&White":"1600mah"}
                ,{"P&assthru":" "}
                ,{"&LtBlue":"350mah"}
                ,{"&Fuchsia":"1600mah"}
                ,{"&Stripey":"2200mah"}]
for key, Battery in Batteries
    for Color, Amp in Battery
        if !Label {
            Gui, Add, Radio, vRadio_Battery, % Color
            Label := true
            continue
        }Else
            Gui, Add, Radio, y+10, % Color
First = True  
for key, Battery in Batteries
    for Color, Amp in Battery
      If First {
        Gui, Add, Text, ys, % Amp
        First := False        
      } Else
        Gui, Add, Text, y+10, % Amp
Gui, Add, Button, Default, &Submit
Gui, Show,  AutoSize, Choose Battery
Return
                
F3::
    Gui, Show,  
return

GuiClose:
GuiEscape:
    Gui, Submit
Return

Esc::
 ExitApp
Return

ButtonSubmit:
    Gui, Submit, 
    for Color, Amp in Batteries[Radio_Battery]
        MsgBox % RegExReplace(Color,"&") "`t" Amp
return

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 14:37
by FanaticGuru
DyNama wrote:I'm assigning it a hotkey for the routine to be easily available so i commented out the ExitApp in the ButtonSubmit: subroutine, but when i pressed the hotkey a second time, the GUI appeared but the colors and amps were off by a line and it returns the color chosen the 1st time not the 2nd. i tried adding Color := to clear the previous run but that didn't do it. what do i need to clear to run the program more than once? For now i'll replace that ExitApp with Reload.
You really only need to create the Gui once in the Auto-Execute section of the code and then just show and hide it from then on.

Code: Select all

Batteries := [	 {"&Blue":"1500mah"}
				,{"&Green":"1300mah"}
				,{"&Orange":"1300mah"}
				,{"&Purple":"1300mah"}
				,{"&Yellow":"2200mah"}
				,{"&White":"1600mah"}
				,{"P&assthru":" "}
				,{"&LtBlue":"350mah"}
				,{"&Fuchsia":"1600mah"}
				,{"&Stripey":"2200mah"}]

for key, Battery in Batteries
	for Color, Amp in Battery
	{
		if !Label
		{
			Gui, Add, Radio, vRadio_Battery, % Color
			Label := true
			continue
		}
		Gui, Add, Radio,yp+20, % Color
	}
Gui, Add, Text, ym-20   
for key, Battery in Batteries
	for Color, Amp in Battery
		Gui, Add, Text, x80 yp+20, % Amp
Gui, Add, Button, Default, &Submit

!F3::
	Gui, Show,, Choose Battery
return

ButtonSubmit:
	Gui, Submit, NoHide ; Remove "NoHide" to make Gui disappear after each submit
	for Color, Amp in Batteries[Radio_Battery]
		MsgBox % RegExReplace(Color,"&") "`t" Amp
return

GuiClose:
GuiEscape:
	Gui, Hide
return
This is a better practice for working with Gui's and more how I actually code my Gui's.

FG

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 14:51
by FanaticGuru
DyNama wrote:OMG, that is beautiful, FG! Now what exactly is that, and where do i read AHK help on it?
This code is mainly just about understanding Objects and how to use For-Loops to loop through the elements of an object.

And using ym (Y margin) and yp (Y previous) to position things in the Gui.

To see the structure of the Batteries Object you can add this code at the end of the script:

Code: Select all

/*
; inspired by Lexikos ExploreObj()
PrintArr
   Prints the layout of an array (in text form) so that you can easily
   see the layout of it.

   array = The input array. Don't add the []'s.
   depth = How deep should we go if there are arrays within arrays?
   * indentLevel should not be touched as it's hard-coded in! DO NOT TOUCH.

example: st_printArr([["aaa","bbb","ccc"],[111,222,333]])
output:
[1]
    [1] ==> aaa
    [2] ==> bbb
    [3] ==> ccc

[2]
    [1] ==> 111
    [2] ==> 222
    [3] ==> 333
*/
st_printArr(array, depth=5, indentLevel="")
{
   for k,v in Array
   {
      list.= indentLevel "[" k "]"
      if (IsObject(v) && depth>1)
         list.="`n" st_printArr(v, depth-1, indentLevel . "    ")
      Else
         list.=" => " v
      list.="`n"
   }
   return rtrim(list)
}
Then put MsgBox % ST_printarr(Batteries) right after the Batteries Object is defined to see its structure. Seeing the structure of the Object in a graphical way should help you to understand what the For-Loops are doing.

This function is from the String Things library that can be found here:
http://ahkscript.org/boards/viewtopic.php?f=6&t=53

FG

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 16:49
by DyNama
toralf wrote:This worked for me. The line Gui, New cause some problem. Don't know why, maybe a bug. I'll pots a simplified version in the bug forum.
Thanx, toralf! That works! And now i know how to highlight a few words of code in this forum so i won't have to color them red. :lol:
FanaticGuru wrote:
DyNama wrote:OMG, that is beautiful, FG! Now what exactly is that, and where do i read AHK help on it?
This code is mainly just about understanding Objects and how to use For-Loops to loop through the elements of an object.

[...]

Then put MsgBox % ST_printarr(Batteries) right after the Batteries Object is defined to see its structure. Seeing the structure of the Object in a graphical way should help you to understand what the For-Loops are doing.

This function is from the String Things library that can be found here:
http://ahkscript.org/boards/viewtopic.php?f=6&t=53

FG
ok, Objects. This will take some study. I've heard of programming languages becoming "object-oriented" but i never tried any of them, coding in BASIC in the 80s and AutoLISP within AutoCAD in the 90s. I've never really tried to learn higher-level languages. That's why AHK has got me excited--I'm programming again, and these are my first programs for Windows!

1 thing i can point out:

Code: Select all

if !Label {
            Gui, Add, Radio, vRadio_Battery, % Color
            Label := true
            continue
        }Else
            Gui, Add, Radio, y+10, % Color
i have tried to make flags a dozen times--setting a flag like Label to branch a program at some point--but never got one to work. if I understand it:

Code: Select all

if !Label {  ;;if Label is blank/nil
            Gui, Add, Radio, vRadio_Battery, % Color  ;;add this radio button with variable
            Label := true  ;;then put something in Label
            continue  ;;skips the rest of the Loop, never used this before
        }Else ;; if Label is not nill
            Gui, Add, Radio, y+10, % Color ;;add the rest of the radio buttons without a variable
so learning this will be very handy for some of my other projects.

I like the idea of making the GUI once and hiding it between uses, that sounds nice and tidy. I actually already have a String Things library (maybe not the latest), was just putting ST_delete in a program yesterday!

Thanx, FanaticGuru, i will definitely study this! Thanx too to toralf and Blackholyman!

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 17:31
by kon
@FanaticGuru
My personal preference would be to avoid looping through an object that only has one key/value pair. With some slight changes to your code we get this:

Code: Select all

Batteries := [   ["&Blue",    "1500mah"]
                ,["&Green",   "1300mah"]
                ,["&Orange",  "1300mah"]
                ,["&Purple",  "1300mah"]
                ,["&Yellow",  "2200mah"]
                ,["&White",   "1600mah"]
                ,["P&assthru",      " "]
                ,["&LtBlue",   "350mah"]
                ,["&Fuchsia", "1600mah"]
                ,["&Stripey", "2200mah"]]

for key, Battery in Batteries
    if (key = 1)
		Gui, Add, Radio, vRadio_Battery, % Battery.1
    else
		Gui, Add, Radio, yp+20, % Battery.1

; Or ternary version of above
;for key, Battery in Batteries
;	Gui, Add, Radio, % key = 1 ? "vRadio_Battery" : "yp+20", % Battery.1

Gui, Add, Text, ym-20

for key, Battery in Batteries
	Gui, Add, Text, x80 yp+20, % Battery.2

Gui, Add, Button, Default, &Submit

!F3::
	Gui, Show,, Choose Battery
return

ButtonSubmit:
	Gui, Submit, NoHide
	MsgBox % RegExReplace(Batteries[Radio_Battery].1, "&") "`t" Batteries[Radio_Battery].2
return

GuiClose:
GuiEscape:
	Gui, Hide
return
Edit: Also, instead of setting a flag, we can just check if key = 1.

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 18:05
by FanaticGuru
kon wrote:@FanaticGuru
My personal preference would be to avoid looping through an object that only has one key/value pair.

Edit: Also, instead of setting a flag, we can just check if key = 1.
Yea, I can understand the not liking to loop through an object of one because it could cause some confusing because you are not really looping multiply times but I like how it makes the script descriptive and readable by being able to give names to the key and value in the object.

But I do like eliminating block braces when possible and like the assigning and using of the Label all in one to get things down to one line in the If-Statement.

New and improved code:

Code: Select all

Batteries := [	 {"&Blue":"1500mah"}
				,{"&Green":"1300mah"}
				,{"&Orange":"1300mah"}
				,{"&Purple":"1300mah"}
				,{"&Yellow":"2200mah"}
				,{"&White":"1600mah"}
				,{"P&assthru":" "}
				,{"&LtBlue":"350mah"}
				,{"&Fuchsia":"1600mah"}
				,{"&Stripey":"2200mah"}]

for key, Battery in Batteries
	for Color, Amp in Battery
		if Label
			Gui, Add, Radio,yp+20, % Color
		else
			Gui, Add, Radio, % Label := "vRadio_Battery", % Color
Gui, Add, Text, ym-20   
for key, Battery in Batteries
	for Color, Amp in Battery
		Gui, Add, Text, x80 yp+20, % Amp
Gui, Add, Button, Default, &Submit

!F3::
	Gui, Show,, Choose Battery
return

ButtonSubmit:
	Gui, Submit, NoHide ; Remove "NoHide" to make Gui disappear after each submit
	for Color, Amp in Batteries[Radio_Battery]
		MsgBox % RegExReplace(Color,"&") "`t" Amp
return

GuiClose:
GuiEscape:
	Gui, Hide
return
FG

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 18:24
by kon
Yeah, I don't know what would be more confusing to a user new to objects, nested for-loops but with the advantage of names, or obj[x].1 type syntax. Probably a toss-up.

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 19:24
by DyNama
yep, a toss up! whew!

Re: Help needed for a list of radio buttons

Posted: 30 Jul 2014, 21:52
by toralf
Just to throw in another variant, that combines some of the earlier pros and cons.

Code: Select all

Batteries := [   {Color: "&Blue",    AMP: "1500mah"}
                ,{Color: "&Green",   AMP: "1300mah"}
                ,{Color: "&Orange",  AMP: "1300mah"}
                ,{Color: "&Purple",  AMP: "1300mah"}
                ,{Color: "&Yellow",  AMP: "2200mah"}
                ,{Color: "&White",   AMP: "1600mah"}
                ,{Color: "P&assthru",AMP: " "}
                ,{Color: "&LtBlue",  AMP: " 350mah"}
                ,{Color: "&Fuchsia", AMP: "1600mah"}
                ,{Color: "&Stripey", AMP: "2200mah"}]

For key, Battery in Batteries
  If (key = 1)
    Gui, Add, Radio, vRadio_Battery , % Battery.Color "  -  " Battery.AMP
  Else
    Gui, Add, Radio, xm, % Battery.Color "  -  " Battery.AMP

Gui, Add, Button, Default, &Submit
Return

F3::
  Gui, Show,, Choose Battery
return

ButtonSubmit:
  Gui, Submit, NoHide
  Color := StrSplit(Batteries[Radio_Battery].Color, "&")
  MsgBox % Color.1 Color.2 " - " Batteries[Radio_Battery].AMP
return

GuiClose:
GuiEscape:
  Gui, Hide
return

Re: Help needed for a list of radio buttons

Posted: 31 Jul 2014, 12:27
by FanaticGuru
toralf wrote:Just to throw in another variant, that combines some of the earlier pros and cons.

Code: Select all

Batteries := [   {Color: "&Blue",    AMP: "1500mah"}
                ,{Color: "&Green",   AMP: "1300mah"}
                ,{Color: "&Orange",  AMP: "1300mah"}
                ,{Color: "&Purple",  AMP: "1300mah"}
                ,{Color: "&Yellow",  AMP: "2200mah"}
                ,{Color: "&White",   AMP: "1600mah"}
                ,{Color: "P&assthru",AMP: " "}
                ,{Color: "&LtBlue",  AMP: " 350mah"}
                ,{Color: "&Fuchsia", AMP: "1600mah"}
                ,{Color: "&Stripey", AMP: "2200mah"}]

For key, Battery in Batteries
  If (key = 1)
    Gui, Add, Radio, vRadio_Battery , % Battery.Color "  -  " Battery.AMP
  Else
    Gui, Add, Radio, xm, % Battery.Color "  -  " Battery.AMP

Gui, Add, Button, Default, &Submit
Return

F3::
  Gui, Show,, Choose Battery
return

ButtonSubmit:
  Gui, Submit, NoHide
  Color := StrSplit(Batteries[Radio_Battery].Color, "&")
  MsgBox % Color.1 Color.2 " - " Batteries[Radio_Battery].AMP
return

GuiClose:
GuiEscape:
  Gui, Hide
return
I started to do it this way at one point and is generally the best way in a full blown script. When doing complex multi-dimensional arrays, if you keep the keys to descriptive and the values to the actual data, it makes the code easier to read and helps keep things straight. It is better standard practice. When you start using the actual data as keys it is generally a shortcut that sometimes can make it hard to get the information back out of the data structure, especially when the array gets deep with dimensions. If you spend the time to structure the data right at the beginning the coding is easier. Often times on more complex scripts I will spend a great deal of time just thinking about how I want to structure the data before I even begin coding. It is a real pain when you have a 1000 lines of code and then need to change the data structure to add a feature, which messes up all your code that uses that data structure.

Code above looks good, I don't really care for the splitting of the color at the end to remove the "&". Seems RegExReplace would be better suited but the rest of it is great.

I know the original questions has been answered three times over but good to see different programming techniques. Often times on the forums people will answer questions with a clever trick that works for that specific question but is a shortcut and not good standard practices for coding in general. Which is fine for short scripts but if that script grows into a large utility that then needs to be modified down the road, it can be very problematic.

FG