Bitmap in Dialog darstellen

Plattformunabhängige GUIs mit wxWidgets.
Antworten
samy-delux
User
Beiträge: 44
Registriert: Donnerstag 26. April 2007, 19:23

Dienstag 1. Mai 2007, 20:25

Hey Leute,

Ich benutze folgenden Code um ein Bild in einem Dialog darzustellen. Die Funktion 'ShowMap()' wird durch einen Button aufgerufen...

Code: Alles auswählen

    def ShowMap(self, event):
        self.bitmap = wx.Bitmap('/home/samy/workspace/Flugsuche/karte.jpg')
        
        dc = wx.MemoryDC(self.bitmap)
        gc = wx.GraphicsContext_Create(dc)
        pen = wx.Pen("white", 4, wx.SOLID)
        gc.SetPen(pen)
       
        # Test linie
        gc.DrawLines(((10, 40), (300, 150)))
       
        dc.SelectObject(wx.NullBitmap) 
        
        wx.EVT_PAINT(self, self.OnPaint)

        self.resultdialog = wx.Dialog(self, -1, "Karte", wx.Point(200,200), size=(410, 358))

        self.resultdialog.ShowModal()
        self.resultdialog.Destroy()
    
    
    def OnPaint(self, event):
        dc = wx.PaintDC(self.resultdialog)
        dc.DrawBitmap(self.bitmap, 5, 5)
Wenn ich den Dialog jetzt jedoch schliesse, tritt folgender Fehler aus:

Code: Alles auswählen

Traceback (most recent call last):
  File "./workspace/Flugsuche/mainwx.py", line 241, in OnPaint
    dc = wx.PaintDC(self.resultdialog)
  File "/usr/lib/python2.4/site-packages/wx-2.8-gtk2-unicode/wx/_gdi.py", line 4626, in __init__
    _gdi_.PaintDC_swiginit(self,_gdi_.new_PaintDC(*args, **kwargs))
TypeError: in method 'new_PaintDC', expected argument 1 of type 'wxWindow *'
Traceback (most recent call last):
  File "./workspace/Flugsuche/mainwx.py", line 241, in OnPaint
    dc = wx.PaintDC(self.resultdialog)
  File "/usr/lib/python2.4/site-packages/wx-2.8-gtk2-unicode/wx/_gdi.py", line 4626, in __init__
    _gdi_.PaintDC_swiginit(self,_gdi_.new_PaintDC(*args, **kwargs))
TypeError: in method 'new_PaintDC', expected argument 1 of type 'wxWindow *'
Hab schon etwas rumporbiert... aber ich versteh nicht, warum OnPaint nach dem schliessen des Dialogs nocheinmal aufgerufen wird?
Oder sehe ich es eh komplett falsch??

so long,
Samy
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Dienstag 1. Mai 2007, 20:55

samy-delux hat geschrieben:Code um ein Bild in einem Dialog darzustellen.
Hi Samy!

Drei Probleme:

1.

Code: Alles auswählen

``wx.EVT_PAINT(self, self.OnPaint)``
Das war einmal vor ein paar hundert Jahren, als man noch das Event initialisierte und dabei das Objekt und den Handler übergab.

Das ist lange her und war ziemlich komisch zu programmieren.
Ich bin froh, dass wir heute mit ``Bind()`` arbeiten können.

Code: Alles auswählen

self.Bind(wx.EVT_PAINT, self.OnPaint)
2. Das Paint-Event tritt immer dann auf, wenn ein Teil eines Fensters (Window, Widget, ...) neu gezeichnet werden muss. Einzige Ausnahme ist die Maus. Fährst du mit der Maus über ein Fenster, dann kümmert sich das Betriebssystem, Gnome oder KDE selber darum, dass das Bild hinter der Maus neu gezeichnet wird. Fährst du aber z.B. mit einem Fenster über den Bildschirm-Bereich hinaus und dann wieder zurück, dann muss das Fenster oder ein Teil davon neu gezeichnet werden. Wird ein anderes Fenster über dem Fenster angezeigt, bewegt oder geschlossen, dann muss dein Fenster neu gezeichnet werden. Und in solchen Fällen löst wxPython das Ereignis "EVT_PAINT" aus.

