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

Hello everyone,

I've been stuck on this for several days now and I'm at wits end here. I'm by no means an expert in Perl.

I'm writing a GUI app using WxPerl. To cut down on the noise, I've recreated a portion of the app where I'm having issues. I designed the layout in FormBuilder, then used the resulting XRC file. Sorry in advance, I tried to add the XRC as __DATA__ but my GUI is in a package and I wasn't able to create a filehandle that XRC would accept using the XRC Load method (after several hours I gave up on it), anyway, the XRC __DATA__ is at the bottom of the script and would need to be saved into a file named: noname.xrc.

In a nutshell, the GUI has two grids (left and right), with two buttons in the middle. For testing, there's an "add row" button at the top of the main frame, which adds a row to the left grid. I wrote an EVT_SIZE function to adjust the last column of the grid on the left to fill the remaining space, which then modifies the grid on the right in the same way to keep them equal proportions.

Issues:

1) Click the add button 20 times, then adjust the size of the main frame window. Notice how the grid all of a sudden expands and eats up the entire bottom of the frame. Click the add button a few more times and it continues eating up the bottom... I can't seem to get the height to adjust to prevent it from eating up the bottom portion. Maybe there's an obvious form setting I'm missing? Even removing the growablecols flag from the wxGridBagSizer doesn't stop this from happening.

2) An annoying visual issue, which is probably related to the proportional sizing. Basically, there's border padding on each side of the grid (5x2), which is 10. So I've subtracted 11 from the width before it is set, but ideally it should be 10. However, if it's set to 10, when resizing occurs the last column keeps growing forever...

