First timer - bitmap event issues.

Hello there,
I am tinkering with wxPython, chasing an idea I have to write a
ttf font manager for Linux.

I have never used an email list before, so I am not sure if this is the
correct way to proceed. I will jump in.

WRAPPING
I don't know how to post the python code with wrapping on. I have disabled it.
The test is broken with the Enter key (Linux style). I am using Kmail so it might be horrible on Windows.
Please advise.
Can one attach (rather than paste) python code to these list emails?

PLATFORM:
Fedora Core 3 (Linux i686 AMD Athlon)
Python 2.3 and 2.4 depending on the Gods of the command-line.

wxPython, as reported by rpm -qa | grep wxPython
wxPython2.6-gtk2-unicode-2.6.3.2-fc2_py2.3

OUTLINE
I want to see the TTF fonts that I have. I don't want to install them before
I can preview them, I want to see them where they lie, on the drive on an
arbitrary path. The idea is to allow management of "groups" of fonts that can
be installed and removed in herds. If I have to design for client A then I
install all those fonts and fire-up Inkscape. After that I remove them and
install those for client B. Like that.

I have not found anything like this for Linux. On Windows, if anyone is
interested, there is a free app called "The font thing" that will do all
this.

WHERE I AM STUCK
I have hacked my way through the initial curve of wxPython. I have found a way
to draw arbitrary ttf files to a bitmap (using Python Imaging Library). I
have found how to cram that into a wxStaticBitmap. This all done by the skin
of my teeth and with google and the wxPython wiki (way cool). I have ordered
that wxPython book, but it's still floating over the Atlantic Ocean
somewhere.

I have hacked it so that I now have a wxBitmap per font preview and they
stack-up vertically in a scrolledPanel. All cool.

What I am trying to do now is make each bitmap clickable.
I want to be able to select it (have it turn inverse or blueish) so that it can be identified by
an index or an object ref or something that lets me use it.

That is where I am totally stuck. I find events in wxPy to be completely foreign to me.
I guess I was spoiled by too many years of Visual Basic! I can't seem to find which events apply to which controls.

The thing is, I have a list of the bitmaps (self.wxBitmaps) as I build them I append them to this list.
How do I point all of them to the same function (Onclick) so that they pass some kind of id or index along?

If you look at my code you will see the experiments that I have been trying.
Some are remarked, some not, they can be switched in and out.
There is a section where I focus on just one bitmap, trying to get it to call an event and to
identify itself to that handler in some way. So far no luck.

I cannot find a clear description of the form to use when assigning functions to the events,
so there is confusion about where the id goes, if it goes at all.

THE CODE
#!/usr/bin/env python2.3

#Using:
#(wxGTK, unicode, gtk2, wx-assertions-on, SWIG-1.3.27)
#Running on Python 2.3.4
import wx, os
import wx.lib.scrolledpanel as scrolled
#Requires Python Imaging Library: I have "python-imaging-1.1.4-7"
import Image, ImageFont,ImageDraw

