Hi all,
I am just a beginner in wxPython programming. I want to rotate a PNG-Picture in
small steps cw and ccw to align it to an overlayed grid. The grid has to be
drawn over the bitmap everytime. I want to do that flicker free with the
'wx.BufferedPaintDC'-methode.
At the moment I can not say where the program will end up, so I try to do the
whole code according to the MVC (Model View Controller)-structure to keep it
upgradable without loosing the overview. I do not have the experience now to
understand if this is the best way for this project. It is my first GUI-software.
The Problem:
If I click on the [ROTATE RIGHT] or the [ROTATE LEFT]-Button the
'UpdateImageView'-methode is called correctly by the PubSub-System. But the
picture will not be updated. I see only a small black square on the upper left
corner. I can't help myself, I did not find any mistake. Maybe someone can give
me a hint? General comments to the code are also very welcome.
Thank you in advance.
DirkP
Hint: to run the code it is needed have a picture "testpic.png" (400x300 px) in
the current directory.
#!/usr/bin/env python
"""
Rotates image right or left
"""
import wx
from wx.lib.pubsub import Publisher as pub
class ImageWork (object):
def __init__(self):
self.rot_angle_total = 0.0
def ImgLoad (self):
self.img = wx.Image('testpic.png', wx.BITMAP_TYPE_PNG)
return self.img
def ImgRotate (self, dir, image):
self.img = image
self.img_centre = wx.Point(self.img.GetWidth()/2,self.img.GetHeight()/2 )
if dir == "right":
rot_angle_incr=-0.01
else:
rot_angle_incr=0.01
self.rot_angle_total = self.rot_angle_total+rot_angle_incr
self.img =
self.img.Rotate(self.rot_angle_total,self.img_centre,interpolating=True)
print self.rot_angle_total
pub.sendMessage("IMAGE CHANGED", self.img)
return self.img
class ImageView(wx.Frame):
def __init__(self, parent, image):
wx.Frame.__init__(self, parent, title="ImageView", size=(450,450))
self.img_view = image
img_window = PaintWindow(self, 1, self.img_view)
def UpdateImageView(self, image):
self.img_view = image
img_window = PaintWindow(self, 1, self.img_view)
class PaintWindow(wx.Window):
def __init__(self, parent, ID, image):
wx.Window.__init__(self, parent)
self.bmp = image.ConvertToBitmap()
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_PAINT, self.OnPaint)
def OnSize(self, evt):
self.InitBuffer()
def OnPaint(self, evt):
dc = wx.BufferedPaintDC(self, self.buffer)
def InitBuffer(self):
w, h = self.GetClientSize()
self.buffer = wx.EmptyBitmap(w, h)
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
dc.Clear()
self.DrawView(dc)
def DrawView(self, dc):
dc.DrawBitmap(self.bmp, 1, 1, True)
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangle(10,10, 380, 270)
dc = wx.BufferedPaintDC(self, self.buffer)
class ControlpanelView(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title="Control Panel",size=(200,200))
sizer = wx.BoxSizer(wx.VERTICAL)
self.rotright_btn = wx.Button(self, label="ROTATE RIGHT")
self.rotleft_btn = wx.Button(self, label="ROTATE LEFT")
sizer.Add(self.rotright_btn, 0, wx.EXPAND | wx.ALL)
sizer.Add(self.rotleft_btn, 0, wx.EXPAND | wx.ALL)
self.SetSizer(sizer)
class Controller:
def __init__(self, app):
self.imagework = ImageWork()
self.img=self.imagework.ImgLoad()
self.imagewindow = ImageView(None, self.img)
self.controlwindow = ControlpanelView(self.imagewindow)
self.controlwindow.rotright_btn.Bind(wx.EVT_BUTTON, self.RotRight)
self.controlwindow.rotleft_btn.Bind(wx.EVT_BUTTON, self.RotLeft)
pub.subscribe(self.ImageChanged, "IMAGE CHANGED")
self.imagewindow.Show()
self.controlwindow.Show()
def RotRight (self, event):
self.img = self.imagework.ImgRotate("right", self.img)
def RotLeft(self, event):
self.img = self.imagework.ImgRotate("left", self.img)
def ImageChanged(self, message):
self.imagewindow.UpdateImageView(message.data)
if __name__ == "__main__":
app = wx.App(False)
controller = Controller(app)
app.MainLoop()