scrolledpanel with dc?

I write a image display software.
Window use full screen, display image can Increase and Reduce with ScrolledPanel.

I use test_scroll_image.py to learn how to use ScrolledPanel.
But when I use panel and dc to draw image. My code test_scroll_panel_dc.py cann’t support ScrolledPanel.

Please help me.
Thanks

Bluehills.jpg

test_scroll_image.py (1.46 KB)

test_scroll_panel_dc.py (8.77 KB)

···


jiang zhixiang

Rill wrote:

I write a image display software.
Window use full screen, display image can Increase and Reduce with
ScrolledPanel.

I use test_scroll_image.py to learn how to use ScrolledPanel.
But when I use panel and dc to draw image. My code
test_scroll_panel_dc.py cann't support ScrolledPanel.

I'm sorry, I don't quite understand what you're asking.

A ScrolledPanel manages the windows that are placed on it. If you draw
directly onto the panel using a DC, the ScrolledPanel has no way to know
about that drawing, so when it scrolls, your drawing will be lost.

Can you tell us a bit more about how you're using the panel?

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Hi,

I write a image display software.
Window use full screen, display image can Increase and Reduce with ScrolledPanel.

I use test_scroll_image.py to learn how to use ScrolledPanel.
But when I use panel and dc to draw image. My code test_scroll_panel_dc.py cann’t support ScrolledPanel.

Please help me.
Thanks

There are several problems in your scripts that are contributing to it not working, here are some things to look into.

  1. Many of the hierarchies of Parent to Child controls and what sizers they are in are wrong and is screwing up the layout management. A windows direct children should be the only items added to its sizer (i.e. see self.panel and self.view in the Frame class).

  2. Related to the above, you have scrolled panels inside of scrolled panels. Would simplify it down to just having your view directly derived from ScrolledPanel and draw to that to get started.

  3. ScrolledPanel is not actually a panel, it derives from Window so you cant really use sizers to manage its size unfortunately Need to manually manage its size as the frame is resized.

  4. As you change the scaling you will need to update the Virtual size of the canvas, as the image becomes bigger the virtual space becomes bigger, and visa versa for zoom out. Currently you are always setting the same constant virtual size.

  5. Look at the function signatures for SetupScrolling method.

Cody

···

On Tue, Mar 26, 2013 at 3:56 AM, Rill luckrill@gmail.com wrote:

O,base code I use panel, it’s view photo is right.
Then I want to add scrolledpanel to Increase/Reduce image and the hope the image can scrolled.
I try to add ScrolledPanel, but the work are wrong.
Who can modify my code test_scroll_panel_dc.py to support image scrolled?

O,base code I use panel, it’s view photo is right.

Then I want to add scrolledpanel to Increase/Reduce image and the hope the image can scrolled.
I try to add ScrolledPanel, but the work are wrong.

You want a ScrolledWindow, not a scrolledPanel. Look in the demo for examples. I think the drawing example uses one.

Chris

···

On Mar 26, 2013, at 8:05 PM, luckrill luckrill@gmail.com wrote:

Who can modify my code test_scroll_panel_dc.py to support image scrolled?

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 wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.

Display image with scrollpanel and DC, This problem is too difficult for me.
I search and read many scroll code, did not find the answers I need.
Now, I need step by step to debug and learn scroll panel.
When I succeed, I will post here my code.
Thanks

luckrill wrote:

Display image with scrollpanel and DC, This problem is too difficult
for me.
I search and read many scroll code, did not find the answers I need.
Now, I need step by step to debug and learn scroll panel.

I'm not sure how a DC gets involved in this at all. Here is the very
primitive image viewer tool I write, using a ScrolledWindow. It's not a
pinnacle of shining coding style, but it works. You will need to change
the definition of "BASE" to tell it what default directory to start in.
You can right-click on a file to do a few simple operations (delete,
rename, move, launch in external app).

import os
import wx

BASE = "c:/tmp"