class MainFrame(wx.Frame):
    def __init__(self,parent, id,title,position,size):
        wx.Frame.__init__(self,parent, id,title,position, size)
        #Please insert you own path to some ttf files here:
        self.fonts = self.GetFontList("/home/donn/visuals/fonts/TTFS/Z/")

        #The scrollpanel with the images in it:
        pansizer = wx.BoxSizer(wx.VERTICAL)
        self.scrollPanel = scrolled.ScrolledPanel(self, -1, size=self.GetClientSize())
        
        #The idea here is to have a long vertically scrolling list of font previews.
        #These are PIL images converted to wxStaticBitmaps because I cannot figure out
        #how to draw arbitrary fonts in wxPython that are NOT in the designated font folder (like ~/.fonts)
        
        #Let's loop the loop
        self.wxBitmaps = []
        i = 0 #Trying to tack IDs onto the bitmaps, for event purposes.
        for f in self.fonts:
            wxb = wx.StaticBitmap(self.scrollPanel, i, self.wxTtfBitmap(f,64,"The lazy fox and so on"))
            #wxb.Bind(wx.EVT_LEFT_DOWN, self.OnClick, wxb, i) #Does nothing
            #wx.EVT_LEFT_DOWN(self, i, self.OnClick) #Assertion error
            #self.scrollPanel.Bind(wx.EVT_LEFT_UP,self.OnClick,wxb,i) #Does nothing
            wx.EVT_LEFT_UP(wxb,self.OnClick) #This at least triggers the function, but there is no id()
            self.wxBitmaps.append(wxb)
            #wx.EVT_LEFT_DOWN(self.wxBitmaps[i],i,self.OnClick) #Assertion error
            #self.wxBitmaps[i].Bind(wx.EVT_LEFT_DOWN, self.OnClick, self.wxBitmaps[i], i)
            pansizer.Add(wxb,0,wx.GROW)
            i += 1
         
        #Trying to get events from a single image.
        # I Remarked the loop above when I tested this:
        #self.wxb = wx.StaticBitmap(self.scrollPanel, 100, self.wxTtfBitmap(self.fonts[0],64,"Unclickable"))
        #wxb.Bind(wx.EVT_LEFT_UP,self.OnClick,wxb,100) #Does nothing at all
        #wx.EVT_LEFT_UP(self,100,self.OnClick) #Assertion Error
        #wx.EVT_LEFT_UP(self.wxb,self.OnClick) #This at least triggers the function, but there is no id()
        #wx.EVT_LEFT_UP(wxb,100,self.OnClick)#Assertion Error
        #wx.EvtHandler.Connect(self,100,-1,wx.EVT_LEFT_UP,self.OnClick) #No go at all.
        
        self.scrollPanel.SetSizer(pansizer)
        self.scrollPanel.SetAutoLayout(1)
        self.scrollPanel.SetupScrolling()
        
        box = wx.BoxSizer(wx.VERTICAL)
        box.Add(self.scrollPanel, 0, wx.LEFT | wx.ALL | wx.ADJUST_MINSIZE, 0)
        box.Fit(self)
        self.SetAutoLayout(True)
        self.SetSizer(box)
        wx.EVT_CLOSE(self, self.OnCloseWindow)
        
    def OnClick(self,event):
        #I can't seem to find a way to identify the particular bitmap that was clicked on.
        #I would like at least an index that I can use against a list.
        print event, event.GetId(),event.GetClassName(),event.GetEventType()
        evobj = event.GetEventObject()
        print evobj #Shows the scrollPanel! Not the wxBitmap.??

    def wxTtfBitmap(self,paf,points,text):
  #Any suggestions to improve this would be oh, so cool.
        #Make the PIL image
        font = ImageFont.truetype(paf,points)
        lx,ly = font.getsize(text)
        pilimage = Image.new("F",(lx,ly),256)
        draw = ImageDraw.Draw(pilimage)
        draw.text((0,0),text,font=font)
        #PIL TO BITMAP
        #1. PIL to wxIMAGE
        wximage = wx.EmptyImage(lx,ly)
        wximage.SetData(pilimage.convert('RGB').tostring())
        #2. wxIMAGE to wxBITMAP
        return wximage.ConvertToBitmap()
   
    def OnCloseWindow(self, event):
        self.Destroy()

    def GetFontList(self, dir):
        return [os.path.join(dir,f) for f in os.listdir(dir) if f[-4:].upper() == ".TTF"]

class App(wx.App):
    def OnInit(self):
        frame = MainFrame(None, -1, "wxBitmap Test", wx.DefaultPosition,(550,200))
        self.SetTopWindow(frame)
        frame.Show(True)
        return True

app = App(0)
app.MainLoop()

THANKS
Thanks for the patience.

Donn Ingle,
South Afica.

donn wrote:

Hello there,
I am tinkering with wxPython, chasing an idea I have to write a ttf font manager for Linux.

I have never used an email list before, so I am not sure if this is the correct way to proceed. I will jump in.

WRAPPING
I don't know how to post the python code with wrapping on. I have disabled it.
The test is broken with the Enter key (Linux style). I am using Kmail so it might be horrible on Windows.
Please advise.
Can one attach (rather than paste) python code to these list emails?

Yes, attachments are fine, and usually preferred, unless the code snippet is small with little risk of wrapping issues.

What I am trying to do now is make each bitmap clickable.
I want to be able to select it (have it turn inverse or blueish) so that it can be identified by
an index or an object ref or something that lets me use it.

