iMisspell has asked for the wisdom of the Perl Monks concerning the following question:

Hello all, looking for some guidance using Radiobuttons in a program im creating.

Heres the scoop.
I have a sql-table; id, type, file and path ('type' is used as a "flag" to determine if the file is an 'Install' file or an 'Update' file (which is where the Radio buttons come in)).


Im dynamically create a bunch of Radio-buttons with the code below (image included).

What i would like is to have rows of "install/update" buttons with a label to the right of the two RadioButtons (which ive been successful in doing), but im having a problem with toggling the buttons.
Ive tried a bunch of things, placing the r-buttons in frames, not in frames, changing the RadioButtons 'value' and 'variable'. No matter what ive tried, i can not get the buttons to toggle correctly and display correclty. When toggling, ether all the 'install' buttons become selected when only selecting one, or only a single buttons is selected and not toggling anything, or selecting 'install' on a row will select both buttons on that row, but never toggling each row correctly.
When the buttons are first displayed, none of them are 'selected', all buttons are 'deselected'.

All the arrays are being filled correctly, used 'print' to double check. The r-button '-command =>' works correctly and sets the correct information in the sub it calls.

Heres the code
sub setExensionFilesChk{ my $index1 = $_[0] || return ; $index1 = ($index1 -1); my $extNameIs = "$extensionNames[$index1][0]"; #print "* $extNameIs *\n"; @extensionFiles=(); @extensionFileBothInstall=(); my $q = $db->query("SELECT filelist_id, filelist_type, filelist_pa +th, filelist_file FROM filelist WHERE filelist_extension = '$extNameI +s'"); while (my $ref = $q->fetchrow_hashref() ) { #print "$$ref{'filelist_file'}\n"; push @extensionFiles, [ $$ref{'filelist_id'}, $$ref{'filelist_ +type'}, $$ref{'filelist_path'}, $$ref{'filelist_file'} ]; push @extensionFileBothInstall, [ $$ref{'filelist_id'}, $$ref{ +'filelist_type'} ]; } $extFileFrame->destroy if $extFileFrame; $extFileFrame = $fileListPane -> Frame(); $extFileFrame->configure( -width=>500, -height=>400 ); $extFileFrame -> grid(-row=>1,-column=>1,-columnspan=>3,-sticky=>" +nw"); my $names; my $i = 0; my $rdb; for $names ( @extensionFiles ) { $i++; if("@$names[1]" eq "both"){ #print "@$names[3]\n"; my $FileFrame = $extFileFrame -> Frame(); $FileFrame -> grid(-row=>($i + 1),-column=>1,-columnspan=> +3,-sticky=>"nw"); $rdb = $FileFrame -> Radiobutton(-text=>"Both", -value=>"@ +$names[0]", -variable=>"@$names[1]", -command => [ \&setFileBothInsta +ll, "@$names[0]", 'both' ]); $rdb -> select(); $rdb -> grid(-row=>(1),-column=>0, -sticky=>"w"); $rdb = $FileFrame -> Radiobutton(-text=>"Install", -value= +>"@$names[0]", -variable=>"@$names[1]", -command => [ \&setFileBothIn +stall, "@$names[0]", 'install' ]); $rdb -> deselect(); $rdb -> grid(-row=>(1),-column=>1, -sticky=>"w"); my $lab = $FileFrame -> Label(-text=>" - @$names[2]@$names +[3]"); $lab -> grid(-row=>(1),-column=>2, -sticky=>"w"); } else { } } my $lbl_extName = $extFileFrame -> Label(-text=>"($i) Extension Fi +les:"); $lbl_extName -> grid(-row=>1,-column=>0,-columnspan=>3); $extensionsFilesWindow->update; }
And an image to get a visual, the five r-buttons on the left are used to call the sub posted above which will retrieve the file names & paths from the sql-table and display them to the list on the right, which is where the problem is.
http://thewwwaddress.com/AddExtensonFileToSQL.jpg

Thanks for any help with this...
--------------------------
The following will explane what im doing with the program, if you care to know.
I have developed a couple of Mediawiki extensions.
Now i would like to create a general perl app to create two .tar files, one will be the Full install (with config, language and image files) the second will be be for Updates (with-out config, language and image files) along with the appropriate Install and Update SQL info.

The code above is only a small part of the program, the "input stage" for my local dbase which will hold info (SQL table names and files names & paths). There is another window in the program which i can select and scan a dir and its sub folders, collect the file names and paths, save them to my local dbase along with acouple 'if' checks on the files extensions to be able to "flag" them 'Install' or 'Both' ('both' meaning the file is used for the Install and the Update).
Theres a problem, while "inputting" these file names to my local dbase, there are some files which are not flagged correctly and thats where the sub routine above comes in. Instead of manually changing the flag in the dbase, i thought i would go about it with the code above. When one of the Radiobuttons above is toggled, it will call a 'sub' and update the 'flag' for that file (using the setFileBothInstall() routine (not posted here) passing 'filelist_id', 'install' or 'both' depending on which radio button is toggled) in my local dbase.
So theres the story :)

