Hello, I'm writing an application that displays an image . The main
frame, by now, just has a menubar and a wxWindow subclass that displays
the opened image. The main frame is not resizable. Anyway I want it to
grow or shrink when I open a new image.
I use a wxBoxSizer to put things in the main frame (I'll add some
controls). The only method I found to make the frame resize according to
the need of the internal image window is to remove the image window from
the sizer and then add it again. Is there a better way of doing that?
Anyway I'm using wxPythonWIN32-2.3.3.1-Py22.
A strange thing I noticed is that when I use wxSizer.Remove(wxWindow) or
wxSizer.Remove(int) the result, even if the windows is removed, is
always None. On the wxWindows documentation I read that the return value
should be a boolean. Well "None" is like a "false"... is it a bug or
just my misunderstanding?
Another thing is that is I resize(from inside the application) once the
window, everything works ok. If I resize it again and the size is
smaller than the old one, the size remains big.... Any hint?
Anyway this is the (relevant) source code. If somebody can give me advice on how to
make things better or faster or more wxPython-style, well, you are
welcome The method that tries to resize the frame is MainFrame.SetImageSource.
from pyVideo.ImageSource import *
from pyVideo.CRImage import *
from wxPython.wx import *
import os
import time
#This is the wxWindow that shows the CRImage
class CRImageWindow(wxWindow):
DEFAULTSIZE=(384,288)
def __init__(self,parent,id,point,image=None):
#You can pass an image or None,
#in that case an empty image is created
if image:
self.sz=image.size
else:
self.sz=self.DEFAULTSIZE
wxWindow.__init__(self,parent,id,point,self.sz)
self.wxi=None
self.image=None
self.wxb=None
self.SetImage(image)
EVT_PAINT(self,self.OnPaint)
#SetImage means that you are passing a new CRImage and
#therefore you need to reinit all the necessary
#data in the class
def SetImage(self,image):
self.image=image
if image:
self.sz=image.size
else:
self.sz=self.DEFAULTSIZE
self.SetSize(self.sz)
if self.wxi:
del self.wxi
self.wxi=wxEmptyImage(self.sz[0],self.sz[1])
self.UpdateImage(image)
#update image is called when the ImageSource
#is moved forward or backward
# and therefore the characteristics of the image
#(its size) do not change
def UpdateImage(self,image):
if image:
self.image=image
self.wxi.SetData(image.tostring())
if self.wxb:
del self.wxb
self.wxb=wxBitmapFromImage(self.wxi)
def Repaint(self):
dc=wxClientDC(self)
dc.BeginDrawing()
self.BlitFrame(dc)
dc.EndDrawing()
def BlitFrame(self,dc):
dc.DrawBitmap(self.wxb,0,0,0)
def OnPaint(self,event):
self.BlitFrame(wxPaintDC(self))
def saveImage(self,path):
self.image.save(path)
class MainFrame(wxFrame):
FILE_NEWWINDOW=10
FILE_OPEN=20
FILE_SAVE=30
FILE_EXIT=40
def __init__(self,parent,id,mainApp):
self.path=None
self.imageSource=None
self.moviePanel=None
self.mainApp=mainApp
wxFrame.__init__(self,parent,id,
"ImageSource Window",
wxPoint(100,100),
wxSize(358,300),
wxSYSTEM_MENU | wxCAPTION|wxMINIMIZE_BOX)
self.__MakeMenu()
self.imageWindow=CRImageWindow(self,-1,(-1,-1),None)
self.sizer=wxBoxSizer(wxVERTICAL)
self.SetAutoLayout(1)
self.SetSizer(self.sizer)
self.sizer.Add(self.imageWindow,0,wxALL,0)
self.sizer.Fit(self)
self.sizer.SetSizeHints(self)
def OpenFile(self,event):
dlg = wxFileDialog(self,
"Choose an ImageSource file (movie or picture)"
, ".", "",
"AVI files (*.avi)|*.avi|AviSynth files
(*.avs)|*.avs|QuickTime files (*.mov)|*.mov|MPEG
file (*.mpg)|*.mpg|All files (*.*)|*.*",
wxOPEN>wxHIDE_READONLY|wxFILE_MUST_EXIST)
if dlg.ShowModal() == wxID_OK:
self.SetImageSource(dlg.GetPath())
#A new ImageSource is opened,
#therefore we need to create it and change the window size
def SetImageSource(self,ISPath):
self.path=ISPath
if self.imageSource:
del self.imageSource
self.imageSource=ImageSource(
self.path,IS_PLAY_ONCE,RIMAGE_RGB24)
self.SetTitle(
"ImageSource Window: "
+os.path.basename(self.imageSource.name))
print self.sizer.Remove(self.imageWindow)
self.imageWindow.SetImage(self.imageSource.img)
self.sizer.Add(self.imageWindow,0,wxALL,0)
self.sizer.Fit(self)
self.sizer.Layout()
self.sizer.SetSizeHints(self)
class VideoApp(wxApp):
def __init__(self,id):
wxApp.__init__(self,id)
def OnInit(self):
ImageSourceInit()
frame=MainFrame(NULL,-1,self)
frame.Show(true)
self.SetTopWindow(frame)
return true
def makeNewFrame(self):
MainFrame(NULL,-1,self).Show()
if __name__=='__main__':
app=VideoApp(0)
app.MainLoop()