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