Little square issue (reprise)

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Little square issue (reprise)

Adrian Hill

The "little black square" issue mentioned in the thread
"Oddness with wx.Notebook"
https://groups.google.com/forum/#!topic/wxpython-users/NRAXzaPU5d8 ,
and the earlier thread linked from that one, seems to not be confined
to wx.Notebook-based applications.

The attached sample application produces a square of around 20x20 pixels in
the top left corner of a wx.Frame, or its child wx.Panel, without any
wx.Notebook instance.

The attached application simply toggles between displaying one of two
different blue-gray colored images (after the user presses a key). The square
is clearly visible in the top left corner while toggling is in progress.

When the user presses a key a second time, the toggling stops, and the final
image is displayed correctly.

The color of the "little square" seems to depend on the background color of the
frame or panel that is the parent of the wx.StaticBitmap.

For convenience, the application defines some variables at the top that control
various different tests I tried.
I also experimented with binding the EVT_ERASE_BACKGROUND event to an empty
function, but it did not noticably affect the displayed bitmaps.

I have obtained the same result on two different systems, using Python 3.5.2,
wx.Python 4.0.0b2 on a 64-bit Windows 7 PC. One system was a desktop, and the
other a laptop, which may imply that the suggestion that it is a graphics
driver issue is unlikely.

The CallAfter() suggestion from Tim is not applicable in this context where the
square is visible long after Frame1.__init__'s work is done.

The application is intended to be a MWE - in my real application, I'm capturing
images off a camera and displaying them in a bitmap.

Any ideas on how to get around the little squares will be gratefully
implemented :)

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

little_square.py (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Little square issue (reprise)

Robin Dunn
On Thursday, January 11, 2018 at 12:38:20 PM UTC-8, Adrian Hill wrote:

Any ideas on how to get around the little squares will be gratefully
implemented :)


Whenever you see the "little squares" on Windows it is usually due to the widgets being created by default in a visible state. Since Windows doesn't buffer the display like the other platforms do then you can see the widget momentarily in that state, where it has a size but no content yet, or whatever. For example when adding a new page to a notebook it's possible to see the new panel for a moment before it has a paint event handler, or child widgets, before it has had the size changed to match the notebook's client area, and before the notebook has been told to manage the new panel as a page.

In this case you are seeing the static bitmap widget at its default size of (20,20) and before the image has been assigned to it. By the time the next refresh comes along the widget will have sized itself to its default size that matches the image size and is ready to draw the image in the paint handler. In this case the simplest way to avoid seeing an incorrect initial state is to create the widget with an initial size that matches the image size.

            self._sbmp = wx.StaticBitmap(self._parent_wnd, wx.ID_ANY,
                                         wx.Bitmap(image1 if (i & 0x01) else image2),
                                         size=(640,480))


A more general approach would be to use the 2-phase create approach and hide the widget before it is created:

            self._sbmp = wx.StaticBitmap()
            self._sbmp.Hide()
            self._sbmp.Create(self._parent_wnd, wx.ID_ANY,
                              wx.Bitmap(image1 if (i & 0x01) else image2))
            self._sbmp.Show()


-- 
Robin Dunn
Software Craftsman
http://wxPython.org

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Little square issue (reprise)

Tim Roberts
In reply to this post by Adrian Hill
Adrian Hill wrote:

>
> The "little black square" issue mentioned in the thread
> "Oddness with wx.Notebook"
> https://groups.google.com/forum/#!topic/wxpython-users/NRAXzaPU5d8 ,
> and the earlier thread linked from that one, seems to not be confined
> to wx.Notebook-based applications.
>
> The attached sample application produces a square of around 20x20
> pixels in
> the top left corner of a wx.Frame, or its child wx.Panel, without any
> wx.Notebook instance.

But this is a very different situation.  Your square is briefly visible,
but goes away when things settle down.