That is where I am totally stuck. I find events in wxPy to be completely foreign to me. I guess I was spoiled by too many years of Visual Basic! I can't seem to find which events apply to which controls.

The thing is, I have a list of the bitmaps (self.wxBitmaps) as I build them I append them to this list.
How do I point all of them to the same function (Onclick) so that they pass some kind of id or index along?

Just use the Bind method on each one to connect the events you are interested in to the same handler. The rest of the plumbing is already provided for you by wxPython. In the event handler function you are passed an event object, and you can use event.GetId() to get the ID of the wx.StaticBitmap widget that generated the event (this is either the ID you passed to the constructor, or one that was generated for you if you passed -1/wx.ID_ANY.) Or you can use event.GetEventObject() to get a reference to the wx.StaticBitmap object itself.

If you look at my code you will see the experiments that I have been trying.
Some are remarked, some not, they can be switched in and out.
There is a section where I focus on just one bitmap, trying to get it to call an event and to
identify itself to that handler in some way. So far no luck.

The basic form is this:

  destination.Bind(evtType, callable, [source, [id]])

(Square brackets denote optional args) The destination is an object where the event will be delivered where you want to catch it at, this is usually either the widget that generates the event or one of its parents where you are consolidating some functionality. For example, a combobox event will be delivered to the combobox and then its parent, and then the parent's parent and so on until a Frame or other top-level window is found or a Binding is found for the event. Not all event types propagate like this, only those that derive from wx.CommandEvent. In general the "low level" events like mouse, keyboard, paint, move, size, etc. are *not* command events, and events that are generated in response to the low level events or certain user or system actions will be command events. For example, a mouse click on a wx.Button is a low-level event, but the button catches it and turns it into a wx.EVT_BUTTON event when the proper sequence of mouse events have been received, and the wx.EVT_BUTTON event is a command event.

When you consolidate event handlers in one window class for events from multiple child windows then you often need a way to distinguish if an event came from combobox A or combobox B, or menu item 1 or menu item 2, or etc. This is where the source and/or id parameters come into play. It essentially just gives more details to the event processing system to use when searching for an event binding. For example if I use

  self.Bind(wx.EVT_BUTTON, self.DoSomething, btn1)

then DoSomething will only be called when btn1 is activated, but not btn2 even if they are located on the same parent window. (Unless you force them to have the same ID, which is not a good idea.)

I cannot find a clear description of the form to use when assigning functions to the events,
so there is confusion about where the id goes, if it goes at all.

You shouldn't need to use the id much anymore, if at all. We've added some things like Bind that extract the id for you so you don't need to worry about it.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

donn wrote:

Can one attach (rather than paste) python code to these list emails?

yes, that's the preferred way to do it for more than a few lines of
code, for just that reason (and indenting can get messed up).

PLATFORM:
Fedora Core 3 (Linux i686 AMD Athlon)
Python 2.3 and 2.4 depending on the Gods of the command-line.

wxPython, as reported by rpm -qa | grep wxPython
wxPython2.6-gtk2-unicode-2.6.3.2-fc2_py2.3

Excellent! a lot of folks forget to provide this info.

WHERE I AM STUCK
I have hacked my way through the initial curve of wxPython. I have found a way to draw arbitrary ttf files to a bitmap (using Python Imaging Library). I have found how to cram that into a wxStaticBitmap.

In general, wxStaticBitmap has few features. You might want to create
your own class, derived from wx.Window, that displays the Bitmap and
holds the logic you want in it. This would make your event binding a bit
easier too.

I guess I was spoiled by too many years of Visual Basic!

Spoiled is the word! And not in a good way!

The thing is, I have a list of the bitmaps (self.wxBitmaps) as I build them I append them to this list.
How do I point all of them to the same function (Onclick) so that they pass some kind of id or index along?

The event that gets passed to your handler has the ID of the wxWindow
that generated it. There was some discussion about this recently on this
list.

I cannot find a clear description of the form to use when assigning functions to the events,
so there is confusion about where the id goes, if it goes at all.

I try to avoid explicit IDs whenever possible. See:

http://wiki.wxpython.org/index.cgi/wxPython_Style_Guide

A suggestion: try to post code that doesn't rely on other libs, like
PIL. In this case, you could just load a couple bitmaps from files for
testing. This would also keep you from needing to point to ttf files.

