[wxPython] Persistent Display???

I'm looking for a window that will incrementally add text strings with
out keeping track of them all. (i.e. I want to use the display frame
buffer as my display memory.) In the program below, additional text
strings to be displayed come in whenever the mouse is clicked as
fgColor:wxBLUE, bgColor:wxWHITE, X:100, Y:200, text: "Clicked Here".

Unfortunately, I can't seem to stop the window erase on an EVT_PAINT
event, and therefore lose all the prior text strings that were
displayed. I trapped the EVT_ERASE_BACKGROUND event but could not
prevent the window erasing.

Also the SetTextBackground method of wxDC does not seem to do anything.

I have included a little test program to demonstrate my dilemma

COLORLIST = [wxBLUE, wxRED, wxBLACK, wxGREEN]
DEFAULT_FORECOLOR = COLORLIST[0]
DEFAULT_BACKCOLOR = COLORLIST[0]

class MBDisplay(wxWindow):
        def __init__(self, parent, id,
pos=wxDefaultPosition,size=wxDefaultSize):
                wxWindow.__init__(self, parent, id, pos, size)
                self.SetBackgroundColour(wxNamedColour('white'))
                self.font = wxFont(12, wxMODERN, wxNORMAL,
wxNORMAL,faceName='courier')
                EVT_PAINT(self, self.OnPaint)
                EVT_ERASE_BACKGROUND(self, self.eraseBackground)
                EVT_LEFT_DOWN(self, self.OnClick)

                self.random = whrandom.whrandom()

    # INFO FOR MAKING THE TEXT DISPLAY, UPDATED WHEN MOUSE IS CLICKED
                self.drawInfo = (DEFAULT_BACKCOLOR, DEFAULT_FORECOLOR,
100, 100, "In the beginning")

        def Draw(self, dc = None):
                if not dc:
                        dc = wxClientDC(self)
                dc.SetFont(self.font)
                xPos = self.drawInfo[2]
                yPos = self.drawInfo[3]
                textSize = dc.GetTextExtent(self.drawInfo[4])
                dc.SetClippingRegion(xPos, yPos, textSize[0],
textSize[1])
                dc.Clear()
                dc.SetTextForeground(self.drawInfo[1])
                # THIS LINE DOES NOT SEEM TO DO ANYTHING
                dc.SetTextBackground(self.drawInfo[0])
                dc.DrawText(self.drawInfo[4], xPos, yPos)

        def OnPaint(self, event):
                # WHEN THIS GETS CALLED WINDOW GETS ERASED
                dc = wxPaintDC(self)
                self.Draw(dc)
                print 'OnPaint called'

        def eraseBackground(self, event):
                # GETS CALLED BUT DOES NOT SEEM TO STOP THE WINDOW
ERASE
                print 'eraseBackground called'
                return TRUE
# event.Skip()

        def OnClick(self, event):
                x = event.GetX()
                y = event.GetY()
                # pick random colors for text and background
                bgNum = self.random.randint(0, len(COLORLIST) - 1)
                fgNum = self.random.randint(0, len(COLORLIST) - 1)
                bgColor = COLORLIST[bgNum]
                fgColor = COLORLIST[fgNum]
                self.drawInfo = (bgColor, fgColor, x, y, "Clicked Here")
                self.Draw()

class MBDisplayFrame(wxFrame):
        def __init__(self, parent, id, title):
                self.id = id
                # First, call the base class' __init__ method to create
the frame
                wxFrame.__init__(self, parent, id, title, wxPoint(100,
100), wxSize(645, 485))
# EVT_ERASE_BACKGROUND(self, self.eraseBackground)
                # create window
                wid = NewId()
                self.mbd = MBDisplay(self,wid)

        def eraseBackground(self, event):
                print 'Frame eraseBackground called'
# event.Skip()
# return FALSE

        def OnCloseWindow(self,event):
                self.Destroy()