3) If you click the "Maximize" button in the top right corner of the main frame, then click it again (it's called "Restore Down" then), to revert it back to the previous size, you'll see that the right grid never adjusts obviously, since the left grid hasn't changed size which never triggers the EVT_SIZE event... I've been brainstorming how to fix this, maybe the on size event can check the position of the right grid and determine if it's beyond the width of the main frame? Is there an easier way to get this to size properly?

Ideally, I'd like to set minimum sizes for certain grid columns, but have all the columns grow as the main window is resized. But that's probably a pipe-dream at this point.

Any help greatly appreciated,

Thanks,

-Perluro

#!/usr/bin/perl package wxToplevelFrame; use strict; use warnings; use Wx qw(:everything); use Wx::Grid; use Wx::XRC; use base 'Wx::Frame'; use Data::Dumper; use diagnostics; # import event registration function use Wx::Event qw(:everything); use base qw(Wx::Panel Class::Accessor::Fast); __PACKAGE__->mk_ro_accessors( qw(xrc) ); $| = 1; ### GUI CODE BEGINS ### # create specialized constructor for new subclass sub new { my $class = shift; my $self = $class->SUPER::new(); $self->initialize(); return $self; } sub initialize { my ($self) = @_; my $xrc_path = 'noname.xrc'; Wx::InitAllImageHandlers(); $self->{ xrc } = Wx::XmlResource->new(); $self->xrc->InitAllHandlers(); $self->xrc->Load($xrc_path); $self->xrc->LoadFrame($self, undef, 'MyFrame1',); # main frame close EVT_CLOSE( $self, sub { my ($self) = @_; $self->Destroy(); } ); # LEFT GRID my $grid_left = $self->{ grid_left } = $self->FindWindow('m_grid4' +); $grid_left->CreateGrid(0, 3); $grid_left->SetColLabelSize(25); # label height $grid_left->SetRowLabelSize(25); # row width (far left, the number +s column basically) $grid_left->SetColLabelValue(0, 'col_1'); $grid_left->SetColLabelValue(1, 'col_2'); $grid_left->SetColLabelValue(2, 'col_3'); $grid_left->EnableDragColSize(0); $grid_left->EnableDragRowSize(0); $grid_left->EnableEditing(0); $grid_left->SetDefaultRowSize(20); $grid_left->SetColSize( 0, 190 ); # col 1 $grid_left->SetColSize( 1, 50 ); # col 2 $grid_left->SetColSize( 2, 179 ); # col 3 # RIGHT GRID my $grid_right = $self->{ grid_right } = $self->FindWindow('m_grid +5'); $grid_right->CreateGrid(0, 3); $grid_right->SetColLabelSize(25); # label height $grid_right->SetRowLabelSize(25); # row width (far left, the numbe +rs column basically) $grid_right->SetColLabelValue(0, 'col_'); $grid_right->SetColLabelValue(1, 'col_2'); $grid_right->SetColLabelValue(2, 'col_3'); $grid_right->EnableDragColSize(0); $grid_right->EnableDragRowSize(0); $grid_right->EnableEditing(0); $grid_right->SetDefaultRowSize(20); $grid_right->SetColSize( 0, 190 ); # col 1 $grid_right->SetColSize( 1, 50 ); # col 2 $grid_right->SetColSize( 2, 179 ); # col 3 #EVT_SIZE( $grid_left, \&on_size ); # adjust grid when size change +s #EVT_SIZE( $grid_right, \&on_size ); # adjust grid when size chang +es my $on_size = \&on_size; EVT_SIZE($grid_left, callback($on_size, $self, $grid_left) ); my $button = $self->{ button } = $self->FindWindow('m_button3'); EVT_BUTTON( $button, $button->GetId(), callback(my $button_sub = \&add_row, $self, $button), ); my $gui_actions_text_ctrl = $self->FindWindow('m_textCtrl1'); my $gui_log = Wx::LogTextCtrl->new( $gui_actions_text_ctrl ); $self->{ gui_log_text_ctrl } = Wx::Log::SetActiveTarget( $gui_log +); $self->SetStatusBarPane(-1); return; } sub callback { my $coderef = shift; my @args = @_; #print "what is args\n"; #print Dumper \@args; sub { $coderef->(@args) } # callback function. when we want to pass addition args to a meth +od call, such as an event (EVT_*), we can use this # example: # my $on_size_test = \&on_size_test; # EVT_SIZE($grid_left, callback($on_size, $grid_left, $self) ); } sub on_close { my ($self) = @_; $self->Destroy(); } sub on_size { my ($self, $grid) = @_; print "in on_size sub\n"; # get the number of columns and the initial width which includes t +he far left number column (gutter column, with row indicators 1, 2, 3 + ...) my $num_cols = $grid->GetNumberCols(); my $width = $grid->GetRowLabelSize(); my $gutter_col = $width; print "num_cols: $num_cols\n"; print "initial width: $width\n"; my $col_0; my $col_1; my $col_2; # iterate over each column, get size and add it to our width for (my $col = 0; $col < $num_cols; $col++) { # conditionals of no importance currently, but used during tes +ting if ($col == 0) { $col_0 = $grid->GetColSize($col); print "col: $col, width col_0: $col_0\n"; } elsif ($col == 1) { $col_1 = $grid->GetColSize($col); print "col: $col, width col_1: $col_1\n"; } elsif ($col == 2) { $col_2 = $grid->GetColSize($col); print "col: $col, width col_2: $col_2\n"; } $width += $grid->GetColSize($col); } print "width after iterating over each column: $width\n"; # get sizer that grid is contained in # get width of sizer and subtract it from the total width # the difference will be the size we set for our last column if ($num_cols > 0) { my $static_box_sizer = $grid->GetContainingSizer(); my $sizer = $static_box_sizer->GetSize(); my $sizer_width = $sizer->GetWidth(); print "sizer_width: $sizer_width\n"; print "we are setting width for the last column. sizer_width: + $sizer_width minus the total width: $width (gutter_col: $gutter_col, + col_0, col_1, col_2)\n"; my $width_diff = $sizer_width - $width + $col_2 - 11; # id +eally this should be 10 for padding (5x2) on each side of sizer # but +setting it at 10 causes the col to keep expanding... print "width_diff result of above calc: $width_diff\n"; $grid->SetColSize($num_cols - 1, $width_diff); # last column # adjust grid right to reflect same proportions $self->{ grid_right }->SetColSize($num_cols - 1, $width_diff); + # last column } return; } sub add_row { my ($self, $button) = @_; $self->{ grid_left }->AppendRows(1); my $col = 0; foreach my $value ('testing', 100, 'Sat Aug 20 20:52:20 2016') { my $row; if ($col == 3) { $self->{ grid_left }->AppendRows(1); $row = $self->{ grid_left }->GetNumberRows() - 1; # minus +one from total rows print "col == 2\n"; print "reset\n"; print "what is row: $row\n"; $col = 0; } else { $row = $self->{ grid_left }->GetNumberRows() - 1; } print "value: $value\n"; $self->{ grid_left }->SetCellValue( $row, $col, $value, ); if ($col == 1) { $self->{ grid_left }->SetCellAlignment( $row, $col, wxALIGN_RIGHT, wxALIGN_CENTRE, ); } elsif ($col == 2) { $self->{ grid_left }->SetCellAlignment( $row, $col, wxALIGN_CENTRE, wxALIGN_CENTRE, ); } $col++; } } ### GUI CODE ENDS ### # END: wxToplevelFrame package # create an app object package MyApp; use strict; use warnings; use base 'Wx::App'; # OnInit is called automatically when an app object is first construct +ed sub OnInit { my $self = shift; my $toplevel_frame = wxToplevelFrame->new(); $self->SetTopWindow($toplevel_frame); $toplevel_frame->Show(1); } # END: MyApp package package main; use strict; use warnings; use Data::Dumper; $| = 1; my $app = MyApp->new(); # instantiate our app first $app->MainLoop(); exit;

XRC data (file: noname.xrc)

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1"> <object class="wxFrame" name="MyFrame1"> <style>wxCAPTION|wxCLOSE_BOX|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxR +ESIZE_BORDER|wxSYSTEM_MENU|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL</ +style> <size>998,700</size> <title>Grid Issues</title> <centered>1</centered> <aui_managed>0</aui_managed> <object class="wxPanel" name="m_panel6"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <option>1</option> <flag>wxALL|wxEXPAND</flag> <border>5</border> <object class="wxFlexGridSizer"> <rows>0</rows> <cols>6</cols> <vgap>0</vgap> <hgap>0</hgap> <growablecols></growablecols> <growablerows></growablerows> <object class="sizeritem"> <option>0</option> <flag>wxALL</flag> <border>5</border> <object class="wxButton" name="m_button3"> <label>add row</label> <default>0</default> </object> </object> </object> </object> <object class="sizeritem"> <option>3</option> <flag>wxEXPAND|wxLEFT|wxRIGHT</flag> <border>5</border> <object class="wxGridBagSizer"> <vgap>0</vgap> <hgap>0</hgap> <growablecols>0,2</growablecols> <growablerows>0</growablerows> <object class="sizeritem"> <cellpos>0,0</cellpos> <cellspan>1,1</cellspan> <flag>wxALL|wxEXPAND</flag> <border>5</border> <object class="wxStaticBoxSizer"> <orient>wxHORIZONTAL</orient> <label>left</label> <object class="sizeritem"> <option>1</option> <flag>wxALL|wxEXPAND</flag> <border>5</border> <object class="wxGrid" name="m_gri +d4" /> </object> </object> </object> <object class="sizeritem"> <cellpos>0,1</cellpos> <cellspan>1,1</cellspan> <flag>wxALIGN_CENTER_HORIZONTAL|wxALIGN_CE +NTER_VERTICAL</flag> <border>5</border> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <option>0</option> <flag>wxALL</flag> <border>5</border> <object class="wxButton" name="m_b +utton4"> <style>wxBU_EXACTFIT</style> <label>&gt;</label> <default>0</default> </object> </object> <object class="sizeritem"> <option>0</option> <flag>wxALL</flag> <border>5</border> <object class="wxButton" name="m_b +utton5"> <style>wxBU_EXACTFIT</style> <label>&lt;</label> <default>0</default> </object> </object> </object> </object> <object class="sizeritem"> <cellpos>0,2</cellpos> <cellspan>1,1</cellspan> <flag>wxALL|wxEXPAND</flag> <border>5</border> <object class="wxStaticBoxSizer"> <orient>wxHORIZONTAL</orient> <label>right</label> <object class="sizeritem"> <option>1</option> <flag>wxALL|wxEXPAND</flag> <border>5</border> <object class="wxGrid" name="m_gri +d5" /> </object> </object> </object> </object> </object> <object class="sizeritem"> <option>2</option> <flag>wxEXPAND | wxALL</flag> <border>5</border> <object class="wxNotebook" name="m_notebook2"> <object class="notebookpage"> <label>a page</label> <selected>0</selected> <object class="wxPanel" name="m_panel2"> <style>wxTAB_TRAVERSAL</style> <object class="wxBoxSizer"> <orient>wxHORIZONTAL</orient> <object class="sizeritem"> <option>1</option> <flag>wxALL|wxEXPAND</flag> <border>5</border> <object class="wxTextCtrl" nam +e="m_textCtrl1"> <value></value> </object> </object> </object> </object> </object> </object> </object> </object> </object> <object class="wxStatusBar" name="m_statusBar1"> <style>wxST_SIZEGRIP</style> <fields>2</fields> </object> </object> </resource>

Replies are listed 'Best First'.
Re: Wx Perl grid issues
by Anonymous Monk on Oct 13, 2016 at 08:08 UTC

    Hi, can you use the perl code generator to turn xrc into perl code?

      I believe if you mocked this up using boxsizers only, the problem would go away :)

        Thanks for the reply Anonymous Monk.

        Re: can you use the perl code generator to turn xrc into perl code?

        Formbuilder doesn't export to .pl, but does python and c++.

        Re: I believe if you mocked this up using boxsizers only, the problem would go away :)

        Perhaps, maybe I'll try that and see. It may solve the issue of rows eating up the form space vertically.

        I may come back to this issue at a later time. At the moment, I've lost too much time messing around with it. In the meantime, my workaround was locking down the entire main frame to prevent users from resizing the app. I then adjusted the code to account for when x number of rows is reached to account for the vertical scrollbar and adjust the last column accordingly.

        I appreciate the comments, thanks.

        All the best,

        Perluro