Hintergrundgrafiken in Frames / Sizern

Plattformunabhängige GUIs mit wxWidgets.
Antworten
sacro_thaan
User
Beiträge: 12
Registriert: Montag 23. Januar 2006, 03:21

Hallo liebe Gemeinde,

ich brauche für ein Programm einen SplashScreen und einen About-Dialog. Beide sollen jeweils eine BMP-Grafik (624*224) und einige Buttons (agree/don't agree bzw. OK) beinhalten. Ich hatte vor, das über einen Frame mit zwei Sizern zu machen, einer für die Grafik und einer für die Buttons. Wegen der Größe der Grafik scheint wxStaticBitmap ja wohl nicht zu funktionieren und wegen den Buttons kann ich wxSplashScreen nicht nehmen. Hat einer eine Idee bzw. sogar Code, wie ich das Problem lösen könnte?

Oder hat jemand gefunden, wo ich den Code von wxSplashScreen finde?

Grüße

Till Wagner
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi Till!

Das Einzige was ich zum Thema Hintergrundbild finden kann, ist ein Hinweis auf die Demo --> ColourDB.py.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

sacro_thaan hat geschrieben:Hallo liebe Gemeinde,

ich brauche für ein Programm einen SplashScreen und einen About-Dialog. Beide sollen jeweils eine BMP-Grafik (624*224) und einige Buttons (agree/don't agree bzw. OK) beinhalten. Ich hatte vor, das über einen Frame mit zwei Sizern zu machen, einer für die Grafik und einer für die Buttons. Wegen der Größe der Grafik scheint wxStaticBitmap ja wohl nicht zu funktionieren und wegen den Buttons kann ich wxSplashScreen nicht nehmen. Hat einer eine Idee bzw. sogar Code, wie ich das Problem lösen könnte?

Oder hat jemand gefunden, wo ich den Code von wxSplashScreen finde?

Grüße

Till Wagner
Hallo Till,

vielleicht hilft dir AdvancedSplashScreen (und auch das studieren des Source Codes) von Andrea Gavana weiter.

http://xoomer.virgilio.it/infinity77/en ... plash.html

Ich glaube nicht, dass die Grafik für wx.StaticBitmap zu gross wäre.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi!

Ich habe mich auch noch ein wenig mit diesem Thema beschäftigt. Das ist dabei raus gekommen:

http://gerold.bcom.at/bilder/background_image_test.zip

Leider macht wxPython bei diesem Thema Unterschiede zwischen dem Verhalten unter Linux und unter Windows. GTK hat mit Hintergrundbildern kein Problem. Einfach zuerst das Bild auf das Panel setzen und dann erst das Label und den Button. Das was zuerst auf das Panel gelegt wird, erscheint hinter dem was danach drauf gelegt wird.

Unter Windows hatte ich mit dem gleichen Vorgehen beim Label kein Problem. Nur der Button wurde nicht angezeigt. Irgendwie scheint er wohl hinter das Bild gekommen zu sein. Wenn man aber den Button auf ein neues Panel legt, dann scheint es wieder zu funktionieren.

Leider ist das StaticText-Widget nicht transparent, so dass im Bereich des Labels das Bild nicht durchscheint. Wie das alles unter Linux und Windows aussieht, habe ich mit Bildern im oben genannten Zip-File dokumentiert.

Wie es aussieht, muss man wohl den Text in das Bitmap schreiben. Das kann zwar auch dynamisch von wxPython erledigt werden, muss aber nur dann sein, wenn auch die Größe des Fensters dynamisch und dadurch auch der Text dynamisch positioniert werden soll.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

gerold hat geschrieben:Hi!

Ich habe mich auch noch ein wenig mit diesem Thema beschäftigt. Das ist dabei raus gekommen:

http://gerold.bcom.at/bilder/background_image_test.zip

Leider macht wxPython bei diesem Thema Unterschiede zwischen dem Verhalten unter Linux und unter Windows. GTK hat mit Hintergrundbildern kein Problem. Einfach zuerst das Bild auf das Panel setzen und dann erst das Label und den Button. Das was zuerst auf das Panel gelegt wird, erscheint hinter dem was danach drauf gelegt wird.

Unter Windows hatte ich mit dem gleichen Vorgehen beim Label kein Problem. Nur der Button wurde nicht angezeigt. Irgendwie scheint er wohl hinter das Bild gekommen zu sein. Wenn man aber den Button auf ein neues Panel legt, dann scheint es wieder zu funktionieren.

Leider ist das StaticText-Widget nicht transparent, so dass im Bereich des Labels das Bild nicht durchscheint. Wie das alles unter Linux und Windows aussieht, habe ich mit Bildern im oben genannten Zip-File dokumentiert.

Wie es aussieht, muss man wohl den Text in das Bitmap schreiben. Das kann zwar auch dynamisch von wxPython erledigt werden, muss aber nur dann sein, wenn auch die Größe des Fensters dynamisch und dadurch auch der Text dynamisch positioniert werden soll.

lg
Gerold
:-)
Hallo Gerold, das ist ein schönes Beispiel.
Wäre interessant, was Robin Dunn dazu meint.
pr0stAta
User
Beiträge: 271
Registriert: Freitag 17. September 2004, 11:49
Wohnort: Bremen

Hallo sacro_thaan,
einen Splash Screen kannst du relativ einfach so erstellen:

Code: Alles auswählen

class MySplashScreen(wx.SplashScreen):
    def __init__(self):
        bmp = wx.Image(("splash.png")).ConvertToBitmap()
        wx.SplashScreen.__init__(self, bmp,
                                 wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
                                 2000, None, -1) #2000 ist die Anzeigedauer
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.fc = wx.FutureCall(2000, self.ShowMain)

    def OnClose(self, evt):
        evt.Skip()
        self.Hide()
        if self.fc.IsRunning():
            self.fc.Stop()
            self.ShowMain()

    def ShowMain(self):
      #RUFE HIER DEINE FRAME KLASSE AUF z.B. so:
      frame = Gui()
      frame.Show(True)
      return True


class MyApp(wx.App):
    def OnInit(self):
        wx.SystemOptions.SetOptionInt("mac.window-plain-transition", 1)     
        splash = MySplashScreen()
        splash.Show()

        return True

if (__name__ == '__main__'):
    app = MyApp(False)
    app.MainLoop()
Gruss
sacro_thaan
User
Beiträge: 12
Registriert: Montag 23. Januar 2006, 03:21

Hallo,

danke für eure Hilfe. Leider hat mir keiner eurer Ansätze direkt geholfen, aber ich habe es doch noch hinbekommen. Zwar vom Code her nicht wirklich schön (und Francesco, ich weiß, ich habe immer noch nicht auf den neuen Namespace umgestellt), aber es funktioniert und liefewrt mir genau das, was ich haben wollte. Und nochmal Francesco, du hast recht gehabt. Mit wx.StaticBitmap funktioniert es tatsächlich, jetzt hoffe ich nur, dass das Programm nicht auf Win9x Rechnern laufen soll, da scheint die größe der Bitmaps tatsächlich beschränkt zu sein.

So, für alle, die es interessiert, hier der Code:

Code: Alles auswählen

from wxPython.wx import *

# IDs for controls SplashScreen / About-Box ----------------
ID_BUTTON_AGREE = 5200
ID_BUTTON_DONT_AGREE = 5201
ID_BUTTON_OK = 5202


class SplashScreen(wxFrame):
    def __init__(self, parent, id, title, application, modus):
        wxFrame.__init__(self, parent, id, title,
                         style = wxSTAY_ON_TOP|wxCAPTION |wxCLIP_CHILDREN)

        self.SetBackgroundColour(wxNamedColor("WHITE"))
        self.modus = modus
        self.application = application
        self.ThumbSize = (624,224) # The Size of the Bitmap

        self.button_agree = wxButton(self, ID_BUTTON_AGREE, "I agree")
        self.button_OK = wxButton(self, ID_BUTTON_OK, "OK")
        self.button_dont_agree = wxButton(self, ID_BUTTON_DONT_AGREE, "I do not Agree")

        EVT_BUTTON(self,ID_BUTTON_AGREE, self.PushAgree)
        EVT_BUTTON(self,ID_BUTTON_OK, self.PushOK)
        EVT_BUTTON(self,ID_BUTTON_DONT_AGREE, self.PushDontAgree)

        self.button_agree.SetToolTip(wxToolTip("Agrees and starts the program"))
        self.button_OK.SetToolTip(wxToolTip("Closes the about-dialog"))
        self.button_dont_agree.SetToolTip(wxToolTip("Disagrees and closes the program"))

        self.label = wxStaticText(self, -1,
                                  "This program is for research use only!\n\n"
                                  "Do you agree to that terms?")

        self.Image = wxStaticBitmap(self, -1, wxEmptyBitmap(*self.ThumbSize))
        self.Img = wxImage("MyBitmap.bmp", wxBITMAP_TYPE_BMP).Scale(*self.ThumbSize)
        self.Image.SetBitmap(wxBitmapFromImage(self.Img))

        self.sizer_top = wxFlexGridSizer(5, 1, 5, 5)
        self.sizer_buttons = wxBoxSizer(wxHORIZONTAL)

        self.sizer_buttons.Add(self.button_agree, 0, wxALL, 5)
        self.sizer_buttons.Add(self.button_OK, 0, wxALL, 5)
        self.sizer_buttons.Add(self.button_dont_agree, 0, wxALL, 5)

        if self.modus == "splash":
            self.sizer_buttons.Show(1, false)

        if self.modus == "about":
            self.sizer_buttons.Show(0, false)
            self.sizer_buttons.Show(2, false)
            self.label.SetLabel("This program is for research use only!")

        font = self.label.GetFont()
        font.SetPointSize(16)
        self.label.SetFont(font)

        self.sizer_top.Add(self.Image, 0)
        self.sizer_top.Add(self.label, 0, wxALIGN_CENTER|wxALL, 15)
        self.sizer_top.Add(self.sizer_buttons, 0, wxALIGN_CENTER, 5)

        self.sizer_top.Fit(self)
        self.SetAutoLayout(True)
        self.SetSizer(self.sizer_top)

    def PushAgree(self, event):
        frame = MainFrame(self.application, -1, "MainWindow")
        self.application.SetTopWindow(frame)	
        frame.Show(true)
        self.Destroy()

    def PushOK(self, event):
        self.Destroy()
        
    def PushDontAgree(self, event):
        self.application.ExitMainLoop()
    

class MyApp(wxApp):
    def OnInit(self):
        frame = SplashScreen(None, -1, "User Agreement", self, "splash")
        self.SetTopWindow(frame)
        frame.CentreOnScreen()
        frame.Show(True)
        return True


def main():
    app = MyApp(0)
    app.MainLoop()

	
if __name__ == "__main__":
    main()
	
Gruß

Till
pr0stAta
User
Beiträge: 271
Registriert: Freitag 17. September 2004, 11:49
Wohnort: Bremen

Ah ok, ich hätte deinen Beitrag wohl doch etwas genauer lesen sollen.
Normalerweise sind SplashScreens ja jene Bilder, die auftauchen sobald
man ein Programm startet. Sie dienen ja nur dazu um die Ladezeit zu überbrücken.
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

sacro_thaan hat geschrieben:Hallo,

danke für eure Hilfe. Leider hat mir keiner eurer Ansätze direkt geholfen, aber ich habe es doch noch hinbekommen. Zwar vom Code her nicht wirklich schön (und Francesco, ich weiß, ich habe immer noch nicht auf den neuen Namespace umgestellt), aber es funktioniert und liefewrt mir genau das, was ich haben wollte. Und nochmal Francesco, du hast recht gehabt. Mit wx.StaticBitmap funktioniert es tatsächlich, jetzt hoffe ich nur, dass das Programm nicht auf Win9x Rechnern laufen soll, da scheint die größe der Bitmaps tatsächlich beschränkt zu sein.

So, für alle, die es interessiert, hier der Code:

Ja, mich interessiert das, wieder schönes Sample, kommt gleich in
meine Codesammlung. :)