mappings = {
  '.bmp': wx.BITMAP_TYPE_BMP,
  '.jpg': wx.BITMAP_TYPE_JPEG,
  '.jpeg': wx.BITMAP_TYPE_JPEG,
  '.png': wx.BITMAP_TYPE_PNG,
  '.gif': wx.BITMAP_TYPE_GIF
}

class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__( self, None, -1, 'Image Viewer', size=(1024,768) )

        # Create the controls.

        split = wx.SplitterWindow( self, -1, style=wx.SP_LIVE_UPDATE )
        pnl = wx.ScrolledWindow( split, -1, style=wx.SUNKEN_BORDER )
        pnl.SetScrollbars( 50, 50, 20, 20 )
        self.img = wx.StaticBitmap( pnl, -1 )
        self.imgpanel = pnl

        left = wx.Panel( split, -1, style=wx.SUNKEN_BORDER );
        dirBox = wx.GenericDirCtrl( left, -1,
                style=wx.SUNKEN_BORDER | wx.DIRCTRL_DIR_ONLY )
        self.fileBox = wx.ListBox( left, -1 )
        split.SetMinimumPaneSize( 20 )
        split.SplitVertically ( left, pnl, 200 )

        # Do the layout.

        sizer = wx.BoxSizer( wx.VERTICAL )
        sizer.Add( dirBox, 1, wx.EXPAND, 0 )
        sizer.Add( (10, 10), 0, wx.EXPAND )
        sizer.Add( self.fileBox, 3, wx.EXPAND, 0 )
        left.SetAutoLayout(1)
        left.SetSizer( sizer )
        self.Layout()

        # Create the popup menu.

        popup = wx.Menu()
        id = wx.NewId()
        popup.Append( id, "&Delete" )
        self.Bind( wx.EVT_MENU, self.OnMenuDelete, id=id )
        id = wx.NewId()
        popup.Append( id, "&Rename..." )
        self.Bind( wx.EVT_MENU, self.OnMenuRename, id=id )
        id = wx.NewId()
        popup.Append( id, "&Move to folder..." )
        self.Bind( wx.EVT_MENU, self.OnMenuMove, id=id )
        id = wx.NewId()
        popup.Append( id, "&Launch" )
        self.Bind( wx.EVT_MENU, self.OnMenuLaunch, id=id )
        self.popup = popup

        # Handle events.

        self.Bind( wx.EVT_TREE_SEL_CHANGED, self.OnDir,
dirBox.GetTreeCtrl() )
        self.Bind( wx.EVT_LISTBOX, self.OnFile, self.fileBox )
        self.fileBox.Bind( wx.EVT_RIGHT_UP, self.OnRightClick )
        self.fileBox.Bind( wx.EVT_KEY_UP, self.OnKeyUp )
        dirBox.Bind( wx.EVT_KEY_UP, self.OnKeyUp )

        # Set the initial state.

        self.path = BASE
        dirBox.SetPath( self.path )
        self.FillFileBox()

    def FillFileBox( self ):
        knownfmts = mappings.keys()
        files = [k for k in os.listdir( self.path )
                   if os.path.splitext(k)[1].lower() in knownfmts]
        self.fileBox.Clear()
        self.fileBox.InsertItems( files, 0 )

    def OnDir( self, evt ):
        db = evt.GetEventObject().GetParent()
        self.path = db.GetPath()
        self.FillFileBox()
        evt.Skip()

    def getFile( self ):
        return os.path.join( self.path, self.fileBox.GetStringSelection() )

    def RefillBox( self ):
        ordinal = self.fileBox.GetSelection()
        self.FillFileBox()
        self.fileBox.SetSelection( ordinal )

    def OnFile( self, evt ):
        sel = self.getFile()
        ext = os.path.splitext( sel )[1].lower()
        if not mappings.has_key( ext ):
            return

        bmp = wx.Image( sel, mappings[ext] ).ConvertToBitmap()
        sz = (bmp.GetWidth(), bmp.GetHeight())
        self.img.SetSize( sz )
        self.img.SetBitmap( bmp )
        self.imgpanel.SetVirtualSize( sz )

    def OnRightClick( self, evt ):
        lb = evt.GetEventObject()
        lb.PopupMenu( self.popup, evt.GetPosition() )

    def OnMenuDelete( self, evt ):
        sel = self.getFile()
        os.remove( sel )
        self.RefillBox()
        self.OnFile( None )

    def OnMenuRename( self, evt ):
        old = self.fileBox.GetStringSelection()
        dlg = wx.TextEntryDialog( self, 'Enter new name:', 'Rename', old )
        dlg.SetValue( old )
        if dlg.ShowModal() == wx.ID_OK:
            os.rename(
                self.getFile(),
                os.path.join( self.path, dlg.GetValue() )
            )
            self.RefillBox()
            self.OnFile( None )
        dlg.Destroy()

    def OnMenuMove( self, evt ):
        dlg = wx.DirDialog(self, "Choose new directory:",
                style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON )
        dlg.SetPath( self.path )
        if dlg.ShowModal() == wx.ID_OK:
            old = self.getFile()
            base = os.path.split( old )[1]
            new = os.path.join( dlg.GetPath(), base )
            if old <> new:
                os.rename( old, new )
                self.RefillBox()
                self.OnFile( None )
        dlg.Destroy()

    def OnMenuLaunch( self, evt ):
        os.system( self.getFile() )

    def OnKeyUp( self, evt ):
        keycode = evt.GetKeyCode()
        if keycode == wx.WXK_ESCAPE:
            self.Destroy()

