Example of a non-scaling scrolling image view?

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

Example of a non-scaling scrolling image view?

Mark Summerfield
I want a widget that shows PNG images.

The widget will vary in size depending on the user sizing the window it is in but I don't want the image it shows to be scaled. Iinstead I want the image to be shown at its actual size occupying the top-left if it is smaller than the widget or with scrollbars appearing if it is larger than the widget. The images the widget will be given will vary in size, so it needs to adapt whenever it is given a new image.

Does anyone have or can direct me to an example widget that has this kind of behaviour?

--
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].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/ddaa81a3-1d9d-410c-8248-79604666601e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Example of a non-scaling scrolling image view?

Robin Dunn
On Wednesday, June 19, 2019 at 12:55:42 AM UTC-7, Mark wrote:
I want a widget that shows PNG images.

The widget will vary in size depending on the user sizing the window it is in but I don't want the image it shows to be scaled. Iinstead I want the image to be shown at its actual size occupying the top-left if it is smaller than the widget or with scrollbars appearing if it is larger than the widget. The images the widget will be given will vary in size, so it needs to adapt whenever it is given a new image.

Does anyone have or can direct me to an example widget that has this kind of behaviour?

There are likely samples of this all over, but it's fairly straight forward.  I would approach it like this:
  1. Derive a new class from wx.Window
  2. In the __init__ set a bitmap attribute to wx.NullBitmap, and bind the EVT_PAINT event to a handler method, and set the background style to wx.BG_STYLE_PAINT.
  3. Give it a method to set the bitmap attribute, and have it call self.Refresh after the attribute is set.
  4. In the EVT_PAINT handler do these steps:
    1. Create a wx.AutoBufferedPaintDC
    2. Set the dc's background brush (dc.SetBackground) to whatever you want the window to look like when there is no bitmap, or in the areas that the image does not cover.
    3. Call dc.Clear()
    4. if the bitmap attribute's IsOk() method returns True, call dc.DrawBitmap to draw it.
--
Robin

--
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].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/4ec957b4-9d2e-451f-a3b9-61edee6d8a01%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Example of a non-scaling scrolling image view?

Mark Summerfield
Thanks for that. I got it to work fine without scrollbars (once I'd set the BackgroundStyle), but my attempts to get scrollbars working have failed.
If you run the attached and resize the window to be smaller than the image on Gtk the scrollbars appear and don't work. On Windows the scrollbars appear and do work, but the drawing gets all messed up. This is frustrating since I feel as though I'm really close!

On Thursday, 20 June 2019 02:43:27 UTC+1, Robin Dunn wrote:
On Wednesday, June 19, 2019 at 12:55:42 AM UTC-7, Mark wrote:
I want a widget that shows PNG images.

The widget will vary in size depending on the user sizing the window it is in but I don't want the image it shows to be scaled. Iinstead I want the image to be shown at its actual size occupying the top-left if it is smaller than the widget or with scrollbars appearing if it is larger than the widget. The images the widget will be given will vary in size, so it needs to adapt whenever it is given a new image.

Does anyone have or can direct me to an example widget that has this kind of behaviour?

There are likely samples of this all over, but it's fairly straight forward.  I would approach it like this:
  1. Derive a new class from wx.Window
  2. In the __init__ set a bitmap attribute to wx.NullBitmap, and bind the EVT_PAINT event to a handler method, and set the background style to wx.BG_STYLE_PAINT.
  3. Give it a method to set the bitmap attribute, and have it call self.Refresh after the attribute is set.
  4. In the EVT_PAINT handler do these steps:
    1. Create a wx.AutoBufferedPaintDC
    2. Set the dc's background brush (dc.SetBackground) to whatever you want the window to look like when there is no bitmap, or in the areas that the image does not cover.
    3. Call dc.Clear()
    4. if the bitmap attribute's IsOk() method returns True, call dc.DrawBitmap to draw it.
--
Robin

--
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].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/f1313f67-9b1b-4a57-a9f5-5273d6e11a04%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

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

Re: Example of a non-scaling scrolling image view?

