Search code examples
perlwxwidgetswxperl

Tiling bitmaps on a wxFrame


I want to set the background on a frame with tiling bitmaps, using wxPerl. With the help of an example from wxWidgets I've come up with the code below. Unfortunately, it doesn't do anything, the frame remains blank. Is this even the right way to do it, or is there another way?

use warnings;
use strict;

package MyFrame;
use Wx qw(:everything);
use base qw( Wx::Frame );

sub new {
    my ( $class, $path ) = @_;
    my $self
        = $class->SUPER::new( undef, -1, 'Test', [ -1, -1 ], [ 600, 400 ], );
    $self->set_tiling_background($path);
    return $self;
}

sub set_tiling_background {
    my ( $self, $path ) = @_;

    ## Create a wxBitmap from the file
    my $file = IO::File->new($path);
    binmode $file;

    my $handler = Wx::BMPHandler->new();
    my $image   = Wx::Image->new();
    $handler->LoadFile( $image, $file );
    my $bitmap = Wx::Bitmap->new($image);

    ## Just to check that the bitmap is good.
    $bitmap->SaveFile('saved.bmp', wxBITMAP_TYPE_BMP);

    ## Draw the bitmap tiling over the frame
    ## https://github.com/wxWidgets/wxWidgets/blob/master/src/html/htmlwin.cpp
    my $dc = Wx::WindowDC->new($self);

    my $size_x = $bitmap->GetWidth;
    my $size_y = $bitmap->GetHeight;

    for ( my $x = 0; $x < 600; $x += $size_x ) {
        for ( my $y = 0; $y < 400; $y += $size_y ) {
            $dc->DrawBitmap( $bitmap, $x, $y, 0 );
        }
    }
}

package MyApp;
use base 'Wx::App';
my $path = '/path/to/bitmap.bmp';

sub OnInit {
    my ($self) = @_;
    my $frame = MyFrame->new($path);
    $frame->Show(1);
}

package main;
MyApp->new->MainLoop;


Solution

  • Here is an example using the ERASE_BACKGROUND event handler:

    package MyFrame;
    use Wx qw(:everything wxBITMAP_TYPE_JPEG);
    use base qw( Wx::Frame );
    use feature qw(say);
    use strict;
    use warnings;
    use Wx::Event;
    
    sub new {
        my ( $class, $path ) = @_;
        my $self
            = $class->SUPER::new( undef, -1, 'Test', [ -1, -1 ], [ 600, 400 ], );
        my $bitmap = Wx::Bitmap->new( $path , wxBITMAP_TYPE_JPEG );
        Wx::Event::EVT_ERASE_BACKGROUND( $self, sub { $self->setBgImage( $bitmap, @_) });
        return $self;
    }
    
    sub setBgImage {
        my ( $self, $bitmap, $frame, $evt ) = @_;
    
        return if !defined $evt;
        my $dc = $evt->GetDC();
        my $size_x = $bitmap->GetWidth;
        my $size_y = $bitmap->GetHeight;
    
        for ( my $x = 0; $x < 600; $x += $size_x ) {
            for ( my $y = 0; $y < 400; $y += $size_y ) {
                $dc->DrawBitmap( $bitmap, $x, $y, 0 );
            }
        }
    }
    
    package MyApp;
    use base 'Wx::App';
    my $path = 'logo.jpg';
    
    sub OnInit {
        my ($self) = @_;
        my $frame = MyFrame->new($path);
        $frame->Show(1);
    }
    
    package main;
    MyApp->new->MainLoop;
    

    This gives me the following output on Ubuntu 20.04:

    enter image description here

    See also: wxPython: Putting a Background Image on a Panel