[fc] Graphical Hierarchy Tree in wxPython

Christopher Barker Chris.Barker at noaa.gov
Mon Jul 16 16:31:46 PDT 2007


Astan Chee wrote:
> So I've finished modifying the wxDragImage class to support what I =

> wanted to do as mentioned above.


Your code wouldn't run for me on OS-X. It turns out that you can't call =

DC.Clear() on a MemoryDC until after the Bitmap is Selected into it, =

which makes sense. While I was making that fix, I had to change the =

order of calling:

                     dc =3D wx.MemoryDC()
                     dc.Clear()
                     dc.SelectObject(bmp)

to:

                     dc =3D wx.MemoryDC()
                     dc.SelectObject(bmp)
                     dc.Clear()

in a LOT of places, which says to me that you need some re-factoring -- =

the DRY (Don't Repeat Yourself) is a good one to follow.

I also found in SetSelected and SetUnSelected, the lines:

             self.bmp =3D wx.EmptyBitmap(self.size.GetWidth(), =

self.size.GetHeight())
             memDC =3D wx.MemoryDC()
             memDC.SelectObject(self.bmp)
             memDC.Clear()
             memDC.SetTextForeground(wx.RED)
             memDC.SetFont(font)
             memDC.DrawText(self.text, 0, 0)
             memDC.SelectObject(wx.NullBitmap)
             mask =3D wx.Mask(self.bmp, bg_colour)
             self.bmp.SetMask(mask)

             dc.Blit(self.pos.x, self.pos.y,
                     self.bmp.GetWidth(), self.bmp.GetHeight(),
                     memDC, 0, 0, op, True)

and got an error with the Blit() call: you can't do:

memDC.SelectObject(wx.NullBitmap)

Then expect to do the Blit with that DC! However, there may be a reason =

for that line -- but it can't go there in that way.

Also, the code in those two methods is very similar -- again DRY!

Then I got:
Traceback (most recent call last):
   File "./wxDragImage.py", line 688, in OnLeftUp
     self.dragShape.line.Draw(dc)
   File "./wxDragImage.py", line 37, in Draw
     memDC, 0, 0, op, True)
   File =

"//Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-pack=
ages/wx-2.8-mac-unicode/wx/_gdi.py", =

line 3373, in Blit
     return _gdi_.DC_Blit(*args, **kwargs)
wx._core.PyAssertionError: C++ assertion "Ok()" failed at =

/BUILD/wxPython-src-2.8.4.0/src/common/dcgraph.cpp(733) in DoBlit(): =

wxGCDC(cg)::DoBlit - invalid DC

I'm not sure what that's about yet, so I don't have your code fully =

running.

I see this (in Expand, but probably I other places):
if self.bmp.Ok():
     bg_colour =3D wx.Colour(0, 0, 0)
     font =3D wx.Font(15, wx.ROMAN, wx.NORMAL, wx.BOLD)
     self.bmp =3D wx.EmptyBitmap(self.size.GetWidth(), self.size.GetHeight(=
))

looks like a potential error: Why check if the bmp is Ok() if you're =

going to make a new one anyway?

I worked with the wx. namespace version that someone posted to the =

wxPython list -- I found a few more spots to fix.

I also got rid of the dependency on the Demo "Run.py" script, creating a =

simple wx.App instead.



> I didn't use FloatCanvas for this =

> because I wanted to display text

FloatCanvas handles Text just fine.

> also I seemed to like the wxDragImage =

> better. As for zooming, I think scrolling is the same thing.

no, it's not -- you may not need zooming, but it would let you see more =

of less of the tree as you like.

Anyway, all the problems I describe above point out why FloatCanvas is =

so nifty -- all that working nwioth bitmaps and wxDCs is a pain in teh =

*&&^*. That's why I wrote FloatCanvas -- I had to figure it all out in =

there, and now it just works for you.

Also, maybe there is still something wrong with your code on OS-X, but =

it is intensely slow when re-sizing or really just about any interaction.

> The code =

> works by creating a hierarchy from dictionaries that may contain other =

> (deeper) dictionaries.

and also lists of string -- I found it a bit tricky to parse out the =

tree, as it wasn't internally consistent.

Anyway, I've make a stab at doing it with FloatCanvas. You tree layout =

code was pretty enmeshed with the DragObject code, so rather than =

duplicating it, I started from scratch. As you well know, laying out a =

tree like that is far from trivial, and I've not done anything =

brilliant, but it works OK. You do need to know the depth of the tree =

before hand to make it work, though.

Anyway, that's not the point. What I have now is a FloatCanvas based =

version that zooms, scrolled, lets you drag the nodes around, and is =

pretty darn snappy.

It needs some refactoring before it's expanded much - the tree layout =

code should be a separate module, You definately don't want hard coded =

data, and you'll probably want a niftier DrawObject to represent your =

nodes, etc.

Enclosed is the code and a screen shot. It should work with the =

FloatCanvas shipped with wxPython 2.8.4

-Chris

PS: not one reference to a Bitmap, MemoryDC, Blit, etc.


-- =

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker at noaa.gov
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screenshot.png
Type: image/png
Size: 46130 bytes
Desc: not available
Url : http://lists.wxwidgets.org/pipermail/wxpython-users/attachments/20070=
716/b0112c80/Screenshot.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Tree.py
Type: text/x-python
Size: 9704 bytes
Desc: not available
Url : http://lists.wxwidgets.org/pipermail/wxpython-users/attachments/20070=
716/b0112c80/Tree.py


More information about the wxpython-users mailing list