Das mit dem Namespace:
Habe es vielleicht zu oft betont, ist aber eh nicht so wichtig. :)

Mit der Grösse:
Habe auf WindowsXP mit 800x600 pixel Grafik probiert (obwohl du Win9x gemeint hast), und das wird angezeigt;
Sowohl mit der Original- als auch mit reduzierter Grösse.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Francesco hat geschrieben:Das mit dem Namespace:
Habe es vielleicht zu oft betont, ist aber eh nicht so wichtig. :)
Hi Francesco!

Das ist für dich vielleicht nicht wichtig, aber für mich ist wxPython erst durch die neue Schreibweise interessant geworden.

Die alte Schreibweis und die excessive Nutzung der ID´s, hat mich so abgeschreckt, dass ich mich lieber erst mit Tkinter und pyGtk befasst habe. In pyGTK habe ich mich sogar intensiv eingelesen. Alles umsonst, da ich mich jetzt endlich mit wxPython befasse und mit dem Wissen um die anderen GUI´s kaum mehr etwas anfangen kann.

Seit ich "Bind()" kenne und "wx" importieren kann, hat sich wxPython für mich um 180° gedreht. -- Zum Guten.

Es fühlt sich jetzt logischer und durchschaubarer an, obwohl sich kaum etwas geändert hat.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

