1

I'm using the Perl IUP module implemented by kmx, I liked it due to ease of using it and somewhat ok look.

I need to create a Frame box with multiple button from a list (lets say 40-50). I can create this easily in a for loop going through the array (double Array, containing "Name" and value for each row) `

my @ChildsSetOfButtons=();
foreach $array (@ITEMNAME)
{
    $tempButton = IUP::Button->new( TITLE=>$array->[2],
                SIZE=>"50x20", FONTSTYLE=>'bold',FONTSIZE=>"10");
    $tempButton->ACTION( sub {selOrder($array->[3]); });
}
push(@ChildsSetOfButtons,$tempButton); 
my $tableOfButton = IUP::Frame->new( TITLE=>"Items",child=>
                IUP::GridBox->new( child=> [@ChildsSetOfButtons], NUMDIV=>4, 
                ORIENTATION=>"HORIZONTAL"), MARGIN=>"5x5",
                EXPANDCHILDREN =>"YES",GAPLIN=>10, GAPCOL=>10);

Well the Buttons appear in the GUI beautifully in a nice grid. Now my problem is, how I can send the individual unique values from each Button actions? I understand that the the values are statically linked at the time of creation of the button.

but somehow this similar implementation I could get it working in the PerlTK, Since I started with this IUP, I don't want to go back to TKperl and start writing my whole GUI from sratch. `

foreach my $array (@ITEMNAME)
{
    $fr2->Button(-text=>$array->[2],
                 -padx => 6,
                 -font => ['arial', '10', 'normal'],
                 -foreground  => 'blue',
                 -command => [\&writeUARTDirect,$array->[3]],
                )->pack(-side=>'bottom');
}

` How can I get it worked in the perl-IUP framework? Can anyone tell me a trick ? :)

Aravind Nadumane
  • 170
  • 1
  • 11

1 Answers1

2

There are some issues with your example. I added a bit to make it runnable:

use IUP ':all';
use strict;
use warnings;
use v5.30;

my @ITEMNAME = ([0,0,foo=>'btn_foo'],
                [0,0,bar=>'btn_bar']
                );
my @ChildsSetOfButtons=();
foreach my $array (@ITEMNAME)
{
    my $tempButton = IUP::Button->new(
                                      TITLE=>$array->[2],
                                      SIZE=>"50x20",
                                      FONTSTYLE=>'bold',
                                      FONTSIZE=>"10");

    # alternative: copied value
    # my $value = $array->[3];
    # $tempButton->ACTION( sub {selOrder($value); });

    $tempButton->ACTION( sub {selOrder($array->[3]); });

    push(@ChildsSetOfButtons,$tempButton);

}
my $tableOfButton = IUP::Frame->new(
                TITLE=>"Items",
                child=>
                    IUP::GridBox->new( child=> [@ChildsSetOfButtons],
                                       NUMDIV=>4, 
                                       ORIENTATION=>"HORIZONTAL"),
                MARGIN=>"5x5",
                EXPANDCHILDREN =>"YES",
                GAPLIN=>10,
                GAPCOL=>10);
my $dlg = IUP::Dialog->new( TITLE=>"Test Dialog",
                            MARGIN=>"10x10",
                            child=> $tableOfButton,);

# Do you want changes like these being reflected in the callback?
$ITEMNAME[1]->[3] = 'another_value';
$ITEMNAME[0] = [];    

$dlg->Show;

IUP->MainLoop;

sub selOrder{
    my $val = shift;
    say "you pressed $val";
}

I added strict and made your variables lexical. You were creating the buttons in a loop but the push statement was outside of the loop. So your buttons were not added to @ChildsSetOfButtons.

Your callback sub references $array->[3] which is an alias into @ITEMNAME this might lead to unintended side effects if the values in @ITEMNAME are changed. You can avoid that by copying the value into a lexical variable inside the loop and use that in your callback. This way you get a closure with the value decoupled from @ITEMNAME.

clamp
  • 2,552
  • 1
  • 6
  • 16
  • my Push statement was inside the loop, during the code formatting in the Question post I might have moved it down. But your solution with the "alternative: copied value" has worked for me!! I took your source as it is and try to run. Since I have Perl 5.28, i removed the dependencies and experimented with the alternate solution of copying locally and it worked like Gem. Perhaps your code as it is will work in the 5.32 out of the box. I will update my perl in sometime to the latest. Many thanks again and it saved my day :) – Aravind Nadumane Jan 30 '21 at 15:47
  • The version statement does not matter. (Except for say() which has long been available.) – clamp Jan 30 '21 at 15:59