3. Du hast eine Methode (Eventhandler) an das PAINT-Ereignis des Frames gebunden und verwendest dieses Ereignis zum Zeichnen in ein **anderes** Widget -- in einen Dialog. Das funktioniert zwar prinzipiell, aber ist erstens nicht sinnvoll und zweitens gerätst du damit in einen Teufelskreis. Der Dialog wird ja über dem Frame angezeigt. Wird der Dialog bewegt oder geschlossen, dann wird das PAINT-Ereignis des Frames aufgerufen. --> aber wohin soll jetzt gezeichnet werden? Der Dialog ist ja schon nicht mehr da.

Fazit: Du solltest dir überlegen, deinen Dialog als eigenständige Klasse zu realisieren und schon beim Initialisieren des Dialogs das Bild mitzugeben.

mfg
Gerold
:-)

PS: Bitte versuche so oft wie möglich, funktionierenden Beispielcode mitzuliefern, der dein Problem aufzeigt. Dann muss man nicht immer selber ein Gerüst um den Problemcode herum bauen.
[url]http://halvar.at[/url] | [url=http://halvar.at/elektronik/kleiner_bascom_avr_kurs/]Kleiner Bascom AVR Kurs[/url]
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Dienstag 1. Mai 2007, 21:14

In etwa so:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import wx

wx.SetDefaultPyEncoding("iso-8859-15")


class MyDialog(wx.Dialog):
    
    def __init__(
        self, parent = None, id = -1, title = "Karte", bitmap = None
    ):
        wx.Dialog.__init__(self, parent, id, title)
        self.bitmap = bitmap
        self.SetClientSize(bitmap.GetSize())
        self.Bind(wx.EVT_PAINT, self.on_paint)
    
    
    def on_paint(self, event = None):
        dc = wx.PaintDC(self)
        dc.DrawBitmap(self.bitmap, 0, 0)    


class MyFrame(wx.Frame):
    
    def __init__(
        self, parent = None, id = -1, title = "Example", size = wx.Size(550, 420)
    ):
        wx.Frame.__init__(self, parent, id, title, size = size)
        
        panel = wx.Panel(self)
        
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox_main)
        
        button = wx.Button(panel, -1, "Show map")
        vbox_main.Add(button, 1, wx.EXPAND | wx.ALL, 10)
        button.Bind(wx.EVT_BUTTON, self.ShowMap)
    
    
    def ShowMap(self, event):
        self.bitmap = wx.Bitmap('test.jpg')
       
        dc = wx.MemoryDC(self.bitmap)
        gc = wx.GraphicsContext_Create(dc)
        pen = wx.Pen("white", 4, wx.SOLID)
        gc.SetPen(pen)
       
        gc.DrawLines(((10, 40), (300, 150)))
       
        dc.SelectObject(wx.NullBitmap)
       
        self.resultdialog = MyDialog(self, -1, bitmap = self.bitmap)
        self.resultdialog.ShowModal()
        self.resultdialog.Destroy()


def main():
    """Testing"""
    
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
mfg
Gerold
:-)
Zuletzt geändert von gerold am Mittwoch 2. Mai 2007, 21:33, insgesamt 1-mal geändert.
[url]http://halvar.at[/url] | [url=http://halvar.at/elektronik/kleiner_bascom_avr_kurs/]Kleiner Bascom AVR Kurs[/url]
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
samy-delux
User
Beiträge: 44
Registriert: Donnerstag 26. April 2007, 19:23

Mittwoch 2. Mai 2007, 20:53

Danke fuer die grosszuegige Hilfe!!
Das Forum hier ersetzt fast die maessige Dokumentation von Python! Hier bekommt man die Beispiele, die bei zum Beispiel PHP direkt dabei sind :D
Antworten