A few comments on your code, to get you started:

THE CODE
#!/usr/bin/env python2.3

Why not 2.4? 2.3 is getting pretty old in the tooth!

        self.scrollPanel = scrolled.ScrolledPanel(self, -1, size=self.GetClientSize())

You can leave the id out altogether:

self.scrollPanel = scrolled.ScrolledPanel(self,
                        size=self.GetClientSize())

I cannot figure out how to draw arbitrary fonts in wxPython that are NOT
in the designated font folder (like ~/.fonts)

This is a problem that I don't know the solution too, but I'd like to!
Anyone?

        i = 0 #Trying to tack IDs onto the bitmaps, for event purposes.

don't do that! If you need an ID, use wx.NewId()

        for f in self.fonts:
            wxb = wx.StaticBitmap(self.scrollPanel, i, self.wxTtfBitmap(f,64,"The lazy fox and so on"))
            #wxb.Bind(wx.EVT_LEFT_DOWN, self.OnClick, wxb, i) #Does nothing

This should work:

wxb.Bind(wx.EVT_LEFT_DOWN, self.OnClick)

You don't need the last two arguments, you're calling the Bind method of
the object, it knows what it is!

        evobj = event.GetEventObject()
        print evobj #Shows the scrollPanel! Not the wxBitmap.??

Ahh! here's your problem, I think. wxStaticBitmaps are just that:
Static. They are a thin wrapper around simple code that jsut draws a
bitmapon the wx.Window, they aren't full Windows, and don't have full
event handling capability. This varies according to platform as well.

IN fact, I jsut tried this in some of my code, and found the same thing. clicking on the StaticBitmap raised the event, but

event.GetID() and event.GetEventObject()

both returned the object and ID of the parent, rather than the StaticBitmap. Is this a bug?

You might want to create your own class, or you might be able to use a
wx.BitmapButton, or one of the classes in wx.Python.lib.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Christopher Barker wrote:

IN fact, I jsut tried this in some of my code, and found the same thing. clicking on the StaticBitmap raised the event, but

event.GetID() and event.GetEventObject()

both returned the object and ID of the parent, rather than the StaticBitmap. Is this a bug?

Yes. I thought that was fixed when they added the ability to find the right widget to send the event to. I'll look into implementing a fix.

You might want to create your own class, or you might be able to use a
wx.BitmapButton, or one of the classes in wx.Python.lib.

See wx.lib.statbmp, it's a generic version of wx.StaticBitmap.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Yes. I thought that was fixed when they added the ability to find the
right widget to send the event to. I'll look into implementing a fix.

Thanks.

> You might want to create your own class, or you might be able to use a
> wx.BitmapButton, or one of the classes in wx.Python.lib.
See wx.lib.statbmp, it's a generic version of wx.StaticBitmap.

I will try my hand at these beasties.

On this topic of investigating the internals of Python libraries, I am
currently struggling with various techniques:
1. I open SPE type wx and hit the dot. Then I wait (and wait) for the list to
open so I can scroll around and try to guess what methods and events are the
ones I might need.
2. I open pycrust, import wx and then try to navigate the endless tree-view.
3. I grep through the api folder.
4. I google until my fingers bleed : )

Are there better ways to get the dope?

Thanks for all the tips.
Donn

···

On Thursday 27 April 2006 01:29, Robin Dunn wrote:

Just use the Bind method on each one to connect the events you are
... snip ...
  self.Bind(wx.EVT_BUTTON, self.DoSomething, btn1)
then DoSomething will only be called when btn1 is activated, but not
btn2 even if they are located on the same parent window. (Unless you
force them to have the same ID, which is not a good idea.)

Thank you for the detailed explanation. I can't say I totally grok it all, I
will have to get some more experience in using events.

You shouldn't need to use the id much anymore, if at all. We've added
some things like Bind that extract the id for you so you don't need to
worry about it.

Ah, I was wondering if "Bind" was newer than wx.EVT_xxx(stuff) which is
suggested in the wiki under the getting started tutorial.

Donn

···

On Wednesday 26 April 2006 23:26, Robin Dunn wrote:

> PLATFORM:
> Fedora Core 3 (Linux i686 AMD Athlon)
> Python 2.3 and 2.4 depending on the Gods of the command-line.
>
> wxPython, as reported by rpm -qa | grep wxPython
> wxPython2.6-gtk2-unicode-2.6.3.2-fc2_py2.3

