Painting How-To [Screwed up last mail list]

I’m making a little raster editor in wxPython and I’ve come across some trouble. I’m able to paint tools such as brushes and fill no problem, because they are drawn onto my buffer directly. Tools I’m having trouble with are lines, circles, and the likes, because they should be temporarily drawn to the screen - and only drawn to the buffer once the mouse is let go. I’ve been stuck on this problem for quite some time now, having tried so many methods and failed them all, so now I come to you nice people. I’d really appreciate it if you could tell me what I’m doing wrong.

I have attatched my program to this message. As you can see, the line tool creates huge amounts of flickering, and doesn’t even work properly. I’d really like it to be smooth with the buffer. Well, thanks in advance to anyone who helps!

paint.py (3.16 KB)

first, a couple style comments:

- it really is better to use spaces than tabs to indent -- it's more or less the python standard.

- ID_TOOL_BRUSH=wx.NewId()
   ID_TOOL_LINE=wx.NewId()
   Explicit IDs are kind of ugly, see:
   http://wiki.wxpython.org/wxPython_Style_Guide

Instead of ID_TOOL_whatever, you could have a tool object, or a string, or better yet, put your drawing code, etc into a tool object, then you wouldn't even need to know what kind of tool object it was.

But now to the real issues:

Your Paint handler should call the same Draw method -- rather than duplicating the code there.

One good method for doing this kind of thing is to not actually re-draw the whole buffer each time. what you can do instead is draw a "shadow" of your object as the mouse moves -- you do this with a ClientDC and set the DC mode to XOR -- draw once, you get a reverse color version, draw again and it's back to the original bitmap underneath.

However, what you've doing should work OK -- drawing bitmaps to the screen is very fast. a few issue though:

         dc=wx.BufferedDC(wx.ClientDC(self), self.buffer)
         dc.DrawBitmap(self.buffer, 0, 0)

you don't want to draw the buffer to a buffered DC, it will draw itself. You want a regular ClientDC. And you want to just draw there, rather than in a Paint Handler (you could do it there, but you're kind of doing both now)

Then, on mouse-up, you need to draw the final line to the buffer -- note that this is why you want your drawing code to be in a Line object -- then you can put it in only one place.

By the way, I'd like to discourage you from making a bitmap editor like this -- why not make it a vector object editor -- you always save the resulting bitmap out later, but if you keep vector objects, then you can change them, move them, re-scale, etc, etc.

You might want to look at wx.lib.floatcanvas for some ideas. Or the latest version and extra demos here:

http://morticia.cs.dal.ca/FloatCanvas/

Enclosed is my edited version, which seems to work. It could still use some cleaning up.

junk.py (4.2 KB)

···

--
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@noaa.gov

Hi Kevin, Chris & All,

Hi Chris,

> first, a couple style comments:
>
> - it really is better to use spaces than tabs to indent -- it's more
> or less the python standard.
>
> - ID_TOOL_BRUSH=wx.NewId()
> ID_TOOL_LINE=wx.NewId()
> Explicit IDs are kind of ugly, see:
> http://wiki.wxpython.org/wxPython_Style_Guide
>
> Instead of ID_TOOL_whatever, you could have a tool object, or a
> string, or better yet, put your drawing code, etc into a tool
> object, then you wouldn't even need to know what kind of tool object
> it was.

BTW, any possibility you could put together a more complete example of
"no ID usage" with menu and toolbar items? The link you posted only
has an example using a menu item with a standard ID, and doesn't
address checking menu items in, say, UpdateUI or other event handlers.
(And perhaps with XRC files, I don't know if there's anything special
there?) I'd actually like to move away from using IDs, and have played
with things like some MVC separation of menu/toolbar items, but so far
I haven't been able to figure out how to get rid of IDs throughout the
program and I'm not aware of any good examples showing how to get away
from them while still working with UpdateUI, etc.

I don't know if I grasped exactly the issue here and if I understood
correctly your suggestion, but could you (and everyone who wishes so)
please try the attached example and see if it does what you asked? It
might be refactored a bit, but it's something I put together in half
an hour...
If it answers your question, I will go for a Wiki page as soon as I
have some time. If it doesn't, could you please explain what's missing
(or tell me that I have completely missed the point)? :smiley:

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

MenuTest.py (19.1 KB)

···

On Dec 4, 2007 9:01 PM, Kevin Ollivier wrote:

On Dec 4, 2007, at 11:46 AM, Christopher Barker wrote:

Hi Andrea,

Hi Kevin, Chris & All,

Hi Chris,

first, a couple style comments:

- it really is better to use spaces than tabs to indent -- it's more
or less the python standard.

- ID_TOOL_BRUSH=wx.NewId()
ID_TOOL_LINE=wx.NewId()
Explicit IDs are kind of ugly, see:
http://wiki.wxpython.org/wxPython_Style_Guide

Instead of ID_TOOL_whatever, you could have a tool object, or a
string, or better yet, put your drawing code, etc into a tool
object, then you wouldn't even need to know what kind of tool object
it was.

BTW, any possibility you could put together a more complete example of
"no ID usage" with menu and toolbar items? The link you posted only
has an example using a menu item with a standard ID, and doesn't
address checking menu items in, say, UpdateUI or other event handlers.
(And perhaps with XRC files, I don't know if there's anything special
there?) I'd actually like to move away from using IDs, and have played
with things like some MVC separation of menu/toolbar items, but so far
I haven't been able to figure out how to get rid of IDs throughout the
program and I'm not aware of any good examples showing how to get away
from them while still working with UpdateUI, etc.

I don't know if I grasped exactly the issue here and if I understood
correctly your suggestion, but could you (and everyone who wishes so)
please try the attached example and see if it does what you asked? It
might be refactored a bit, but it's something I put together in half
an hour...
If it answers your question, I will go for a Wiki page as soon as I
have some time. If it doesn't, could you please explain what's missing
(or tell me that I have completely missed the point)? :smiley:

Yes, this is pretty much what I'm looking for. The only thing is that I find the tuple approach very flexible overall, although it's possible I'm still missing something. I have to deal with cases like submenus, and so the tuple approach can get a hard to read when you expand that menubar to have 25-30 total items instead of 6-7 with nested submenus.

Ultimately what I'd like to see is a general purpose mixin that someone can just derive from, set their menu/toolbar 'model' using CreateMenuBar(mbarmodel) or CreateToolBar(tbarmodel), and the rest is handled by the mixin. IMHO the 'next generation' is really about coming up with simple approaches and not asking each user to write the same logic in every one of their apps. (e.g. requiring each user to devise their own solution to make wxPython apps more MVC-oriented.) I think what you have is actually very close, but I'm wondering if there isn't a better way to define the model component for menubars and toolbars...

Anyway, this definitely should be on the wiki. :slight_smile:

Thanks,

Kevin

···

On Dec 4, 2007, at 4:35 PM, Andrea Gavana wrote:

On Dec 4, 2007 9:01 PM, Kevin Ollivier wrote:

On Dec 4, 2007, at 11:46 AM, Christopher Barker wrote:

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
<MenuTest.py>---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org