gerold hat geschrieben:
Francesco hat geschrieben:Das mit dem Namespace:
Habe es vielleicht zu oft betont, ist aber eh nicht so wichtig. :)
Hi Francesco!

Das ist für dich vielleicht nicht wichtig, aber für mich ist wxPython erst durch die neue Schreibweise interessant geworden.

Die alte Schreibweis und die excessive Nutzung der ID´s, hat mich so abgeschreckt, dass ich mich lieber erst mit Tkinter und pyGtk befasst habe. In pyGTK habe ich mich sogar intensiv eingelesen. Alles umsonst, da ich mich jetzt endlich mit wxPython befasse und mit dem Wissen um die anderen GUI´s kaum mehr etwas anfangen kann.

Seit ich "Bind()" kenne und "wx" importieren kann, hat sich wxPython für mich um 180° gedreht. -- Zum Guten.

Es fühlt sich jetzt logischer und durchschaubarer an, obwohl sich kaum etwas geändert hat.

lg
Gerold
:-)
Hi Gerold,

aha, so habe ich das noch nie betrachtet. :)

Ich habe eine Antwort von Robin Dunn:
Wegen dem Problem, das der Button nicht auf dem SplashScreen zu sehen ist:

This is because in effect you are overlapping the StaticBitmap and the
Button controls, and overlapping sibling controls is supported by
wxWidgets. A better approach would be to not use the wx.StaticBitmap,
but instead bind a handler to the panel's EVT_ERASE_BACKGROUND event,
and in that handler draw the bitmap to the dc given to you by the event
object.


