1

I have a Frame containing a BoxSizer with a ListBox and Panel. I want to programmatically resize the panel and then force the Frame to resize. I can resize the Panel as below, but how do I force the BoxSizer or Frame to resize?

The sample code below creates an application with a Resize menu option that resizes the panel:

#!/usr/bin/perl

use strict;
use warnings;
use Wx;

package TestApp;

use base qw (Wx::App);
use Wx qw (wxMINIMIZE_BOX wxSYSTEM_MENU wxCAPTION wxCLOSE_BOX wxCLIP_CHILDREN);

sub OnInit {
    my $self  = shift;
    my $frame = TestFrame->new (
        undef,
        -1,
        'Test App',
        [-1, -1],
        [-1, -1],
        wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN
    );

    $frame->Show (1);
    $self->SetTopWindow ($frame);

    return 1;
}

package TestFrame;

use base qw (Wx::Frame);
use Wx::Event qw (EVT_MENU);
use Wx qw (wxHORIZONTAL wxEXPAND wxALL wxBORDER_SIMPLE);

our @id = (0 .. 100);

sub new {
    my $class = shift;
    my $self  = $class->SUPER::new (@_);

    my $boxsizer = Wx::BoxSizer->new (wxHORIZONTAL);

    my $listbox = Wx::ListBox->new (
        $self,
        -1,
        [-1, -1],
        [64, -1]
    );

    my $panel = Wx::Panel->new (
        $self,
        -1,
        [-1, -1],
        [-1, -1],
        wxBORDER_SIMPLE
    );

    $boxsizer->Add (
        $listbox,
        0,
        wxEXPAND | wxALL,
        5
    );

    $boxsizer->Add (
        $panel,
        0,
        wxALL,
        5
    );

    my $menubar = Wx::MenuBar->new ();
    my $menu = Wx::Menu->new ();
    $menu->Append ($id[0], "Small Panel");
    $menu->Append ($id[1], "Large Panel");
    $menubar->Append ($menu, 'File');
    $self->SetMenuBar ($menubar);

    $panel->SetClientSize (100, 200);
    $self->SetSizerAndFit ($boxsizer);

    EVT_MENU ($self, $id[0], sub {
        $panel->SetMinSize ([-1, -1]);
        $panel->SetClientSize ([100, 200]);
        $panel->SetMinSize ($panel->GetClientSize ());
        $self->SetClientSize ($boxsizer->GetSize ());
        $self->Fit ();
    });

    EVT_MENU ($self, $id[1], sub {
        $panel->SetMinSize ([-1, -1]);
        $panel->SetClientSize ([200, 300]);
        $panel->SetMinSize ($panel->GetClientSize ());
        $self->SetClientSize ($boxsizer->GetSize ());
        $self->Fit ();
    });

    return $self;
}

package main;

my ($app) = TestApp->new ();

$app->MainLoop ();
Andrew Miller
  • 143
  • 1
  • 9

1 Answers1

2

Calling $self->Fit() will do it provided you call $panel->SetMinSize() instead of SetClientSize().

VZ.
  • 21,740
  • 3
  • 39
  • 42
  • That seems to resize the Frame to the original size, not the new size – Andrew Miller Jan 27 '14 at 11:44
  • Sorry, I didn't think it through, `Fit()` is indeed not enough if you just set the client size because the best (aka min) size of the panel still retains its initial value. I've edited the answer to be hopefully correct. – VZ. Jan 27 '14 at 13:10
  • Adding $panel->SetMinSize ($panel->GetSize ()) seems to work flawlessly under Windows. On Linux (Fedora 20) I had to add $panel->SetMinSize ([-1, -1]) before I call SetClientSize. However this only seems to work intermittently (the panel resizes but the window does not). Is there any way to fix this on Linux? – Andrew Miller Jan 27 '14 at 14:04
  • I really don't see why would the behaviour be different under Unix, why did you have to add the call resetting the min size? – VZ. Jan 27 '14 at 14:42
  • When I make the panel smaller than the original nothing happens in Linux unless I reset the min size (Windows works fine without this line). With this line it works maybe 50% of the time, so it might be a bug with the way wxperl is interacting with GTK+ – Andrew Miller Jan 27 '14 at 15:01