http://qs321.pair.com?node_id=271574
Category: GUI Programming
Author/Contact Info Jay Madigan (PERLscienceman) perlsciman@hotmail.com
Description: I was reading through nodes and found one on Matrices (reference Node ID 267624 "Code to solve Matrix Formation Puzzle"). It reminded me of a little TK app. that I put together that solves a user input 3X3 Matrix. The code is in the early stages of my experimenting with Perl/Tk. I am certain that in some areas (like 'About' dialog box creation) it could definitely stand for some improvement; but that is what life and learning are about. So... here it is. Any feedback is greatly appreciated.
#!/usr/bin/perl -w
#
use Tk;
use Tk::DialogBox;
use Math::MatrixReal;
use strict;
sub convert ;

my $MW = MainWindow->new;

### --- Prevents Main Window Resizing
$MW->bind('<Configure>' => sub{
        my $xe = $MW->XEvent;
        $MW->maxsize($xe->w, $xe->h);
        $MW->minsize($xe->w, $xe->h);
});


### --- Main Window Title
#$MW->title("Determinant");
$MW->title("3X3");

### --- Create Button Frame ##Frame for EXIT Button
my $button_frame = $MW->Frame();
        $button_frame->pack(-side => 'bottom', -expand => '1', -fill =
+> 'both');
### --- Create Exit Button
my $exit = $button_frame->Button(-text => 'Exit',
               -foreground => 'red',    
               -activebackground => "#FF9090",
                       -font => 'bold',
                       -command => sub
            {
             exit;
            });
$exit->pack(-side => 'left', -expand => '1', -fill => 'both');



### --- Create Button Frame 2 ## Frame for About Button
my $button_frame2 = $MW->Frame();
        $button_frame2->pack(-side => 'bottom', -expand => '1', -fill 
+=> 'both');
### --- Create About Button
$button_frame2->Button(-text => "About",
        -foreground => "#007300",
        -activebackground => "#98FB98",
            -font => 'bold',
        -command => sub
         { 
        my $dialogA = $MW->DialogBox( -title   => "About this program"
+,
                                              -buttons => [ "OK" ],
                                );

            $dialogA->add("Label",
                
                -borderwidth => '3',
                -background => "#FAEBD7", #ANTIQUE WHITE
#                -background => "#88FFCC", 
                                -font => 'bold',
                    -justify => 'left',
                -relief => 'sunken', #One seriously long text string f
+ollows on the next line -->
                                -text => "FOR BEST RESULTS USE: PERL 5
+.6.1 \& Tk 8.0 OR BETTER\nAdditional Required Perl Module: Math::Matr
+ixReal.\nThis program calculates the determinant of a 3X3 Matrix.\nTh
+e Result appears in the \"Green Box\".\n*****************************
+***********************************************************\nVersion 
+0.1 -- 10\/20\/2001 Initial Version Written by Jay Madigan.\nVersion 
+0.2 -- 12\/04\/2001 Minor text formatting change to disclaimer.\n****
+*********************************************************************
+***************\nREFERENCES ON MATRICES\:\nhttp\:\/\/www.microtonal.c
+o.uk\/matritut.htm\#det\nfile\:\/\/\/C\|\/Perl\/html\/site\/lib\/Math
+\/MatrixReal.html\n**************************************************
+**************************************\nThis program is freeware and 
+may be modified and\/or redistributed \nunder the same terms as the G
+NU public license of PERL.\nNo warranty on this code is assumed or im
+plied. ")->pack;

### --- Prevents Dialog Box Resizing
$dialogA->bind('<Configure>' => sub{
        my $xeD = $dialogA->XEvent;
        $dialogA->maxsize($xeD->w, $xeD->h);
        $dialogA->minsize($xeD->w, $xeD->h);
});



            $dialogA->Show;
}
)->pack(-side => 'right', -expand => '1', -fill => 'both');



### --- Create Button Frame 3 ###Frame for Calculate Button
my $button_frame3 = $MW->Frame();
        $button_frame3->pack(-side => 'bottom', -expand => '1', -fill 
+=> 'both');

### --- Create Convert Button
my $convert = $button_frame3->Button(-text => 'Calculate',
                                    -foreground => "blue",
                                    -activebackground => "#ADD8E6", 
                                    -font => 'bold',
                                    -command => sub
                                                   {
                                                        convert;
                                                        });
$convert->pack(-side => 'left', -expand => '1', -fill => 'both');



### --- Create Determinant Frame
my $det_frame = $MW->Frame()->pack(-expand => '1', -fill => 'none', -s
+ide
=> 'bottom');

#$det_frame->Label(-text => "Element name:", -font => 'Arial')->pack(-
+side => 'left');
my $det_value = $det_frame->Entry(-highlightbackground => 'green',-hig
+hlightthickness => '1',-font => 'Arial', -width => '10.9', -relief =>
+ 'sunken')->pack(-side => 'left', padx => '2');




