PNG-Transparenz

Plattformunabhängige GUIs mit wxWidgets.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

PNG-Transparenz

Beitragvon nkoehring » Montag 30. Juli 2007, 18:37

Hallo...


ich moechte ein fast vollstaendig grafisches UI fuer mein Programm haben. Das ganze wuerde sich aus PNGs zusammensetzen. Leider scheint wxPython ein Problem damit zu haben, die Transparenz darzustellen. Außerdem muss ich eine Mask-Color festlegen, da er sonst scheinbar Weiß oder Schwarz nimmt und dadurch Bildfehler einbaut. Die groesste Sorge ist aber weiterhin, dass eigentlich Transparente Grafiken (wo nicht nur eine Farbe komplett Transparent, sondern die einzelnen Farben alphawertig sind) nicht Transparent sind.

Danke schonmal fuer Antworten...

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

Re: PNG-Transparenz

Beitragvon gerold » Montag 30. Juli 2007, 19:04

nkoehring hat geschrieben:Leider scheint wxPython ein Problem damit zu haben, die Transparenz darzustellen.

Hallo nkoehring!

Unter Windows funktioniert es, wenn ich selber zeichne. Bitte ausprobieren:

Code: Alles auswählen

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

import wx

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


class MyFrame(wx.Frame):
   
    def __init__(
        self, parent = None, title = "Example", size = wx.Size(550, 420)
    ):
        wx.Frame.__init__(self, parent, -1, title, size = size)
       
        panel = wx.Panel(self)
        panel.SetBackgroundColour("white")
        self.panel = panel
       
        self.bmp = wx.Bitmap("bild.png")
        panel.Bind(wx.EVT_PAINT, self.on_panel_paint)
   
   
    def on_panel_paint(self, event):
        event.Skip()
       
        # Mit Buffer
        dc = wx.BufferedPaintDC(self.panel, buffer = self.bmp)
       
        # Ohne Buffer
        #dc = wx.PaintDC(self.panel)
        #dc.DrawBitmap(self.bmp, 0, 0, useMask = True)


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


if __name__ == "__main__":
    main()

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
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:

Beitragvon gerold » Montag 30. Juli 2007, 19:14

Besser so:

Code: Alles auswählen

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

import wx

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


class MyBitmapPanel(wx.Panel):
   
    def __init__(self, parent = None, background_color = "white", bitmap = None):
        wx.Panel.__init__(self, parent)
        self.SetBackgroundColour(background_color)
        self.bmp = bitmap
        if self.bmp:
            size = self.bmp.GetSize()
            self.SetSize(size)
            self.SetSizeHintsSz(size)
       
        self.Bind(wx.EVT_PAINT, self.on_self_paint)
   
   
    def on_self_paint(self, event):
        event.Skip()
        if self.bmp:
            dc = wx.BufferedPaintDC(self, buffer = self.bmp)
   
   

class MyFrame(wx.Frame):
   
    def __init__(
        self, parent = None, title = "Example", size = wx.Size(550, 420)
    ):
        wx.Frame.__init__(self, parent, -1, title, size = size)
       
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(vbox_main)
       
        bmp = wx.Bitmap("bild.png")
       
        green_panel = MyBitmapPanel(self, "green", bmp)
        vbox_main.Add(green_panel, 1, wx.EXPAND)
       
        yellow_panel = MyBitmapPanel(self, "yellow", bmp)
        vbox_main.Add(yellow_panel, 1, wx.EXPAND)
   
        self.Fit()
        self.SetSizeHintsSz(self.GetSize())


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


if __name__ == "__main__":
    main()

Bild
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Beitragvon nkoehring » Montag 30. Juli 2007, 19:43

ah vielen Dank... das sieht schonmal gut aus.

Nun muss ich nur noch viele Bilder uebereinander packen... ich hoffe dazu muss ich nicht jedesmal ein eigenes Panel definieren -.-
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Beitragvon nkoehring » Montag 30. Juli 2007, 19:47