Excellent! a lot of folks forget to provide this info.

Should one provide it on every reply to a given 'post' or only in the OP ?

In general, wxStaticBitmap has few features. You might want to create
your own class, derived from wx.Window, that displays the Bitmap and
holds the logic you want in it. This would make your event binding a bit
easier too.

I am fuzzy on this notion. Is there an example you could point me to. I gather
that it will be something like "class myBitmap(wx.Window):", but as to what
goes in the __init__ and so forth, and how to cater for events I am too new
to this game to guess.

> I guess I was spoiled by too many years of Visual Basic!
Spoiled is the word! And not in a good way!

<derail>
I know it's fashionable to dis VB, but I never really saw the reason for it. I
came from Z80A under GW-Basic (on an old Spectravideo 318) through DOS and
various flavours of Basic like PowerBasic (wow) and so VB was a natural
extension of my skills. (You can tell I'm a spaghetti-function man! OOP is
still kinda eerie to my mind.)
Its IDE certainly facilitates the use of the language: quick auto-complete,
clear arrangements of methods and events, quick ways to jump between sections
and modules, not to mention the dead simple form creation and use. Sure, many
things sucked, but seen from a high-level perspective it's very effective.
If they pulled their fingers out and made it cross platform, well... But we
all know that will never happen.
</derail>

A suggestion: try to post code that doesn't rely on other libs, like
PIL. In this case, you could just load a couple bitmaps from files for
testing. This would also keep you from needing to point to ttf files.

Right. I actually wondered about that bit, but then assumed PIL would be
common for Python devs. I take note and remember.

A few comments on your code, to get you started:
> THE CODE
> #!/usr/bin/env python2.3

Why not 2.4? 2.3 is getting pretty old in the tooth!

To tell the truth, this was adapted from a copypaste from the wiki.

> self.scrollPanel = scrolled.ScrolledPanel(self, -1,
> size=self.GetClientSize())
You can leave the id out altogether:

Okay. Gotcha.

> I cannot figure out how to draw arbitrary fonts in wxPython that are NOT
> in the designated font folder (like ~/.fonts)
This is a problem that I don't know the solution too, but I'd like to!
Anyone?

Hence my mangling a ttf via PIL into a wxBitmap of sorts. Surely not the
fastest or most memory forgiving process. Then again, what do I know about
drawing TTF fonts!

> evobj = event.GetEventObject()
> print evobj #Shows the scrollPanel! Not the wxBitmap.??
Ahh! here's your problem, I think. wxStaticBitmaps are just that:
Static. They are a thin wrapper around simple code that jsut draws a
bitmapon the wx.Window, they aren't full Windows, and don't have full
event handling capability. This varies according to platform as well.

IN fact, I jsut tried this in some of my code, and found the same thing.
clicking on the StaticBitmap raised the event, but

event.GetID() and event.GetEventObject()

both returned the object and ID of the parent, rather than the
StaticBitmap. Is this a bug?

You might want to create your own class, or you might be able to use a
wx.BitmapButton, or one of the classes in wx.Python.lib.

Right, thanks. I have asked further questions about this in another reply,
specifically if there is any code I can refer to to help me understand this.

Donn.

···

On Thursday 27 April 2006 00:48, Christopher Barker wrote:

donn wrote:

Its IDE certainly facilitates the use of the language:

Actually, I have heard a LOT about how nice the VB IDE is. I haven't used any of the commercial Python ones, but they may be worth a look-see.

Right, thanks. I have asked further questions about this in another reply, specifically if there is any code I can refer to to help me understand this.

You can try poking around the Wiki and wx.lib.

It looks like there may be something close to what you need there anyway.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                          
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

I must be dense because I cannot fin wx.lib.statbmp in pycrust/pyfilling. The
nearest I can get is wx.lib.slice (going by alphabet).
What am I missing?

Donn

···

On Thursday 27 April 2006 07:57, donn wrote:

> > wx.BitmapButton, or one of the classes in wx.Python.lib.
> See wx.lib.statbmp, it's a generic version of wx.StaticBitmap.

Well, I have tried some more and have had no luck.
This post contains an attachment.