### --- Create Row 3 Frame
my $row3_frame = $MW->Frame()->pack(-expand => '1', -fill => 'none', -
+side
=> 'bottom');

my $r3c1 = $row3_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');
my $r3c2 = $row3_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');
my $r3c3 = $row3_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');

### --- Create Row 2 Frame
my $row2_frame = $MW->Frame()->pack(-expand => '1', -fill => 'none', -
+side
=> 'bottom');

my $r2c1 = $row2_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');
my $r2c2 = $row2_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');
my $r2c3 = $row2_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');

### --- Create Row 1 Frame
my $row1_frame = $MW->Frame()->pack(-expand => '1', -fill => 'none', -
+side
=> 'bottom');

my $r1c1 = $row1_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');
my $r1c2 = $row1_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');
my $r1c3 = $row1_frame->Entry(-font => 'bold', -width => '3', -relief 
+=> 'sunken')->pack(-side => 'left', padx => '2', pady => '2');







MainLoop;

#### BEGIN SECTION FOR SUBROUTINES ----

sub convert {
    my $r1c1 = $r1c1->get;
    my $r1c2 = $r1c2->get;
    my $r1c3 = $r1c3->get;
    my $r2c1 = $r2c1->get;
    my $r2c2 = $r2c2->get;
    my $r2c3 = $r2c3->get;
    my $r3c1 = $r3c1->get;
    my $r3c2 = $r3c2->get;
    my $r3c3 = $r3c3->get;

    print "\n";
    print "$r1c1  $r1c2  $r1c3\n";
    print "$r2c1  $r2c2  $r2c3\n";
    print "$r3c1  $r3c2  $r3c3\n";

my $matrix = Math::MatrixReal->new_from_string(<<"MATRIX");
[ $r1c1  $r1c2  $r1c3 ]
[ $r2c1  $r2c2  $r2c3 ]
[ $r3c1  $r3c2  $r3c3 ]
MATRIX
   
    my $LR_matrix = $matrix->decompose_LR();


    my $determinant = $LR_matrix->det_LR();

    my $det = $determinant;

    $det_value->delete('0', 'end');
    $det_value->insert('0', $det);
    return;
     
}
Replies are listed 'Best First'.
Re: Perl/Tk 3X3 Matrix Solver
by graff (Chancellor) on Jul 06, 2003 at 19:52 UTC
    The code would be shorter, and would most likely be easier to read and maintain (and extend), if you used an AoA for the matrix Entry widgets and another AoA (with a slightly different name) to hold the Entry widget values; these two tightly-related data structures could be configured in a loop (the following is not tested, but should be close to usable):
    my $last_row = 2; my $last_col = 2; my $matrix_entry; my $matrix_value; for my $row (0 .. $last_row) { my $row_frame = $MW->Frame()->pack(-expand => '1', -fill => 'none', -side => 'top'); for my $col (0 .. $last_col) { $$matrix_entry[$row][$col] = $row_frame->Entry(-font => 'bold', -width => '3', -relief => 'sunken', -textvariable => $$matrix_entry[$row][$col], )->pack(-side => 'left', padx => '2', pady => + '2'); } }
    Note that you don't need to keep separate handles around for the three frame widgets, and by using the -textvariable attribute on the Entry widgets, you don't need all the "get()" method calls. Your solution subroutine can then be simpler too, using a loop (or map and join) to print out the matrix values, and using the "new_from_rows" method of Math::MatrixReal to initialize the matrix object.

    update: changed from my $nrows=3 ... for my $row (1..$nrows)... -- I realized that for the sake of the Math::MatrixReal calls, the array elements really should start at 0 rather than 1.

      This is great! Thanks! I still consider myself new in the world of Perl/Tk. In my spare time I tinker around with Perl/Tk related scripts. This is exactly the kind of feedback/suggestions that I was hoping for.
      Life is a continuous learning experience!
      And Perl Monks is a great contributor to that experience!