class MyApp(wxApp):
        def OnInit(self):
                mbDisplay = MBDisplayFrame(NULL, -1, 'Display window')
                mbDisplay.Show(true)
                self.SetTopWindow(mbDisplay)
                return true

if __name__ == "__main__":
        app = MyApp(0) # Create an instance of the application class
        app.MainLoop() # Tell it to start processing events

Patrick Gaffney
patrickg@asti-usa.com

···

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/mailman/listinfo/wxpython-users

Maybe what you want is a double buffering strategy. Write your text and
other stuff
an off-screen memory device context. Make your paint function copy the
update region
from your off screen buffer. Seems to me that this is the best way to do
almost any kind of
display window. The only reason this isn't more common is that memory used
to be
expensive.

- Ken

···

----- Original Message -----
From: "Patrick Gaffney" <patrickg@asti-usa.com>
To: "wxPython-users" <wxpython-users@lists.sourceforge.net>
Sent: Wednesday, October 18, 2000 6:04 AM
Subject: [wxPython] Persistent Display???

I'm looking for a window that will incrementally add text strings with
out keeping track of them all. (i.e. I want to use the display frame
buffer as my display memory.) In the program below, additional text
strings to be displayed come in whenever the mouse is clicked as
fgColor:wxBLUE, bgColor:wxWHITE, X:100, Y:200, text: "Clicked Here".

Unfortunately, I can't seem to stop the window erase on an EVT_PAINT
event, and therefore lose all the prior text strings that were
displayed. I trapped the EVT_ERASE_BACKGROUND event but could not
prevent the window erasing.

Also the SetTextBackground method of wxDC does not seem to do anything.

I have included a little test program to demonstrate my dilemma

COLORLIST = [wxBLUE, wxRED, wxBLACK, wxGREEN]
DEFAULT_FORECOLOR = COLORLIST[0]
DEFAULT_BACKCOLOR = COLORLIST[0]

class MBDisplay(wxWindow):
        def __init__(self, parent, id,
pos=wxDefaultPosition,size=wxDefaultSize):
                wxWindow.__init__(self, parent, id, pos, size)
                self.SetBackgroundColour(wxNamedColour('white'))
                self.font = wxFont(12, wxMODERN, wxNORMAL,
wxNORMAL,faceName='courier')
                EVT_PAINT(self, self.OnPaint)
                EVT_ERASE_BACKGROUND(self, self.eraseBackground)
                EVT_LEFT_DOWN(self, self.OnClick)

                self.random = whrandom.whrandom()

# INFO FOR MAKING THE TEXT DISPLAY, UPDATED WHEN MOUSE IS CLICKED
                self.drawInfo = (DEFAULT_BACKCOLOR, DEFAULT_FORECOLOR,
100, 100, "In the beginning")

        def Draw(self, dc = None):
                if not dc:
                        dc = wxClientDC(self)
                dc.SetFont(self.font)
                xPos = self.drawInfo[2]
                yPos = self.drawInfo[3]
                textSize = dc.GetTextExtent(self.drawInfo[4])
                dc.SetClippingRegion(xPos, yPos, textSize[0],
textSize[1])
                dc.Clear()
                dc.SetTextForeground(self.drawInfo[1])
                # THIS LINE DOES NOT SEEM TO DO ANYTHING
                dc.SetTextBackground(self.drawInfo[0])
                dc.DrawText(self.drawInfo[4], xPos, yPos)

        def OnPaint(self, event):
                # WHEN THIS GETS CALLED WINDOW GETS ERASED
                dc = wxPaintDC(self)
                self.Draw(dc)
                print 'OnPaint called'

        def eraseBackground(self, event):
                # GETS CALLED BUT DOES NOT SEEM TO STOP THE WINDOW
ERASE
                print 'eraseBackground called'
                return TRUE
# event.Skip()

        def OnClick(self, event):
                x = event.GetX()
                y = event.GetY()
                # pick random colors for text and background
                bgNum = self.random.randint(0, len(COLORLIST) - 1)
                fgNum = self.random.randint(0, len(COLORLIST) - 1)
                bgColor = COLORLIST[bgNum]
                fgColor = COLORLIST[fgNum]
                self.drawInfo = (bgColor, fgColor, x, y, "Clicked Here")
                self.Draw()