wegen dem transparenten StaticText:

On wxGTK and wxMac the native static text controls are naturally
transparent (because either they are just drawn directly on the parent,
or because multi-layer compositing is done by the platform) but on
Windows they are their own window. Some work has been done in wxWidgets
to make them inherit the background of the parent in order to appear
transparent, but that currently only works for solid colour backgrounds,
or unmodified themed backgrounds on XP.

The easiest thing to do now is to either make the text be part of the
image, or draw it yourself on the dc after drawing the bitmap.

(Also Device Context DrawText verwenden, um transparent zu erhalten.)
sacro_thaan
User
Beiträge: 12
Registriert: Montag 23. Januar 2006, 03:21

Hallo Francesco,
Francesco hat geschrieben: Ja, mich interessiert das, wieder schönes Sample, kommt gleich in
meine Codesammlung. :)
Auf dass es irgendwas mal jemandem helfe, der ein Ähnliches Proglem hat. Gut, dass es Menschen wie dich gibt, die alles Sammeln ;-)
Francesco hat geschrieben:Das mit dem Namespace:
Habe es vielleicht zu oft betont, ist aber eh nicht so wichtig. :)
Nee, hast ja Recht. Aber ich nutze (falls das jemand kennt) Python Enthought Edition (http://code.enthought.com/enthon/), weil es auf der Seite der Matplotlib-Bibliothek (http://matplotlib.sourceforge.net/) empfohlen wurde. Und dort in der Doku wird der neue Namespace nicht verwendet. Auch einige Code.Snippnets, die ich im Netzt gefunden hatte, verwenden ihn nicht. Daher wusste ich es am anfang nicht, und bin im Moment zu faul umzustellen. Kommt aber noch, wenn ich das Gröbste geschafft habe.
Francesco hat geschrieben:Mit der Grösse:
Habe auf WindowsXP mit 800x600 pixel Grafik probiert (obwohl du Win9x gemeint hast), und das wird angezeigt;
Sowohl mit der Original- als auch mit reduzierter Grösse.
Ich nutze XP und soweit ich weiss, soll das Programm unter XP und 2000 laufen. Auf die Einschränkung bin ich nur wegen der mir vorliegenden Doku gekommen:

"wxStaticBitmap
A static bitmap control displays a bitmap. It is meant for display of the small icons in the dialog boxes and is not meant to be a general purpose image display control. In particular, under Windows 9x the size of bitmap is limited to 64*64 pixels and thus you should use your own control if you want to display larger images portably.

Remarks

The bitmap to be displayed should have a small number of colours, such as 16, to avoid palette problems."

Gruß

Till
Antworten