Re: Can you display a bitmap with/inside of a sizer?

James Lynes <[email protected]> Thu, 7 May 2015 15:23:52 -0400
Newsgroups gmane.comp.lang.perl.wxperl
Message-ID <CABPyseiRn6ZRvm9QD9SUjcZvdGnzY6jHQLj=aBW8aXBOfby4pw@mail.gmail.com>
Steve:

You are already beyond me on looking for the memory leak based on your PM
post. The wxBook has a section on finding memory leaks, but what you are
doing with Valgrind is probably more advanced. Wish I could help more...

I like your idea for a standard layout - Header/Main/Footer. I need to work
that into my new app boiler plate file.  It's amazing how many lines are
required for the sizers! Getting there. It makes more sense now that I have
it working. Nice to have example code to look at. Need to get github set up
on this laptop so I can add this to my examples repository.

For what it's worth, attached is my latest learning "exercise".

James




On Thu, May 7, 2015 at 3:02 AM, Steve Cookson <[email protected]>
wrote:

>  Hi James,
>
> Well really I find sizers are a bit problematic too.  At the beginning I
> did them just as you are doing.  Then I started drawing the more
> complicated ones out on a piece of paper before starting and now I have a
> standard layout which I reuse so that I have a standard header, a main
> panel and a standard footer with a standard set of buttons in it.  The main
> panel still requires some thinking, but I would have used the nested sizers
> idea that you used.  Wx::GridBagSizer is a bit more complicated, but would
> also have worked, that way you might have been able to do the whole thing
> with one sizer.
>
> Regarding the memory leak, I thought I had it.  I made a number of changes
> to make the code more streamlined and efficient and lo and behold the leak
> disappeared only to pop up else where.
>
> It's driving me a bit crazier than I was anyway, and worse, I don't even
> know if it's causing the video crash!  Any suggestions welcome!
>
> Thanks for asking,
>
> Steve.
>
>
> On 06/05/15 23:39, James Lynes wrote:
>
>   Solved... via trial and error and error and error...
>
>  Made the top level sizer horizontal, containing a left and right
> vertical, containing text controls, bitmap, and buttons.
>
>  Will post once I add a few more bells and whistles.
>
>  Thanks again,
>
>  James
>
>
> On Wed, May 6, 2015 at 4:06 PM, James Lynes <[email protected]> wrote:
>
>>   Steve, thanks! Did the job.
>>
>>  But, of course, one question leads to at least one more.....
>>
>>  I would like the bitmap to be displayed to the right of a column of
>> TextCtrls. Currently the TextCtrls are being displayed under the bitmap now
>> that I'm not using an onPaint event . Do I need to create two sub-panels
>> with sub-sizers, one for the bitmap and one for the TextCtrls? Or should
>> the top sizer be a horzontal rather than vertical? Trying to make some
>> sense of this sizer stuff.
>>
>>  James
>>
>>  PS: Did you find your memory leak?
>>
>> On Mon, May 4, 2015 at 11:32 AM, Steve Cookson <[email protected]>
>> wrote:
>>
>>> Hi James,
>>>
>>> You want Wx::StaticBitmap, like this:
>>>
>>>     my $bmp = Wx::Bitmap->new("path/to/bitmap.png", wxBITMAP_TYPE_PNG) ;
>>>     my $sbm = Wx::StaticBitmap->new($parent, wxID_ANY, $bmp,
>>> wxDefaultPosition, wxDefaultSize, );
>>>     $sizer->Add($sbm, 0, 0, 0);
>>>
>>> Regards
>>>
>>> Steve.
>>>
>>>
>>>
>>> On 02/05/15 16:05, James Lynes wrote:
>>>
>>>> Good day!
>>>>
>>>> I'm working on a little app to design common emitter amplifiers. I
>>>> created a circuit schematic with Eagle and exported it to a PNG file.
>>>>
>>>> I am currently displaying the PNG at a fixed location of the screen
>>>> with:
>>>>
>>>>     Wx::Event::EVT_PAINT($self, sub {
>>>>         my ($self, $event) = @_;
>>>>         My $dc = Wx::PaintDC->new($self);
>>>>         my $bmp = Wx::Bitmap->new("CEAmpImg.png, wxBITMAP_TYPE_PNG);
>>>>         $dc->DrawBitmap($bmp, 150, 50, 1);});
>>>>
>>>> If would be nice if I could blend this in with the sizers that are
>>>> controlling the layout of the input and output TextCtrls.
>>>>
>>>> Thanks for your ideas.
>>>>
>>>> James
>>>>
>>>>
>>>>
>>>
>>
>
>
CEAmp1.pl (application/x-perl, 8.5 KB)
#! /usr/bin/perl

# Name:			CEAmp1.pl
# Author:		James M. Lynes, Jr.
# Created:		May 1, 2015
# Modified By:		James M. Lynes, Jr.
# Last Modified:	May 7, 2015
# Change Log:		5/1/2015 - Program Created
#                       5/2/2015 - Fixed $IcqText box for blank field case
#                                - Move $title into the verticle sizer
#                                - Move Design & Exit buttons to the right
#                       5/6/2015 - Modify Sizer layout
#			5/7/2015 - Change TextCtrls to SpinCtrls - prevents divide by 0 possibility
#                                - Used Eagle to draw a border around the schematic bitmap
#                                - Added comments throughout
# Description:		Common Emitter Amp Designer
#                                  Given Vcc, Vceq, Icq, Beta, & Av
#                                  Calculate Bias, Collector, & Emitter Resistor Values
#

package main;
use strict;
use warnings;
my $app = App->new();
$app->MainLoop;

package App;
use strict;
use warnings;
use base 'Wx::App';
sub OnInit {
    Wx::InitAllImageHandlers();
    my $frame = Frame->new();
    $frame->Show(1);
}

package Frame;
use strict;
use warnings;
use Wx qw(:everything);
use base qw(Wx::Frame);
use CEAmp;
use Data::Dumper;

sub new {
    my ($class, $parent) = @_;

    my $self = $class->SUPER::new($parent, -1, "Common Emitter Amplifier Designer", wxDefaultPosition, wxDefaultSize);

#   Create an instance of a CE Amp object(defined in CEAmp.pm)

    $self->{AMP1} = CEAmp::Data->new();

#   Create the Schematic Bitmap(Created in Eagle and exported to a PNG file)

    my $bmp = Wx::Bitmap->new("CEAmpImg1.png", wxBITMAP_TYPE_PNG);
    my $sbm = Wx::StaticBitmap->new($self, wxID_ANY, $bmp, wxDefaultPosition, wxDefaultSize);

# Create Controls

    my $title = Wx::StaticText->new($self, wxID_ANY, "Common Emitter Amplifier Designer",
                                    wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);

    my $VccLabel = Wx::StaticText->new($self, wxID_ANY, "   Vcc,v", wxDefaultPosition, wxDefaultSize); 
    my $VccText = Wx::SpinCtrl->new($self, wxID_ANY, "12", wxDefaultPosition, wxDefaultSize, 
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 24, 12);
 
    my $VceqLabel = Wx::StaticText->new($self, wxID_ANY, "   Vceq,v", wxDefaultPosition, wxDefaultSize); 
    my $VceqText = Wx::SpinCtrl->new($self, wxID_ANY, "5", wxDefaultPosition, wxDefaultSize,
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 24, 5);

    my $IcqLabel = Wx::StaticText->new($self, wxID_ANY, "   Icq,ma", wxDefaultPosition, wxDefaultSize); 
    my $IcqText = Wx::SpinCtrl->new($self, wxID_ANY, "4", wxDefaultPosition, wxDefaultSize,
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 40, 4);

    my $BetaLabel = Wx::StaticText->new($self, wxID_ANY, "   Beta", wxDefaultPosition, wxDefaultSize); 
    my $BetaText = Wx::SpinCtrl->new($self, wxID_ANY, "150", wxDefaultPosition, wxDefaultSize,
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 300, 150);

    my $AvLabel = Wx::StaticText->new($self, wxID_ANY, "   Av", wxDefaultPosition, wxDefaultSize); 
    my $AvText = Wx::SpinCtrl->new($self, wxID_ANY, "5", wxDefaultPosition, wxDefaultSize,
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 100, 5);

    my $R1Label = Wx::StaticText->new($self, wxID_ANY, "R1", wxDefaultPosition, wxDefaultSize); 
    my $R1Text = Wx::TextCtrl->new($self, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY);

    my $R2Label = Wx::StaticText->new($self, wxID_ANY, "R2", wxDefaultPosition, wxDefaultSize); 
    my $R2Text = Wx::TextCtrl->new($self, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY);

    my $RcLabel = Wx::StaticText->new($self, wxID_ANY, "Rc", wxDefaultPosition, wxDefaultSize); 
    my $RcText = Wx::TextCtrl->new($self, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY);

    my $ReLabel = Wx::StaticText->new($self, wxID_ANY, "Re", wxDefaultPosition, wxDefaultSize); 
    my $ReText = Wx::TextCtrl->new($self, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY);

# Create Buttons

    my $designButtonID = 1000;
    my $designButton = Wx::Button->new($self, $designButtonID, "Design", wxDefaultPosition, wxDefaultSize);
    my $exitButton = Wx::Button->new($self, wxID_EXIT, "", wxDefaultPosition, wxDefaultSize);

# Create Sizers

    my $verticalSizerFrame = Wx::BoxSizer->new(wxHORIZONTAL);
    $self->SetSizer($verticalSizerFrame);

    my $leftSizer = Wx::BoxSizer->new(wxVERTICAL);
    my $rightSizer = Wx::BoxSizer->new(wxVERTICAL);
    my $verticalSizerControls = Wx::BoxSizer->new(wxVERTICAL);
    my $horizontalSizerOutputs = Wx::BoxSizer->new(wxHORIZONTAL);
    my $horizontalSizerButtons = Wx::BoxSizer->new(wxHORIZONTAL);

# Layout Sizers

    $verticalSizerFrame->Add($leftSizer, 0, 0, 0);
    $verticalSizerFrame->Add($rightSizer, 0, 0, 0);

    $leftSizer->Add($verticalSizerControls, 0, 0, 0);
    $rightSizer->AddSpacer(50);
    $rightSizer->Add($sbm, 0, 0, 0);
    $rightSizer->AddSpacer(20);
    $rightSizer->Add($horizontalSizerOutputs, 0, 0, 0);
    $rightSizer->AddSpacer(40);
    $rightSizer->Add($horizontalSizerButtons, 0, 0, 0);

    $verticalSizerControls->Add($title, 0, 0, 0);
    $verticalSizerControls->AddSpacer(30);
    $verticalSizerControls->Add($VccLabel, 0, 0, 0);
    $verticalSizerControls->Add($VccText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);
    $verticalSizerControls->Add($VceqLabel, 0, 0, 0);
    $verticalSizerControls->Add($VceqText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);
    $verticalSizerControls->Add($IcqLabel, 0, 0, 0);
    $verticalSizerControls->Add($IcqText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);
    $verticalSizerControls->Add($BetaLabel, 0, 0, 0);
    $verticalSizerControls->Add($BetaText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);
    $verticalSizerControls->Add($AvLabel, 0, 0, 0);
    $verticalSizerControls->Add($AvText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);

    $horizontalSizerOutputs->Add($R1Label, 0, 0, 0);
    $horizontalSizerOutputs->Add($R1Text, 0, 0, 0);
    $horizontalSizerOutputs->AddSpacer(10);
    $horizontalSizerOutputs->Add($R2Label, 0, 0, 0);
    $horizontalSizerOutputs->Add($R2Text, 0, 0, 0);
    $horizontalSizerOutputs->AddSpacer(10);
    $horizontalSizerOutputs->Add($RcLabel, 0, 0, 0);
    $horizontalSizerOutputs->Add($RcText, 0, 0, 0);
    $horizontalSizerOutputs->AddSpacer(10);
    $horizontalSizerOutputs->Add($ReLabel, 0, 0, 0);
    $horizontalSizerOutputs->Add($ReText, 0, 0, 0);

    $horizontalSizerButtons->AddSpacer(300);
    $horizontalSizerButtons->Add($designButton, 0, 0, 0);
    $horizontalSizerButtons->AddSpacer(40);
    $horizontalSizerButtons->Add($exitButton, 0, 0, 0);

# Create Event Handlers

    Wx::Event::EVT_BUTTON($self, $designButton, sub {
                          my ($self, $event) = @_;
                          CEAmp->design($self, $self->{AMP1});		# Run the Design Calculations
                          $R1Text->SetValue($self->{AMP1}->R1);		# Copy results back to Output Controls
                          $R2Text->SetValue($self->{AMP1}->R2);
                          $RcText->SetValue($self->{AMP1}->Rc);
                          $ReText->SetValue($self->{AMP1}->Re);});

    Wx::Event::EVT_BUTTON($self, $exitButton, sub {			# Exit
                          my ($self, $event) = @_;
                          $self->Close;});

    Wx::Event::EVT_TEXT($self, $VccText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                        $self->{AMP1}->Vcc($VccText->GetValue);});

    Wx::Event::EVT_TEXT($self, $VceqText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                        $self->{AMP1}->Vceq($VceqText->GetValue);});

    Wx::Event::EVT_TEXT($self, $IcqText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                         $self->{AMP1}->Icq($IcqText->GetValue / 1000)});

    Wx::Event::EVT_TEXT($self, $BetaText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                        $self->{AMP1}->Beta($BetaText->GetValue);});

    Wx::Event::EVT_TEXT($self, $AvText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                        $self->{AMP1}->Av($AvText->GetValue);});


    $verticalSizerFrame->Fit($self);
    $verticalSizerFrame->Layout();

    return $self;
}
1;
CEAmp.pm (application/x-perl, 1.9 KB)
#! /usr/bin/perl