app = wx.App(0)
fr = MyFrame( app )
fr.Show()
app.MainLoop()

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

This is my image processing software code, all code in one file.

My first wxwidget project, have some fun features.

Now, I want to add image scrolled function.

myimages.py (104 KB)

I debug static image display with scrollpanel is succeed. Image can zoom in and zoom out.
Must remove sizer and add sizer again.

import wx
import wx.lib.scrolledpanel as scrolled

image_filename = “Bluehills.jpg”

class TestPanel(scrolled.ScrolledPanel):
def init(self, parent, lsize):
scrolled.ScrolledPanel.init(self, parent, -1, size=(200,200), style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
self.btn_out = wx.Button(self, label=“Out”)
self.btn_in = wx.Button(self, label=“In”)
self.Bind(wx.EVT_BUTTON, self.on_out, self.btn_out)
self.Bind(wx.EVT_BUTTON, self.on_in, self.btn_in)
self.scale = 0.5
self.scrollPnlSizer = wx.BoxSizer(wx.VERTICAL)

    img = wx.Image(image_filename, wx.BITMAP_TYPE_ANY)
    iwidth = img.GetWidth()  
    iheight = img.GetHeight()

    owidth = int(self.scale*iwidth)
    oheight = int(self.scale*iheight)
    sc_img = img.Scale(owidth,oheight)

    self.staticBitmap = wx.StaticBitmap(self, wx.ID_ANY, wx.BitmapFromImage(sc_img))
   
    self.scrollPnlSizer.Add(self.btn_out)
    self.scrollPnlSizer.Add(self.btn_in)
    self.scrollPnlSizer.Add(self.staticBitmap, 1, wx.EXPAND | wx.ALL, 3)
    self.SetSizer(self.scrollPnlSizer)
    self.Centre()

def on_out(self, event):
    img = wx.Image(image_filename, wx.BITMAP_TYPE_ANY)
    iwidth = img.GetWidth()  
    iheight = img.GetHeight()
    self.scale += 0.1
    owidth = int(self.scale*iwidth)
    oheight = int(self.scale*iheight)
    sc_img = img.Scale(owidth,oheight)

    self.scrollPnlSizer.Remove(self.staticBitmap)
    self.staticBitmap = wx.StaticBitmap(self, wx.ID_ANY, wx.BitmapFromImage(sc_img))
    self.scrollPnlSizer.Add(self.staticBitmap, 1, wx.EXPAND | wx.ALL, 3)
    self.SetSizer(self.scrollPnlSizer)
    self.SetAutoLayout(1)
    self.SetupScrolling() 

    self.Refresh()
    self.Layout()

def on_in(self, event):
    img = wx.Image(image_filename, wx.BITMAP_TYPE_ANY)
    iwidth = img.GetWidth()   # dimensions of image file
    iheight = img.GetHeight()
    self.scale -= 0.1
    owidth = int(self.scale*iwidth)
    oheight = int(self.scale*iheight)
    sc_img = img.Scale(owidth,oheight)

    self.scrollPnlSizer.Remove(self.staticBitmap)
    self.staticBitmap = wx.StaticBitmap(self, wx.ID_ANY, wx.BitmapFromImage(sc_img))
    self.scrollPnlSizer.Add(self.staticBitmap, 1, wx.EXPAND | wx.ALL, 3)
    self.SetSizer(self.scrollPnlSizer)

    self.SetAutoLayout(1)
    self.SetupScrolling() 

    self.Refresh()
    self.Layout()

class TestFrame(wx.Frame):
def init(self, parent):
wx.Frame.init(self, parent, size=(500, 400))

self.Maximize(True)

    size = self.GetSize()
    TestPanel(self, size)

if name == “main”:
app = wx.PySimpleApp()
frame = TestFrame(None)
frame.Show()
app.MainLoop()

congrats on getting your first wx program working!

But you could really clean it up a lot -- some ideas:

1) You probably don't want a ScrolledPanel here, but rather, a Panel
on which you have two things: your buttons, and another Window for teh
image -- for that, you might want a ScrolledWindow. That way, the user
can scroll the image itself, without pushing the buttons off the
screen.