I tried the first suggestion of "wrapping" wx.Window, but I can't get it to
display the wxStaticBitmap that I define within my new class. I am guessing
that I must perform Paint( ) routines. I'm lost.

I tried the wx.lib.statbmp approach - as was suggested to me. I found the
definition in the API. That is what is attached.

Now it draws the image, but from what I can see it does not raise any events
at all.

Can someone give me a hand here? I need a bitmap that can be clicked. I need
to be able to handle the events from a list of many bitmaps (that can get
clicked) in one place.

If all else fails I will try the bitmap button approach. Not ideal, but better
than nothing.

Thanks,
Donn.

wrapwxbitmap.py (1.03 KB)

This may work:

Instead of:
        #self.Bind(wx.EVT_LEFT_UP,self.OnClick,p1)
do:
        p1.Bind(wx.EVT_LEFT_UP,self.OnClick)

···

On Thu, 2006-04-27 at 15:51 +0200, donn wrote:

Now it draws the image, but from what I can see it does not raise any events
at all.

Can someone give me a hand here? I need a bitmap that can be clicked. I need
to be able to handle the events from a list of many bitmaps (that can get
clicked) in one place.

Thanks Ricardo, at least there's some life now.

Two questions more:
1.
The bind command was described by Robin Dunn thusly to me:

destination.Bind(evt,call,[source,[id]])

Where destination was described as: Where the event will be delivered.

So, why was using self.Bind( ) a mistake? Why could the event not be delivered
to self (a wx.Frame)?

2.
If I wanted to subclass wx.Window in order to draw a bitmap, what would the
code look like? Please see my attempt attached. It does not show the image.

Thanks,
Donn

wrapwxwindow.py (1.15 KB)

···

On Thursday 27 April 2006 16:45, Ricardo Pedroso wrote:

This may work:

Instead of:
        #self.Bind(wx.EVT_LEFT_UP,self.OnClick,p1)
do:
        p1.Bind(wx.EVT_LEFT_UP,self.OnClick)

See attachments...

wrapwxwindow.py (1.3 KB)

wrapwxwindow2.py (1.24 KB)

···

On Thu, 2006-04-27 at 17:38 +0200, donn wrote:

2.
If I wanted to subclass wx.Window in order to draw a bitmap, what would the
code look like? Please see my attempt attached. It does not show the image.

donn wrote:

The bind command was described by Robin Dunn thusly to me:

destination.Bind(evt,call,[source,[id]])

Where destination was described as: Where the event will be delivered.

So, why was using self.Bind( ) a mistake? Why could the event not be delivered to self (a wx.Frame)?

It's a matter of defining what "delivered" means. The event is delivered by the system to an object, in this case your BitmapWindow. From there, two things can happen, depending on what kind of event you are dealing with. Mouse events are the type that can only get bound in the Window they are first delivered to. If you don't bind it there, it disappears.

The other kind of event is called a "Command Event", and it will keep moving up from child to parent to see if it gets caught. Robin wrote about this earlier in this thread, maybe if you go back and read it again, will make more sense now.

As this is a mouse event, it is not a command event, so you can't catch it in the parent frame, only in the Window itself.

If I wanted to subclass wx.Window in order to draw a bitmap, what would the code look like?

Below is the the source to statbmp.py You can find it in:

/usr/lib/python2.4/site-packages/wx-2.6-gtk2-unicode/wx/lib

or something like that, depending on your system.

I'd either start with this, or you can subclass it, and then bind Mouse events in it to do what you want inside this object, rather than doing it all in the Frame.

By the way, I hope this hasn't been too frustrating for you. Right when you got started with wx, you got bitten by a bug. Please be assured that that's actually pretty rare, and not par for the course. This is giving you an opportunity to learn stuff that you'll be glad you know later!

-Chris

···

#----------------------------------------------------------------------
# Name: wx.lib.statbmp
# Purpose: A generic StaticBitmap class.
#
# Author: Robin Dunn
#
# Created: 12-May-2004
# RCS-ID: $Id: statbmp.py,v 1.4 2005/05/02 23:43:56 RD Exp $
# Copyright: (c) 2004 by Total Control Software
# Licence: wxWindows license
#----------------------------------------------------------------------

import wx

#----------------------------------------------------------------------