# Name:			CEAmp.pm
# Author:		James M. Lynes, Jr.
# Created:		May 1, 2015
# Modified By:		James M. Lynes, Jr.
# Last Modified:	May 1, 2015
# Change Log:		5/1/2015 - Program Created
# Description:		Common Emitter Amplifier Designer
#				Support Module for wxPerl transistor amplifier designer - CEAmp1.pl
#

package CEAmp;
use strict;
use warnings;
use Data::Dumper;

my %defaults = (
		Av	=> 5,			# Desired Amplifier Voltage Gain
		Vcc	=> 12,			# Collector Voltage
		Vbe	=> .7,			# Base->Emitter Voltage
		Vceq	=> 5,			# Collector->Emitter Voltage at Quiessence
		VR1	=> 0,			# Voltage across VR1
		VR2	=> 0,			# Voltage across Vr2
		R1	=> 0,			# Bias Resistor R1
		R2	=> 0,			# Bias Resistor R2
		Rc	=> 0,			# Collector Resistor
		Re	=> 0,			# Emitter Resistor
		Rt	=> 0,			# Total of Bias Resistors
		Ib	=> 0,			# Base Current
		Ic	=> 0,			# Collector Current
		Ie	=> 0,			# Emitter Current
		Ir	=> 0,			# Bias Current
		Icq	=> .004,		# Desired Collector Current at Quiessence
		Beta	=> 150,			# Transistor DC Current Gain
		Cin	=> 10E-6,		# Input Coupling Capacitor - currently not implemented
		Cout	=> 10E-6,		# Output Coupling Capacitor - currently not implemented
		Transistor	=> "2N3904",	# Transistor Type
		);

sub design {
    my ($class, $self, $amp) = @_;

    $amp->Rt(($amp->Vcc - $amp->Vceq) / $amp->Icq);
    $amp->Re(($amp->Rt / ($amp->Av + 1)));
    $amp->Rc($amp->Rt - $amp->Re);

    $amp->Ib($amp->Icq / $amp->Beta);
    $amp->Ir($amp->Ib * 10);

    $amp->VR2($amp->Vbe + ($amp->Icq * $amp->Re));
    $amp->R2($amp->VR2 / $amp->Ir);
    $amp->VR1($amp->Vcc - $amp->VR2);
    $amp->R1($amp->VR1 / $amp->Ir);
}

package CEAmp::Data;
use strict;
use warnings;
use Class::Accessor::Fast;
use base qw(Class::Accessor::Fast);

__PACKAGE__->mk_accessors(qw(Av Vcc Vbe VR1 VR2 Vceq R1 R2 Rc Re Rt
                             Ib Ic Ie Ir Icq Beta Cin Cout Transistor));

sub new {shift->SUPER::new(@_, \%defaults);}
1;
CEAmpImg1.png (image/png, 3.6 KB) - not displayed