Replies are listed 'Best First'.
Re: Tk: Dynamic Radiobuttons toggle problem...
by keszler (Priest) on Feb 27, 2010 at 02:03 UTC
    I think your problem is that you're assigning the same -value to each Radiobutton.

    In the following code, Radiobuttons "first" and "second" have the same -value. The "third" has a different -value. When you run it, clicking either the "first" or "second" selects both of them; clicking the "third" selects just that one.

    use strict; use warnings; use Tk; use Tk::Radiobutton; my $rb_value; my $mw = Tk::MainWindow->new; $mw->Radiobutton(-text=>'first',-value=>'one',-variable=>\$rb_value)-> +pack; $mw->Radiobutton(-text=>'second',-value=>'one',-variable=>\$rb_value)- +>pack; $mw->Radiobutton(-text=>'third',-value=>'three',-variable=>\$rb_value) +->pack; MainLoop; print $rb_value,$/;
    Changing the -value of the second Radiobutton to 'two' makes it independent from the first.
      Thanks for the feed back.

      Ive tried the following (as posted above)...
      -value=>"@$names[0]" ($names[0] = ID for that file)
      When toggling, each row will stay independent, but selecting one button will also select the other, both working together and not toggling back and forth, per row.

      -value=>"one" -value=>"two"
      Toggling "Install" will select all 'install' buttons for all rows, toggling "update" will de-select the "install" rows and select all 'update' rows (being 'one' and 'two' are now constants ??).

      -value=>"both_@$names[0]" -value=>"install_@$names[0]"
      ($names[0] = ID for that file)
      Makes all buttons independent, no matter what row is selected, the buttons will toggle to that single button.

      In the while-loop, i have my $FileFrame = $extFileFrame -> Frame();
      Doesnt that create a new "instance" of a frame which will be placed in the "parent" container/frame '$extFileFrame' ?
      If so, by placing the two radio buttons (install and update) with $rdb = $FileFrame -> Radiobutton() they are being placed in there own container, and since each container is a new row, rows should not effect each other ???


      Only reason im tring to go with this route now, is because i cant get it working ;) and being new to perl i would like to learn what im doing wrong.

      An alternative which would fit my needs is just create a label with the 'type' flag in it so i can visualy see if the file is for Install or for Update and then place two "normal" cmd_Buttons next to the row, it does not have to be nice and pritty, but i would like to know what im doing wrong with the code above.


      _
        Radiobuttons that have the same -value and -variable are effectively the same button, even if there are dozens of instances.

        Putting Radiobuttons in different Frames does not group them; they are grouped by sharing the same -variable and distinguished within the group by different -values.

        The -variable for the Radiobutton should be a reference to a scalar, e.g. \$something, \$hash{key}, \$array[6], etc. When the Radiobutton is selected - by the user or by calling $rdb->select - the -variable assigned to it is set to its -value. The reverse is also true: if the code sets the $something to a value matching a Radiobutton's -value, that Radiobutton becomes selected.

        use strict; use warnings; use Tk; use Tk::Radiobutton; my $mw = Tk::MainWindow->new; my $rb_value; # undef, no Radiobutton selected $mw->Radiobutton(-text=>'first',-value=>'one',-variable=>\$rb_value)-> +pack(-anchor=>'w'); $mw->Radiobutton(-text=>'second',-value=>'one',-variable=>\$rb_value)- +>pack(-anchor=>'w'); $mw->Radiobutton(-text=>'third',-value=>'three',-variable=>\$rb_value) +->pack(-anchor=>'w'); $mw->Label(-text=>'------------------------')->pack; my $other_value = '0000ff'; # preset blue $mw->Radiobutton(-text=>'RED',-value=>'ff0000',-variable=>\$other_valu +e)->pack(-anchor=>'w'); $mw->Radiobutton(-text=>'GREEN',-value=>'00ff00',-variable=>\$other_va +lue)->pack(-anchor=>'w'); $mw->Radiobutton(-text=>'BLUE',-value=>'0000ff',-variable=>\$other_val +ue)->pack(-anchor=>'w'); MainLoop; print 'rb:',$rb_value,$/; print 'other:',$other_value,$/;
Re: Tk: Dynamic Radiobuttons toggle problem...
by stefbv (Priest) on Feb 27, 2010 at 15:35 UTC

    In addition to the clear explanations provided by keszler, here is a small demo that you may find useful, I hope:

    use strict; use warnings; use Tk; my $top = MainWindow->new; $top->title("Radio"); my %wb; # radio buttons hash # Create 4 radio buttons trick; # cant't remember from where I got it :( # -variable is set to default (see man page) # -value is lower case of label foreach my $label (qw/Top Left Right Bottom/) { my $lower = lc $label; $wb{$lower} = $top->Radiobutton( -text => $label, -relief => 'flat', -value => $lower, -indicatoron => 0, -width => 7, -command => [\&cb_rbutton,$lower], )->pack; } $top->Button( -text => 'Flash', -width => 10, -command => [\&cb_button, \%wb], )->pack; Tk::MainLoop; sub cb_rbutton { # Radio button selected my $rb = shift; print ucfirst($rb), " is on\n"; return; } sub cb_button { # Button released my $rb = shift; foreach my $label ( keys %{$rb} ) { my $variable = $rb->{$label}->cget('-variable'); if ( ! defined ${$variable} ) { # No check button selected print " Select a button!\n"; last; } # When a check button is selected, all 4 buttons value will be # set to $label of the selected check button # To find out which one is selected: print " CB: $label -> ${$variable}\t"; if ( ${$variable} eq $label ) { print "selected, flashing"; $rb->{$label}->flash; print " ...\n"; } else { print "\n"; } } return; }