Hmm... also die ganze Sache hat im Moment noch den Haken, dass ich zwar nun Transparenz habe, aber nur auf die Panel-Hintergrundfarbe bezogen... nicht auf das dahinter liegende Bild :(
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Montag 30. Juli 2007, 19:57

nkoehring hat geschrieben:Nun muss ich nur noch viele Bilder uebereinander packen... ich hoffe dazu muss ich nicht jedesmal ein eigenes Panel definieren

Hallo nkoehring!

Wenn du Widgets auf dem Bild platzieren möchtest --> wx.Panel
Wenn du nichts mehr auf dem Bild platzieren möchtest --> wx.Window

Wenn du die Bilder in je einen Container zeichnest, dann tust du dir evt. leichter beim Abfangen von Events. Das kommt aber auch ganz auf dein Konzept und Ziel an.

Wie auch immer. Eine selbst gestrickte Programmoberfläche kostet den Programmierer viel, viel, viel mehr Arbeit und ist meist nicht so benutzerfreundlich wie eine Standard-Oberfläche.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

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:

Beitragvon gerold » Montag 30. Juli 2007, 20:02

nkoehring hat geschrieben:dass ich zwar nun Transparenz habe, aber nur auf die Panel-Hintergrundfarbe bezogen... nicht auf das dahinter liegende Bild :(

Hallo nkoehring!

NUR UNTER WINDOWS:

Code: Alles auswählen

wx.Panel.__init__(self, parent, style = wx.TRANSPARENT_WINDOW)


wxTRANSPARENT_WINDOW The window is transparent, that is, it will not receive paint events. Windows only.

Wenn das Programm auch unter Linux laufen soll, dann bleibt dir nichts anderes übrig, als alles in ein einziges Widget (Panel, Window,...) zu zeichnen.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Beitragvon nkoehring » Dienstag 31. Juli 2007, 15:57

Hallo nochmal...

ich habe mich eben nochmal rangesetzt und probiert... und festgestellt, dass die Transparenz generell richtig Funktioniert, wenn ich pro Bild ein eigenes Label erstelle und dem Label keine Hintergrundfarbe zuweise... quasi so (getestet unter WinVista):

Code: Alles auswählen

class MyBitmapPanel(wx.Panel):
   
    def __init__(self, parent=None, bitmap=None):
        wx.Panel.__init__(self, parent)
        self.bmp = bitmap
        if self.bmp:
            size = self.bmp.GetSize()
            self.SetSize(size)
            self.SetSizeHintsSz(size)       
        self.Bind(wx.EVT_PAINT, self.on_self_paint)

    def on_self_paint(self, event):
        event.Skip()
        if self.bmp: wx.BufferedPaintDC(self, buffer=self.bmp)

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = wx.CAPTION
        wx.Frame.__init__(self, *args, **kwds)

        # preloades all needed Images (eg. img_bg and img_title)
        self.loadImages()

        bmp = wx.BitmapFromImage(self.img_bg)
        bmp2 = wx.BitmapFromImage(self.img_title)
        self.panel = MyBitmapPanel(self, "white", bmp)
        self.panel2 = MyBitmapPanel(self, "white", bmp2)
        self.Fit()
        self.SetSizeHintsSz(self.GetSize())

    def loadImages(self):
        # ...
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Dienstag 31. Juli 2007, 16:22

nkoehring hat geschrieben:pro Bild ein eigenes Label erstelle und dem Label keine Hintergrundfarbe zuweise... quasi so (getestet unter WinVista)

Hallo nkoehring!

1.) Welches Label? Meinst du Panel?

2.) Du darfst keine Panel übereinander (im gleichen Kontainer) anordnen, wenn du möchtest, dass dein Programm auch unter Linux und Mac funktioniert. Das ist eine der wenigen Einschränkungen, die man bedenken muss, wenn man portabel bleiben möchte.

Teste dein Programm doch auch mal unter Linux. Einfach "VirtualBox" installieren und darin z.B. "Ubuntu" als Gast installieren. Dann hast du ein Testsystem.

