Problem mit wx.BufferedPaintDC

Plattformunabhängige GUIs mit wxWidgets.
Antworten
DirkP
User
Beiträge: 1
Registriert: Mittwoch 21. September 2011, 21:20

Hallo,

ich bin noch Anfänger in wxPython und habe mir aus vielen Beispielcodes eine Anwendung "zusammenkopiert" mit der ich ein Bild per Knopfdruck in kleinen Schritten links und rechts drehen will (an Raster ausrichten). Dieses Raster wird jedes mal über ein Bitmap gezeichnet. Ich möchte das Ganze möglichst Flickerfrei mit der wx.BufferedPaintDC- Methode realisieren.

Ich kann noch nicht abschätzen, wie umfangreich die Anwendung später werden wird und möchte sie von Anfang eine MVC (Model View Controller)-Struktur einsetzen. Ob mir dies bis jetzt gelungen ist, kann ich leider selbst noch nicht ganz einschätzen. Wie gesagt, es ist mein erstes GUI-Projekt.

Im Moment habe ich folgendes Problem:
Beim anklicken des "ROTATE RIGHT" bzw. "ROTATE LEFT"-Buttons wird nach meinem Verständnis, die "UpdateImageView"-Methode über das PubSub-System korrekt aufgerufen. Leider aktualisiert sich die Grafik nicht. Eswird bei mir lediglich ein kleines schwarzes Kästchen oben links erzeugt. Ich komme einfach nicht darauf, wo der Fehler stecken kann. Vielleicht kann mir hier jemand helfen?

Generelle Kommentare und Kritik zum Code sind natürlich auch sehr willkommen.

Vielen Dank im Voraus für Eure Bemühungen.

Gruß
DirkP

Hinweis: zum Ausführen des Programms ist ein Bild mit Namen "testpic.png" (vorzugsweise 400x300 pixel) im aktuellen Verzeichnis notwendig.

Code: Alles auswählen

#!/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()
Antworten