class GenStaticBitmap(wx.PyControl):
     labelDelta = 1

     def __init__(self, parent, ID, bitmap,
                  pos = wx.DefaultPosition, size = wx.DefaultSize,
                  style = 0,
                  name = "genstatbmp"):
         if not style & wx.BORDER_MASK:
             style = style | wx.BORDER_NONE
         wx.PyControl.__init__(self, parent, ID, pos, size, style,
                              wx.DefaultValidator, name)
         self._bitmap = bitmap
         self.InheritAttributes()
         self.SetBestFittingSize(size)

         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
         self.Bind(wx.EVT_PAINT, self.OnPaint)

     def SetBitmap(self, bitmap):
         self._bitmap = bitmap
         self.SetBestFittingSize( (bitmap.GetWidth(), bitmap.GetHeight()) )
         self.Refresh()

     def GetBitmap(self):
         return self._bitmap

     def DoGetBestSize(self):
         """
         Overridden base class virtual. Determines the best size of the
         control based on the bitmap size.
         """
         return wx.Size(self._bitmap.GetWidth(), self._bitmap.GetHeight())

     def AcceptsFocus(self):
         """Overridden base class virtual."""
         return False

     def GetDefaultAttributes(self):
         """
         Overridden base class virtual. By default we should use
         the same font/colour attributes as the native StaticBitmap.
         """
         return wx.StaticBitmap.GetClassDefaultAttributes()

     def ShouldInheritColours(self):
         """
         Overridden base class virtual. If the parent has non-default
         colours then we want this control to inherit them.
         """
         return True

     def OnPaint(self, event):
         dc = wx.PaintDC(self)
         if self._bitmap:
             dc.DrawBitmap(self._bitmap, 0, 0, True)

     def OnEraseBackground(self, event):
         pass

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

I found myself feeling compelled to comment on this one. It (almost)
make things look bad when I've got a bug as well that seems to have been
corrected in CVS (I've got another thread regarding it, something about
pywxrc, InitXmlResource, and other stuff in the subject).

I do understand and believe that it's pretty rare, but it *is* funny to
see such a thing happen twice in one day :slight_smile:

···

On Thu, Apr 27, 2006 at 01:43:02PM -0700, Christopher Barker wrote:

By the way, I hope this hasn't been too frustrating for you. Right when
you got started with wx, you got bitten by a bug. Please be assured that
that's actually pretty rare, and not par for the course. This is giving
you an opportunity to learn stuff that you'll be glad you know later!

--
Michael J. Pedersen
My IM IDs: Jabber/pedersen@icelus.tzo.com, ICQ/103345809, AIM/pedermj022171
           Yahoo/pedermj2002, MSN/pedermj022171@hotmail.com
My GnuPG KeyID: 4E724A60 My Public Key Available At: pgp.mit.edu
My GnuPG Key Fingerprint: C31C 7E90 5992 9E5E 9A02 233D D8DD 985E 4E72 4A60

Heh, I read "bitten by a bug" as I got "infected" by the wx programming 'bug'
and now I was doomed to a blissfull life of wxpython coding! It scanned as
charming, if a little weird :slight_smile:

Donn

···

On Thursday 27 April 2006 22:53, Michael J. Pedersen wrote:

On Thu, Apr 27, 2006 at 01:43:02PM -0700, Christopher Barker wrote:
> By the way, I hope this hasn't been too frustrating for you. Right when
> you got started with wx, you got bitten by a bug.

snip

I found myself feeling compelled to comment on this one. It (almost)
snip
I do understand and believe that it's pretty rare, but it *is* funny to
see such a thing happen twice in one day :slight_smile:

Thank you for the detailed info. Thank you for the time. I am up at 3:22 am
for some silly reason so will check this code out on the morrow. Right now,
back to sleep.
Donn

···

On Thursday 27 April 2006 22:43, Christopher Barker wrote:

donn wrote:
> The bind command was described by Robin Dunn thusly to me:
>
> destination.Bind(evt,call,[source,[id]])
>
> Where destination was described as: Where the event will be delivered.
>
> So, why was using self.Bind( ) a mistake? Why could the event not be
> delivered to self (a wx.Frame)?

It's a matter of defining what "delivered" means. The event is delivered
  by the system to an object, in this case your BitmapWindow. From