I would also point out that your application is leaking windows.  Every
time you toggle, you create a new wx.StaticBitmap, which ends up making
a huge stack of StaticBitmap controls.  You can see that with a Windows
"spy" tool.  Remember that a window continues to live even after the
Python reference is gone.  It doesn't die until you delete the window
via wx.

If I modify your sample very slightly to replace this:
        # Currently-displayed static bitmap.
        self._sbmp = None
with this:
        # Currently-displayed static bitmap.
        self._sbmp = wx.StaticBitmap(self._parent_wnd, wx.ID_ANY)

and then just set a new bitmap into that single control, rather than
creating a new control:
        while self._keep_looping:
            # Show a bitmap of the current image.
            self._sbmp.SetBitmap(
                                         wx.Bitmap(image1 if (i & 0x01) else
                                                   image2))

the little square does not appear.  So, the square appears to be related
to redrawing a window that contains no controls.

--
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Little square issue (reprise)

Adrian Hill

Robin and Tim,

Thanks very much for the responses. I really appreciate it, and (of course)
both your suggestions solved the "little square" issue.

Tim, thanks too for pointing out the leaking windows.

One futher question, if I may, with reference to your statement
"It doesn't die until you delete the window via wx.":
In general, deleting the window via wx means (in this example) using self._sbmp.Destroy()?

Is this only necessary for wx.Window-derived objects?
Should the wx.Image instances also have a call to Destroy() added, or is that
not necessary?
I read https://wxpython.org/Phoenix/docs/html/window_deletion_overview.html, but
it does not mention Destroy() for non-Window items.
The https://wxpython.org/Phoenix/docs/html/wx.Image.html#wx.Image.Destroy does not
offer much as to when Destroy() ought to be called.

Thanks again,
Adrian

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Little square issue (reprise)

Tim Roberts
On Jan 13, 2018, at 7:55 AM, Adrian Hill <[hidden email]> wrote:
>
> Tim, thanks too for pointing out the leaking windows.
>
> One futher question, if I may, with reference to your statement
> "It doesn't die until you delete the window via wx.":
> In general, deleting the window via wx means (in this example) using self._sbmp.Destroy()?

Yes.  You pass a "parent" into the constructor of each wx.Window-derived object  The parent keeps a reference until Destroy happens.  This is a huge convenience; it means you don't have to keep a reference to every window you create.  You can just call
    wx.StaticText( self, -1, "Hello" )
without saving the object, and the text window will live on.


> Is this only necessary for wx.Window-derived objects?

Right.


> Should the wx.Image instances also have a call to Destroy() added, or is that
> not necessary?

Not necessary.  When you replace the image, the last reference to the previous one will be released, and it will be deleted.

Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Little square issue (reprise)

Adrian Hill
Tim,

Thanks for the clear explanation - much appreciated. (I'm finding WIT to be a very useful tool too.)

Adrian

On Saturday, January 13, 2018 at 10:16:34 PM UTC-7, Tim Roberts wrote:
On Jan 13, 2018, at 7:55 AM, Adrian Hill <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="M6w9_ZOMDAAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">hill.a...@...> wrote:
>
> Tim, thanks too for pointing out the leaking windows.
>
> One futher question, if I may, with reference to your statement
> "It doesn't die until you delete the window via wx.":
> In general, deleting the window via wx means (in this example) using self._sbmp.Destroy()?

Yes.  You pass a "parent" into the constructor of each wx.Window-derived object  The parent keeps a reference until Destroy happens.  This is a huge convenience; it means you don't have to keep a reference to every window you create.  You can just call
    wx.StaticText( self, -1, "Hello" )
without saving the object, and the text window will live on.


> Is this only necessary for wx.Window-derived objects?

Right.


> Should the wx.Image instances also have a call to Destroy() added, or is that
> not necessary?

Not necessary.  When you replace the image, the last reference to the previous one will be released, and it will be deleted.

Tim Roberts, <a href="javascript:" target="_blank" gdf-obfuscated-mailto="M6w9_ZOMDAAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">ti...@...
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.