class MBDisplayFrame(wxFrame):
        def __init__(self, parent, id, title):
                self.id = id
                # First, call the base class' __init__ method to create
the frame
                wxFrame.__init__(self, parent, id, title, wxPoint(100,
100), wxSize(645, 485))
# EVT_ERASE_BACKGROUND(self, self.eraseBackground)
                # create window
                wid = NewId()
                self.mbd = MBDisplay(self,wid)

        def eraseBackground(self, event):
                print 'Frame eraseBackground called'
# event.Skip()
# return FALSE

        def OnCloseWindow(self,event):
                self.Destroy()

class MyApp(wxApp):
        def OnInit(self):
                mbDisplay = MBDisplayFrame(NULL, -1, 'Display window')
                mbDisplay.Show(true)
                self.SetTopWindow(mbDisplay)
                return true

if __name__ == "__main__":
        app = MyApp(0) # Create an instance of the application class
        app.MainLoop() # Tell it to start processing events

Patrick Gaffney
patrickg@asti-usa.com
_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/mailman/listinfo/wxpython-users

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/mailman/listinfo/wxpython-users

Haven't got time for more than a very cursory look at your code, but the
fact that these are the same when they clearly shouldn't be is suspect...

DEFAULT_FORECOLOR = COLORLIST[0]
DEFAULT_BACKCOLOR = COLORLIST[0]

There may be other problems in your code of course, but I imagine they might
be rather difficult to uncover without fixing this small problem...

Cheerio, Chris

···

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/mailman/listinfo/wxpython-users

Chris Fama wrote:

Haven't got time for more than a very cursory look at your code, but the
fact that these are the same when they clearly shouldn't be is suspect...

> DEFAULT_FORECOLOR = COLORLIST[0]
> DEFAULT_BACKCOLOR = COLORLIST[0]

Sorry for the long code sample.
The text I display is visible. The text background color is always white
regardless of call to SetTextBackground. This further highlights the
fact that SetTextBackground method seems to do nothing.

My long winded question had another issue that has to do with double
buffering windows. I would like not to have the window erased on every
EVT_PAINT event. Any ideas?

Patrick Gaffney

patrickg@asti-usa.com

···

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/mailman/listinfo/wxpython-users

The text I display is visible. The text background color is always white
regardless of call to SetTextBackground. This further highlights the
fact that SetTextBackground method seems to do nothing.

You need to call dc.SetBackgroundMode(wxSOLID)

My long winded question had another issue that has to do with double
buffering windows. I would like not to have the window erased on every
EVT_PAINT event. Any ideas?

You get a EVT_PAINT because the Window has been damaged and the system is
asking you to recreate it. In other words the window has already been
cleared by something else on the system and there's nothting you can do
about it, it must be redrawn by your program.

That said, there are a few ways to optimise it.

You could keep track of all your strings, positions and colours, and when
EVT_PAINT happens get the update region (the portion of you window that
actually needs redrawn) set a the clipping region to match, and cycle
through all your data redrawing those that intersect your region.

But you said you didn't want to keep all the strings around so lets look at
double-buffering. Basically you make a wxBitmap the same size as your
window and when you want to draw a string make a wxMemoryDC that selects
this bitmap and then draw to that dc. You probably also want to draw to the
window dc as well so you don't have to force a EVT_PAINT to update the
display. Then when EVT_PAINT happens you just make the memory dc again and
Blit() form that dc to the wxPaintDC. The downside is that this is more
work for your program, but not all that much. The other problem is that if
your window gets resized then you need to recreate the bitmap and redraw all
the strings, so you still need to keep track of them all, unless you
initiall make the bitmap be the size of the display...

HTH

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com
http://wxPython.org Java give you jitters?
http://wxPROs.com Relax with wxPython!

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/mailman/listinfo/wxpython-users