there, two things can happen, depending on what kind of event you are
dealing with. Mouse events are the type that can only get bound in the
Window they are first delivered to. If you don't bind it there, it
disappears.

The other kind of event is called a "Command Event", and it will keep
moving up from child to parent to see if it gets caught. Robin wrote
about this earlier in this thread, maybe if you go back and read it
again, will make more sense now.

As this is a mouse event, it is not a command event, so you can't catch
it in the parent frame, only in the Window itself.

> If I wanted to subclass wx.Window in order to draw a bitmap, what would
> the code look like?

Below is the the source to statbmp.py You can find it in:

/usr/lib/python2.4/site-packages/wx-2.6-gtk2-unicode/wx/lib

or something like that, depending on your system.

I'd either start with this, or you can subclass it, and then bind Mouse
events in it to do what you want inside this object, rather than doing
it all in the Frame.

By the way, I hope this hasn't been too frustrating for you. Right when
you got started with wx, you got bitten by a bug. Please be assured that
that's actually pretty rare, and not par for the course. This is giving
you an opportunity to learn stuff that you'll be glad you know later!

-Chris

#----------------------------------------------------------------------
# Name: wx.lib.statbmp
# Purpose: A generic StaticBitmap class.
#
# Author: Robin Dunn
#
# Created: 12-May-2004
# RCS-ID: $Id: statbmp.py,v 1.4 2005/05/02 23:43:56 RD Exp $
# Copyright: (c) 2004 by Total Control Software
# Licence: wxWindows license
#----------------------------------------------------------------------

import wx

#----------------------------------------------------------------------

class GenStaticBitmap(wx.PyControl):
     labelDelta = 1

     def __init__(self, parent, ID, bitmap,
                  pos = wx.DefaultPosition, size = wx.DefaultSize,
                  style = 0,
                  name = "genstatbmp"):
         if not style & wx.BORDER_MASK:
             style = style | wx.BORDER_NONE
         wx.PyControl.__init__(self, parent, ID, pos, size, style,
                              wx.DefaultValidator, name)
         self._bitmap = bitmap
         self.InheritAttributes()
         self.SetBestFittingSize(size)

         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
         self.Bind(wx.EVT_PAINT, self.OnPaint)

     def SetBitmap(self, bitmap):
         self._bitmap = bitmap
         self.SetBestFittingSize( (bitmap.GetWidth(), bitmap.GetHeight()) )
         self.Refresh()

     def GetBitmap(self):
         return self._bitmap

     def DoGetBestSize(self):
         """
         Overridden base class virtual. Determines the best size of the
         control based on the bitmap size.
         """
         return wx.Size(self._bitmap.GetWidth(), self._bitmap.GetHeight())

     def AcceptsFocus(self):
         """Overridden base class virtual."""
         return False

     def GetDefaultAttributes(self):
         """
         Overridden base class virtual. By default we should use
         the same font/colour attributes as the native StaticBitmap.
         """
         return wx.StaticBitmap.GetClassDefaultAttributes()

     def ShouldInheritColours(self):
         """
         Overridden base class virtual. If the parent has non-default
         colours then we want this control to inherit them.
         """
         return True

     def OnPaint(self, event):
         dc = wx.PaintDC(self)
         if self._bitmap:
             dc.DrawBitmap(self._bitmap, 0, 0, True)

     def OnEraseBackground(self, event):
         pass

--

"It appears to me (whether rightly or wrongly) that direct arguments against
christianity and theism produce hardly any effect on the public; and freedom
of thought is best promoted by the gradual illumination of men's minds which
follows from the advance of science." -- Charles Robert Darwin

--

donn wrote:

···

On Thursday 27 April 2006 00:48, Christopher Barker wrote:

PLATFORM:
Fedora Core 3 (Linux i686 AMD Athlon)
Python 2.3 and 2.4 depending on the Gods of the command-line.

wxPython, as reported by rpm -qa | grep wxPython
wxPython2.6-gtk2-unicode-2.6.3.2-fc2_py2.3

Excellent! a lot of folks forget to provide this info.

Should one provide it on every reply to a given 'post' or only in the OP ?

The first post is usually enough, unless the thread drags on for long enough that people forget.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Just got my copy of "wxPython in action" ! Thanks for the book Robin Dunn.

Donn.