Robin Dunn
On Thursday, June 20, 2019 at 2:14:06 AM UTC-7, Mark wrote:
Thanks for that. I got it to work fine without scrollbars (once I'd set the BackgroundStyle), but my attempts to get scrollbars working have failed.
If you run the attached and resize the window to be smaller than the image on Gtk the scrollbars appear and don't work. On Windows the scrollbars appear and do work, but the drawing gets all messed up. This is frustrating since I feel as though I'm really close!


Oops, I somehow missed the "Scrolling" in the first message. There are a few ways to set things up to scroll, some more flexible but complex, some more simple. Your attempt is the former.

The main thing you are missing is adjusting the window to the scrolled offset when painting. You can do that with a call to self.PrepareDC(dc) in your on_paint method. To simplify even further, your entire update_scrollbars can be eliminated if you just set the virtual size to be the bitmap's size whenever the bitmap changes, and scrolling can be enabled by calling SetScrollRate. The ScrolledCanvas will take care of everything else.  See attached.

--
Robin


 

On Thursday, 20 June 2019 02:43:27 UTC+1, Robin Dunn wrote:
On Wednesday, June 19, 2019 at 12:55:42 AM UTC-7, Mark wrote:
I want a widget that shows PNG images.

The widget will vary in size depending on the user sizing the window it is in but I don't want the image it shows to be scaled. Iinstead I want the image to be shown at its actual size occupying the top-left if it is smaller than the widget or with scrollbars appearing if it is larger than the widget. The images the widget will be given will vary in size, so it needs to adapt whenever it is given a new image.

Does anyone have or can direct me to an example widget that has this kind of behaviour?

There are likely samples of this all over, but it's fairly straight forward.  I would approach it like this:
  1. Derive a new class from wx.Window
  2. In the __init__ set a bitmap attribute to wx.NullBitmap, and bind the EVT_PAINT event to a handler method, and set the background style to wx.BG_STYLE_PAINT.
  3. Give it a method to set the bitmap attribute, and have it call self.Refresh after the attribute is set.
  4. In the EVT_PAINT handler do these steps:
    1. Create a wx.AutoBufferedPaintDC
    2. Set the dc's background brush (dc.SetBackground) to whatever you want the window to look like when there is no bitmap, or in the areas that the image does not cover.
    3. Call dc.Clear()
    4. if the bitmap attribute's IsOk() method returns True, call dc.DrawBitmap to draw it.
--
Robin

--
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].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/037882b3-d09c-4777-afd0-b81aaf8778c8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

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

Re: Example of a non-scaling scrolling image view?

Mark Summerfield
Thanks Robin, that works perfectly on both Gtk and Windows!

Out of curiosity, is it OK to replace `if bitmap.IsOk():` with `if bitmap:`?

Also, is there any reason you wrote `self.SetVirtualSize(bitmap.Size)` rather than `self.VirtualSize = bitmap.Size`?
I'm tending to use property getters/setters wherever they are available but don't really know what the recommended style is.

--
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].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/4dedbe9e-1fcd-474f-9298-80f40d9b95b8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Example of a non-scaling scrolling image view?

Tim Roberts
Mark wrote:
>
> Out of curiosity, is it OK to replace `if bitmap.IsOk():` with `if
> bitmap:`?

No.  "if self.bitmap:" is always going to succeed.  The "if" statement
in Python only checks for a few values of truthiness: the value None,
the value False, or an empty sequence (string, list, tuple, set,
dictionary) will evaluate false.  Everything else, including a bitmap
object bound to wxNullBitmap, will evaluate to true.

--
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].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/bb682cdc-3817-c01a-3d44-c0442eae96fb%40probo.com.
For more options, visit https://groups.google.com/d/optout.

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Example of a non-scaling scrolling image view?

Robin Dunn
On Thursday, June 20, 2019 at 12:59:14 PM UTC-7, Tim Roberts wrote:
Mark wrote:
>
> Out of curiosity, is it OK to replace `if bitmap.IsOk():` with `if
> bitmap:`?

No.  "if self.bitmap:" is always going to succeed.  The "if" statement
in Python only checks for a few values of truthiness: the value None,
the value False, or an empty sequence (string, list, tuple, set,
dictionary) will evaluate false.  Everything else, including a bitmap
object bound to wxNullBitmap, will evaluate to true.

Actually, wxPython adds __bool__ and __nonzero__ methods to the wx.Bitmap class that return the value of IsOk(), so yes, it will work.

>>> wx.NullBitmap.IsOk()
False
>>> print('ok' if wx.NullBitmap else 'not ok')
not ok
>>> bool(wx.NullBitmap)
False
>>> 
>>> 
>>> bmp = wx.Bitmap(10,10)
>>> bmp.IsOk()
True
>>> print('ok' if bmp else 'not ok')
ok
>>> bool(bmp)
True

--
Robin



--
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].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/125a33f2-5dad-4611-b446-cf65c8c85d01%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.