mfg
Gerold
:-)

PS: Mit wxPython 2.8 habe ich dieses Verhalten noch nicht unter Linux getestet. Vielleicht hat sich etwas geändert.
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Beitragvon nkoehring » Dienstag 31. Juli 2007, 17:05

danke fuer die Tipps, bei Gelegenheit mache ich das mal. Erstmal muss das Programm einfach nur unter Windows funktionieren, von daher ist die portabilitaet bisher Nebensache, aber dennoch erklaertes Ziel fuer Spaeter.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Beitragvon nkoehring » Dienstag 31. Juli 2007, 18:10

Hallo mal wieder... da kommt schonwieder ein Problem zustande.

Wenn ich auf das Panel (nicht Label :roll: ) einen Event ausfuehre, zB wx.EVT_LEFT_DOWN, soll sich das Bild aendern.
Meine Idee: Ich haenge je Panel eine Methode an den Event, die dafuer sorgt, dass self.bmp durch eine Alternativ-Bitmap ausgetauscht wird und veranlasse einen self.Refresh().
Ich habe zwei Varianten, die beide unterschiedlich falsch Funktionieren:
In der ersten haenge ich die Methode nur an den Event, wenn eine Alternativ-Bitmap uebergeben wird. Dann passiert nichts, wenn ich klicke (der Event scheint nicht zu greifen).
In der zweiten Variante haenge ich die Methode immer an und ueberpruefe innerhalb der Methode auf die Alternativ-Bitmap. Dann verschwinden alle Panels ueber dem ersten...

Zur Veranschaulichung hier der Code fuer die erste Variante:

Code: Alles auswählen

class MyBitmapPanel(wx.Panel):
   
    def __init__(self, parent=None, bitmap=None, alternate=None):
        wx.Panel.__init__(self, parent)
        self.bmp = bitmap
        self.orig = bitmap
        self.alt = alternate
        if self.bmp:
            size = self.bmp.GetSize()
            self.SetSize(size)
            self.SetSizeHintsSz(size)
        self.Bind(wx.EVT_PAINT, self.on_self_paint)
       
        if self.alt:
            self.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
            self.Bind(wx.EVT_LEFT_UP, self.on_mouse_up)

    def on_mouse_down(self, evt):
        print "down..."
        self.bmp = self.alt
        self.Refresh()
   
    def on_mouse_up(self, evt):
        print "and up..."
        self.bmp = self.orig
        self.Refresh()
   
    def on_self_paint(self, evt):
        evt.Skip()
        if self.bmp: wx.BufferedPaintDC(self, buffer=self.bmp)


EDIT: okay, ich weiß jetzt, dass die obenliegenden Bitmaps einfach hinter das "Hintergrundbild" rutschen und dadurch unsichtbar werden. Sorge ich dafuer, dass keine Panels uebereinanderliegen, funktioniert alles so wie ich mir das vorstelle...
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Beitragvon nkoehring » Dienstag 31. Juli 2007, 19:11

Eine Frage... ist es erlaubt, das Canvas vom Frame selbst zu bemalen und dann bemalte Panels drueber zu packen? Denn das scheint gut zu funktionieren...
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Dienstag 31. Juli 2007, 20:45

nkoehring hat geschrieben:Eine Frage... ist es erlaubt, das Canvas vom Frame selbst zu bemalen und dann bemalte Panels drueber zu packen? Denn das scheint gut zu funktionieren...

Hallo nkoehring!

Das weiß ich nicht. Schiebe mal ein kleines Beispiel ins "Lodge it". Dann kann ich es ausprobieren.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Beitragvon nkoehring » Dienstag 31. Juli 2007, 22:06

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

Beitragvon gerold » Dienstag 31. Juli 2007, 23:17

nkoehring hat geschrieben:http://paste.pocoo.org/show/2102/ ...sollte klappen

Hallo nkoehring!

Eigentlich dachte ich an ein funktionierendes Beispiel. :mrgreen:

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder