Standardformatierung in StaticFancyText setzen (neues Prob)

Plattformunabhängige GUIs mit wxWidgets.
Antworten
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Hallo,

ich habe eine Möglichkeit gefunden, einen StaticFancyText nachträglich zu ändern mit:

Code: Alles auswählen

import  wx.lib.fancytext as fa


wx.SetDefaultPyEncoding("utf-8") 


class StaticFancyText(fa.StaticFancyText):
    """StaticFancyText with SetLabel function."""
        
    def SetLabel(self, label):
        label='<font weight="bold" size="11">'+label+'</font>'
        bmp = fa.RenderToBitmap(label,
                wx.Brush(self.GetBackgroundColour(), wx.SOLID))
        self.SetBitmap(bmp)
so kann ich über

Code: Alles auswählen

text.SetLabel('neuer Text')
den vorh. Text ändern und gleichzeitig formatieren,
soweit so gut,
ich möchte aber mit dem Aufruf

Code: Alles auswählen

text=StaticFancyText(self,'text')

gerne von vornherein eine Formatierung erreichen, also einen neu zu erstellenden Text. Im Moment wird der Text im Format der Systemeinstellung ausgegeben. Das Ergebnis soll dann die Wirkung von

Code: Alles auswählen

text=StaticFancyText(self,'<font weight="bold" size="11"> text </font>')
haben

Ich habe lange rumprobiert, aber ich brauche wohl noch einen Gedankenstoß...wie ich das in die Klasse einbaue

Gruß Mathi
Zuletzt geändert von mathi am Freitag 27. August 2010, 13:48, insgesamt 1-mal geändert.
ntrunk
User
Beiträge: 83
Registriert: Sonntag 7. September 2008, 23:09
Wohnort: Buchen (Odenwald)

Hi mathi,
mathi hat geschrieben:

Code: Alles auswählen

text=StaticFancyText(self,'text')
Das erzeugt bei mir einen Fehler

Code: Alles auswählen

Traceback (most recent call last):
  File "test.py", line 8, in <module>
    text=StaticFancyText(self,'text')
TypeError: __init__() takes at least 4 arguments (3 given)
wegen fehlender Angabe der id.
So funktioniert es bei mir

Code: Alles auswählen

import wx
import wx.lib.fancytext as fa

testtext = '<font size="32">Hello world!</font>'

app = wx.App()
frame = wx.Frame(None)
sft = fa.StaticFancyText(frame, -1, testtext)
frame.Show()
app.MainLoop()
Gruß
Norbert
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

ja, Entschuldigung die ID hab ich natürlich vergessen.

Mein Problem ist aber ein anderes, dass ich die Formatierung zentral in einer Klasse haben möchte um strings in versch. Frames gleichzeitig ändern zu können. Daher will ich nicht jeden string einzeln formatieren...

Ich hoffe ich habe mich jetzt klarer ausgedrückt..

Gruß Mathi
BlackJack

@ntrunk: Statt der -1 würde ich `wx.ID_ANY` verwenden. Dann weiss man beim Lesen eher dass an der Stelle eine ID erwartet wird, und wundert sich nicht über die "magische" -1.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

man könnte das Problem z.B. so lösen:

Code: Alles auswählen

class F_Text(fa.StaticFancyText):
    """StaticFancyText with SetLabel function."""
           
    def SetLabel(self, label):
        label='<font weight="bold" size="11">'+label+'</font>'
        bmp = fa.RenderToBitmap(label,
                wx.Brush(self.GetBackgroundColour(), wx.SOLID))
        self.SetBitmap(bmp)
        
def StaticFancyText(self,id,label):
    label='<font family="roman" size="10">'+label+'</font>'
    return F_Text(self,id,label) 
Es funktioniert, aber ich finde das irgendwie ......unschön
BlackJack

@mathi: Du musst halt in Deiner abgeleiteten Klasse auch die `__init__()` überschreiben und dort dann `SetLabel()` aufrufen.
ntrunk
User
Beiträge: 83
Registriert: Sonntag 7. September 2008, 23:09
Wohnort: Buchen (Odenwald)

Hallo zusammen,
mathi hat geschrieben:man könnte das Problem z.B. so lösen:
[... code mit factory-Funktion ausgelassen ...]

Es funktioniert, aber ich finde das irgendwie ......unschön
Es ist unnötig kompliziert, und das ist eigentlich mein Ressort ;-)
Das macht man üblicherweise so:

Code: Alles auswählen

class MyStaticFancyText(fa.StaticFancyText):
    """StaticFancyText with SetLabel function."""
    default_format = '<font weight="bold" size="11">%s</font>'
    def __init__(self, id, label, *args, **kwargs):
        fa.StaticFancyText.__init__(self, id,
            MyStaticFancyText.default_format % label, *args, **kwargs)
    [....]
Kurze Erläuterung, falls du, wie ich glaube, wenig Erfahrung mit dem Ableiten von Klassen hast: die __init__-Methode wird jedes Mal aufgerufen, wenn du eine neue Instanz deiner Klasse erzeugst. Der erste Schritt ist dann i.d.R., die __init__-Methode der Basisklasse aufzurufen.

Gruß
Norbert

edit: Hmm, knapp zu spät ... aber ausführlicher :)
BlackJack

Ich habe mir mal die Implementierung von `StaticFancyText` angeschaut und denke da lässt sich wenig von wiederverwenden beim Ableiten. Also kann man sich das gleich selbst komplett neu implementieren, dann halt mit Default-Formatierung und einer `SetLabel()`-Methode.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Vielen Dank,

da muß ich mal noch etwas drüber nachdenken,
wenn ich das richtig verstehe ist mit
BlackJack hat geschrieben:komplett neu implementieren
gemeint die Klasse `StaticFancyText` mit allen Abhängigkeiten durch eine eigene zu ersetzen??
Zuletzt geändert von mathi am Donnerstag 26. August 2010, 14:15, insgesamt 2-mal geändert.
BlackJack

@mathi: Was heisst "mit allen Abhängigkeiten"? Die Klasse besteht ja nur aus einer `__init__()` die im Grunde fast nur aus dem besteht, was Du in Deiner `SetLabel()`-Methode auch noch einmal machst.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Jetzt habe ich es glaub ich kapiert (zumindest funktioniert es):

Code: Alles auswählen

class StaticFancyText(fa.StaticFancyText):
    """StaticFancyText with SetLabel function."""
    
    def __init__(self, window,id,label, *args, **kargs):
        args = list(args)
        kargs.setdefault('name', 'staticFancyText')
        if 'background' in kargs:
            background = kargs.pop('background')
        elif args:
            background = args.pop(0)
        else:
            background = wx.Brush(window.GetBackgroundColour(), wx.SOLID)
        label='<font weight="bold" size="11">%s</font>' % label
        bmp = fa.RenderToBitmap(label, background)
        wx.StaticBitmap.__init__(self, window, id, bmp, *args, **kargs)

        
    def SetLabel(self, label):
        label='<font weight="bold" size="11">'+label+'</font>'
        bmp = fa.RenderToBitmap(label,
                wx.Brush(self.GetBackgroundColour(), wx.SOLID))
        self.SetBitmap(bmp)
ntrunk
User
Beiträge: 83
Registriert: Sonntag 7. September 2008, 23:09
Wohnort: Buchen (Odenwald)

@mathi
- Leite deine Klasse direkt von wx.StaticBitmap ab. Dein Code funktioniert nur deshalb, weil fa.StaticFancyText (das du doch gar nicht mehr benötigst) selbst von wx.StaticBitmap abgeleitet ist.
- Du hast die default-Formatierung doppelt in deiner Klasse. Das ist 1. unschön und 2. musst du das bei Änderungen an zwei Stellen anpassen.

Gruß
Norbert
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

@ntrunk
Danke für die Aufklärung, ich habe die Hinweise eingearbeitet, jetzt sieht die Sache doch recht brauchbar aus.

Damit denke ich haben wir es gelöst... :D

Gruß Mathi
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Hallo,

ich habe noch ein Coding problem:

unter Eclipse funktioniert das Programm super,

aber starte ich es in Win. erhalte ich folgende Meldung:
File "C:\Python26\lib\site-packages\wx-2.8-msw-unicode\wx\lib\fancytext.py", line 349, in GetFullExtent
RenderToRenderer(str, renderer, enclose)
File "C:\Python26\lib\site-packages\wx-2.8-msw-unicode\wx\lib\fancytext.py", line 332, in RenderToRenderer
p.Parse(str, 1)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2074' in position 54: ordinal not in range(128)
Wie kann das sein, dass es unter Eclipse läuft und vor allem was ist der Fehler??

hier nochmal ein Prog. zum Testen:

http://paste.pocoo.org/show/2JTzY2wajyIcbtVQtwEB/

wäre super wenn Ihr nochmal helfen könntet...
Gruß Mathi
BlackJack

Der Fehler ist, dass das Argument serialisiertes XML sein muss, also Bytes und nicht vom Typ `unicode`. Keine Ahnung warum das in Eclipse funktioniert. Durch die Erfahrungen mit IDLE und Eclipse bin ich allerdings zu dem Schluss gekommen, dass man aus den beiden IDEs keine Python-Programme starten sollte.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

@BlackJack

Oje da wartet ja jetzt eine Menge Arbeit auf mich...aber vielen Dank für die Erklärung :-)
Die Geschichte mit Eclipse ärgert mich schon ein wenig, aber jetzt da ich es weiß...

@all
zur Erklärung:

um
zu erhalten, habe ich

Code: Alles auswählen

u'\u2265'
geschrieben, jetzt muß ich das in XML:
'&#x2265;'
schreiben, und das für jeden griech. Buchstaben, jedes Sonderzeichen etc....

Gruß Mathi
BlackJack

@mathi: Hättest Du das nicht einfach als UTF-8 kodieren können?
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

aber wie denn?
Ich habe die Kodierung doch über wx.SetDefaultPyEncoding("utf-8") gesetzt...
und mit

Code: Alles auswählen

label = label_.encode("UTF-8")
in meiner Klasse StaticFancyText gehts auch nicht :-(

@BlackJack
Kannst Du mir einen Tip geben, wie das funktionieren kann.
Ich wäre dankbar mir die Arbeit ersparen zu können.
Antworten