Hi there,

I decided to use floatcanvas for my MSc project where I develop a custom handwriting recognition system.

One part of this system is to have an image viewer in the UI. I've already played a little bit with the nav and float canvas, but I'm stuck now for 2 days in a problem with the nav canvas and I have no idea why, so I'd appreciate it a lot if you could help me with my problem.

In general: I have a wx.panel in which I'd like to have the navcanvas. Unfortunately, the nav canvas ignores the size parameter so that the canvas is just a very small rectangle. However, when I just use a floatcanvas with a custom build navigation everything works fine, but the disadvantage here is that I'd like to use the UI elements like (zooming, moving, etc.) how it's established in the nav canvas.

I've attached my code to this mail.

I'm looking forward to hearing from you soon.

Best Regards,

Carl Bednorz
'''
Created on 9 Jul 2012

@author: cb1754
'''
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.3 on Sat Jul  7 17:53:03 2012

import wx
import os
import glob
from wx.lib.pubsub import Publisher
from wx.lib.floatcanvas import NavCanvas, FloatCanvas
# begin wxGlade: extracode
# end wxGlade



class mainFrame(wx.Frame):
    
    
    def __init__(self):
        wx.Frame.__init__(self, None, title = "Historical Handwriting Recognition System")
        
        
        #Create Document Panel object which handles the image documents
        self.docPanel = DocumentPanel(self)
        
        
        
        
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.docPanel, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        
        
        
        self.Show()
        self.sizer.Fit(self)
        self.Center()
    
    






#Hm Hard coded --> Has to be refactored!!! to be dynamic? Add window option in menu to set the databases.
BERKELEY_DB_SOURCE = '/home/cb1754/Pictures/DIA_TESTS/DIA_DB/BERKELEY_DB'
PARZIVAL_DB_SOURCE = '/home/cb1754/Pictures/DIA_TESTS/DIA_DB/PARZIVAL_DB'
ST_GALL_DB_SOURCE =  '/home/cb1754/Pictures/DIA_TESTS/DIA_DB/ST_GALL_DB'
        
BERKELEY_DB_NAME = 'Berkeley'
PARZIVAL_DB_NAME = 'Parzival'
ST_GALL_DB_NAME = 'St. Gall'
CREATE_DB = 'Add new database'