2) You don't want to re-load the image every time you change zoom.
rather, keep it around as a class attribute, so you ony need to load
it once.

3) You probably don't want to use a StaticBitmap -- that's for, well,
static bitmaps, -- i.e. ones that dont change. Rather, you should draw
your bitmap on the ScrolledWindow with a wx.DC.DrawBitmap

4) once you've got it working, you may want to get smarted about the
scaling -- if you have a big image, and the user wants to zoom in a
lot, you'll be creating a really big in-memory bitmap -- that could be
a problem.

Now that I think about it, wx.lib.floatcanvas, with a ScaledBitmap2,
does a lot of this for you... Even if you don't want to use it, you
may want to borrow the ScaledBitmap2 code.

Here's an example of that using floatcanvas:

#!/usr/bin/env python

"""
This demo shows how to use a ScaledBitmap2 (which is like a scaled bitmap,
but uses memory more efficiently for large images and high zoom levels.)

"""

## Set a path to an Image file here:
ImageFile = "white_tank.jpg"

import wx
import random
## import the installed version
from wx.lib.floatcanvas import NavCanvas, FloatCanvas

## import a local version
#import sys
#sys.path.append("../")
#from floatcanvas import NavCanvas, FloatCanvas

class DrawFrame(wx.Frame):

    """
    A frame used for the FloatCanvas Demo

    """

    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.CreateStatusBar()

        # Add the Canvas
        Canvas = NavCanvas.NavCanvas(self,
                                     ProjectionFun = None,
                                     BackgroundColor = "DARK SLATE BLUE",
                                     ).Canvas
        Canvas.MaxScale=20 # sets the maximum zoom level
        self.Canvas = Canvas

        FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )

        # create the image:
        image = wx.Image(ImageFile)
        self.width, self.height = image.GetSize()
        img = FloatCanvas.ScaledBitmap2( image,
                                        (0,0),
                                        Height=image.GetHeight(),
                                        Position = 'tl',
                                        )
        Canvas.AddObject(img)

        self.Show()
        Canvas.ZoomToBB()

    def OnMove(self, event):
        """
        Updates the status bar with the world coordinates

        """
        self.SetStatusText("%i, %i"%tuple(event.Coords))

app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()

···

--

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

very good, thank you very much.
I will use scrollwindow.
And I will opensource my image project.