class DocumentPanel(wx.Panel):
    '''
    The Document Panel class creates a wx.Panel that provides an image viewer to access
    the historical document databases.
    '''
    
    def __init__(self,parent):
        '''
        Constructor
        '''
        
        #Init the wx.Panel
        self.panel = wx.Panel.__init__(self, parent, wx.ID_ANY)
        
        #Geth the width and height of the window
        width, height = wx.DisplaySize()
        
        print width, height
        
        
        
        #Set the photo maximum size
        self.photoMaxSize = height - 270
        
        #Initialise the default start image when application starts
        self.initDefaultStartImage()
        
       
        
        Publisher().subscribe(self.updateDocs, ("update images"))
        
        #Create the database combobox and the database static text descriptor 
        self.makeDatabaseSelecter()
        
        #Init picture counter
        self.currentPicture = 0
        self.totalPictures = 0
        self.layout()
        
    def initFloatCanvas(self):
        '''
        Init the float canvas to display the images.
        '''
        # Add the Canvas
        
        #self.showWidth = 800
        #self.showHeight = 600
        #self.InitFirstCanvasImg()
        
        print 'Photomax size'
        print self.photoMaxSize
        
        #Canvas = FloatCanvas.FloatCanvas(self, -1, BackgroundColor = "Grey", size=(self.photoMaxSize, self.photoMaxSize))
        
        #NOTE: The created navcanvas is not fit into the panel but just a small rectangle window!
        NC = NavCanvas.NavCanvas(self, size=(400,400), ProjectionFun = None , Debug=0, BackgroundColor = "Blue").Canvas
        
        self.Canvas = NC
        
       
       
        self.Canvas.MaxScale=20
        
        
        
        self.Canvas.ZoomToBB()
        
        
        
    def initDefaultStartImage(self):
        '''
        Initialises the default start image which is automatically displayed 
        when the application starts.
        '''
        self.docSourceFolder = ST_GALL_DB_SOURCE
        self.picPaths = glob.glob(self.docSourceFolder + "/*.png")
        print 'Init doc source folder: ' + str(self.docSourceFolder)
        print 'Init picPaths: ' + str(self.picPaths) 
        
    def layout(self):
        '''
        Make the layout of the document viewer.
        @todo: Refactor the database combobox into the interaction panel
        '''
        #Create the main sizer
        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        
        #Make image label from file name
        self.imageLabel = wx.StaticText(self, label="")
        
        #create the sizer for the document navigation
        navSizer = wx.BoxSizer(wx.HORIZONTAL)
        
        
        #Init the float canvas
        self.initFloatCanvas()
       
        
       
        
        
        #Init the doc source folder with the first image in the picPaths which is initalised with initDefaultStartImage()
        #In this case it's the first image of the St.Gall database.
        self.loadImageDocs(self.picPaths[0])
        
        #Define the buttons
        navBtnData = [("Previous Image", navSizer, self.onPrevious),
                      ("Next Image", navSizer, self.onNext),
                      ("Zoom In", navSizer, self.onZoomIn),
                      ("Zoom Out", navSizer, self.onZoomOut),
                      ("Zoom to Fit", navSizer, self.onFitImage),
                      ("Move", navSizer, self.on1to1Resolution),]
        
        
        #Add the image label to the ui
        #navSizer.Add(self.imageLabel, 0, wx.ALL | wx.CENTER, 5)
        
        #Add Static text for the image database combo box
        navSizer.Add(self.dbComboBoxText, 0, wx.CENTER)
        
        #Add the database comboxox to the navigation -> Has to be refactored later!!!
        navSizer.Add(self.dbComboBox, 0, wx.CENTER)
        
        #Bind the event to the combobox for selecting the database
        self.dbComboBox.Bind(wx.EVT_COMBOBOX, self.onDatabaseSelect)
        
        #Add the buttons
        for data in navBtnData:
            label, sizer, handler = data
            self.navBuilder(label, sizer, handler)
            
        #Add the navigation to the main sizer
        self.mainSizer.Add(navSizer, 0, wx.ALL | wx.LEFT, 5)
        
        
        #Add the image control the the main sizer
        self.mainSizer.Add(self.Canvas, 0, wx.ALL | wx.LEFT , 5)
       
        
        #self.mainSizer.Add(self.imageCtrl, 0, wx.ALL | wx.LEFT, 5)
        self.SetSizer(self.mainSizer)
        
        
    def makeDatabaseSelecter(self):
        '''
        Method for creating the combo box to select the image database.
        A list contains the default databases St.Gall, Parzival and Berkeley which
        are displayed in a wx.ComboBox and St.Gall is set as default database.
        Furthermore a static text describes the combobox.
        '''
        #Make list with the default image document databases
        self.databases = ['St. Gall', 'Parzival', 'Berkeley', 'Add new database']
        
        #Create the combo box
        self.dbComboBox = wx.ComboBox(self,wx.ID_ANY ,choices = self.databases, style = wx.CB_DROPDOWN | wx.CB_READONLY)
        
        #Set the default selection to St.Gall
        self.dbComboBox.SetSelection(0)
        
        #Set the combo box text
        self.dbComboBoxText = wx.StaticText(self, label='Select Document Database:')
        
        
    def onDatabaseSelect(self, event):
        '''
        Loads the document images based on the selection made by the user in the
        database combobox.
        '''
        
        self.docSourceFolder = ST_GALL_DB_SOURCE
        
        #Get the selection from combobox
        cbSelection = event.GetString()
        print 'db is ' + cbSelection
        
        #Set the docSourceFolder to the selected option made in the combobox
        if cbSelection == BERKELEY_DB_NAME:
            print 'Selected ' + cbSelection
            self.docSourceFolder = BERKELEY_DB_SOURCE
            #Get the png pics from the source folder
            self.picPaths = glob.glob(self.docSourceFolder + "/*.png")
        elif cbSelection == PARZIVAL_DB_NAME:
            print 'Selected ' + cbSelection
            self.docSourceFolder = PARZIVAL_DB_SOURCE
            #Get the png pics from the source folder
            self.picPaths = glob.glob(self.docSourceFolder + "/*.png")
        elif cbSelection == ST_GALL_DB_NAME:
            print 'Selected ' + cbSelection
            self.docSourceFolder = ST_GALL_DB_SOURCE
            #Get the png pics from the source folder
            self.picPaths = glob.glob(self.docSourceFolder + "/*.png")
        elif cbSelection == CREATE_DB:
            print 'Selecetd ' + cbSelection
        
        
        print self.docSourceFolder
        print self.picPaths
        
        Publisher().sendMessage("update images", self.picPaths)
        
        
    def addDatabase(self, database):
        '''
        To add a database.
        @todo: REfactor so that on selected option in Combobox create a new database!
        '''
        self.databases.append(database)
        
    def InitFirstCanvasImg(self, imageDoc):
            '''
            TO BE DELETED
            '''
            self.startImg = wx.Image(imageDoc, wx.BITMAP_TYPE_ANY)
            #Scale the image and preserve the aspect ratio
            WIDTH = self.imgDoc.GetWidth()
            HEIGHT = self.imgDoc.GetHeight()
        
            if WIDTH > HEIGHT:
                self.showWidth = self.photoMaxSize
                self.showHeight = self.photoMaxSize * HEIGHT / WIDTH
            else:
                self.showWidth = self.photoMaxSize * WIDTH / HEIGHT
                self.showHeight = self.photoMaxSize
    
        
    def loadImageDocs(self, imageDoc):
        '''
        Method which loads the image documents.
        
        '''
        #Get the image document name
        imageDocName = os.path.basename(imageDoc)
        
        print 'Image doc name is: ' + imageDocName
        
        #Convert to wx.Image object
        self.imgDoc = wx.Image(imageDoc, wx.BITMAP_TYPE_ANY)
        
        print self.imgDoc.GetHeight()
        
        #Scale the image and preserve the aspect ratio
        WIDTH = self.imgDoc.GetWidth()
        HEIGHT = self.imgDoc.GetHeight()
        
        if WIDTH > HEIGHT:
            self.showWidth = self.photoMaxSize
            self.showHeight = self.photoMaxSize * HEIGHT / WIDTH
        else:
            self.showWidth = self.photoMaxSize * WIDTH / HEIGHT
            self.showHeight = self.photoMaxSize
            
        
        
        #Add the new bitmap to the Canvas
        self.imgDoc = self.Canvas.AddScaledBitmap(self.imgDoc, (0,0), Height=self.imgDoc.GetHeight(),Position = 'tl')
        self.Canvas.ZoomToBB() 
        
        
        #Set the image label 
        self.imageLabel.SetLabel(imageDocName)
        self.Refresh()
        Publisher().sendMessage("resize", "")
            
    def navBuilder(self, label, sizer, handler):
        '''
        Creates button, bind button to event handler and add to the sizer.
        '''
        btn = wx.Button(self, label = label)
        btn.Bind(wx.EVT_BUTTON, handler)
        sizer.Add(btn, 0, wx.ALL | wx.CENTER, 5)
           
    def nextDoc(self):
        '''
        Load next image document from directory
        '''
        #self.Canvas.RemoveObject(self.imgDoc)
        
        self.Canvas.ClearAll()
        
        if self.currentPicture == self.totalPictures - 1:
            self.currentPicture = 0
            
        else:
            self.currentPicture += 1
        
        self.loadImageDocs(self.picPaths[self.currentPicture])
        
    def prevDoc(self):
        '''
        Load previous image from directory
        '''
        self.Canvas.ClearAll()
        
        if self.currentPicture == 0:
            self.currentPicture = self.totalPictures - 1
        else:
            self.currentPicture -= 1
        self.loadImageDocs(self.picPaths[self.currentPicture])
           
    
    def updateDocs(self, msg):
        
        #Clears the Canvas
        self.Canvas.ClearAll()
        self.picPaths = msg.data
        self.totalPictures = len(self.picPaths)
        self.loadImageDocs(self.picPaths[0])
    
    
    def onPrevious(self, event):
        '''
        Calls the prev Doc method to display the previous image in the doc viewer.
        '''
        self.prevDoc()
    
    def onNext(self, event):
        '''
        Calls the next Doc method to display the next image in the doc viewer.
        '''
        self.nextDoc()
    
    def onZoomIn(self, event):
        print 'ZoomIn'
        
        self.Canvas.Zoom(factor = 1.25, center=None, centerCoords='world')
        
        
    
    def onZoomOut(self, event):
        self.Canvas.Zoom(factor = 0.85, center=None, centerCoords='world')
        
    
    def on1to1Resolution(self, event):
        from wx.lib.floatcanvas import GUIMode
        
        print 'Move'
        
        self.GUIMove = GUIMode.GUIMove(self.Canvas)
        self.GUIMouse   =  GUIMode.GUIMouse(self.Canvas)
        # default to Mouse mode
        #self.ToolBar.ToggleTool(self.PointerTool.GetId(), True)
        self.Canvas.SetMode(self.GUIMouse)
        self.GUIMove.OnMove(event)
    
    def onFitImage(self, event):
        print 'Fit image'
        self.Canvas.ZoomToBB()
        self.Canvas.SetFocus()
    
    


class HWRPanel(wx.Panel):
    pass

class interactionPanel(wx.Panel):
    pass

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    DIA2000 = mainFrame()
    app.SetTopWindow(DIA2000)
    DIA2000.Show()
    app.MainLoop()
_______________________________________________
FloatCanvas mailing list
[email protected]
http://paulmcnett.com/cgi-bin/mailman/listinfo/floatcanvas

Reply via email to