Home-Produkte-Testarea-Kontakt-Datenschutz-Aktualisiert: 14-Jul-2013
< Voriger Tag   Nächster Tag >

Sonntag, 14. Juli 2013

SWB: Textausgabe mit Zeilenumbruch

Für die Textausgabe mit Zeilenumbruch wird lxml zum Extrahieren des Textes benutzt. Zur Berechnung der Positionen der Wörter und ihrer Ausgabe kommt im zweiten Schritt die Text-Widget-Klasse hinzu.

HTML parsen -> Text ausgeben

swb_03_show_text zeigt nur den Text des HTML-Dokuments an.

Als HTML-Parser wird lxml benutzt. Das etree.HTMLParser(remove_blank_text=True) entfernt den nicht benötigten Leerraum zwischen den Tags.

r = requests.get(url, headers={'user-agent': self.USER_AGENT})
self.html_sourcecode = r.text

html_parser = etree.HTMLParser(remove_blank_text=True)
html_tree   = etree.fromstring(self.html_sourcecode, html_parser)
text        = etree.tostring(html_tree, encoding='unicode', method='text')

self.text_box.set_text(text)
self.text_box.layout(self.g)
Download: Revision 117
svn checkout --revision 117 https://svn.sven-drieling.de/repos/trunk/playground/webbrowser/ yd-playground-webbrowser-117

Text mit Zeilenumbruch

swb_04_text_linebreak zeigt den Text mit Zeilenumbruch an.

Statt einer for-Schleife benutze ich den Iterator direkt und hole das jeweils nächste Wort mit word = next(wordsIter), so ist der Quelltext linear in 1. Wort, nachfolgende Wörter bis Zeile gefüllt und Zeilenende eingeteilt.

def layout(self, g):
    self.text_width  = 0
    self.text_height = 0

    wordsIter = iter(self.words)

    try:
        word = next(wordsIter)
        (word_width, word_height) = g.font.size(word)

        while True:
            # First word in line
            line_width  = word_width
            line_height = word_height


            # Fill line with following words
            word = next(wordsIter)
            (word_width, word_height) = g.font.size(word)

            while line_width + self.WORD_GAP + word_width < self.width:
                line_width  = line_width + self.WORD_GAP + word_width
                line_height = max(line_height, word_height)

                word = next(wordsIter)
                (word_width, word_height) = g.font.size(word)


            # Next line
            self.text_width  = max(self.text_width, line_width)
            self.text_height = self.text_height + line_height + self.LINE_GAP


    except StopIteration:
        # Last line
        self.text_width  = max(self.text_width, line_width)
        self.text_height = self.text_height + line_height
Download: Revision 119
svn checkout --revision 119 https://svn.sven-drieling.de/repos/trunk/playground/webbrowser/ yd-playground-webbrowser-119

Text-Widget

Zu Vereinfachung werden die vielen unterschiedlichen HTML-Elemente im Rendertree auf eine Handvoll Widgets reduziert (Widget als grafisch dargestelltes Element zur deutlicheren Unterscheidung von den nicht sichtbaren Nodes im HTML-Baum). Für viele Texte reichen so TextWidget mit dem Textteilen, AttributeWidget zum Setzen der Schrift und Farben und VSpaceWidget für den vertikalen Leerraum aus. Aus:

<h1>Überschrift</h1> 

<p>Paragraph.</p>

wird:

AttributeWidget(font='DejaVuSans.ttf', size=24)
TextWidget(text='Überschrift')
VSpace(width=0, height=8)
AttributeWidget(font='DejaVuSerif.ttf', size=16)
TextWidget(text='Paragraph')

Der erste Schritt dahin ist das swb_05_text_widget.

class TextWidget(Widget):
    def __init__(self, text = ''):
        super().__init__()
        self.text = text

    def calculate_size(self, g):
        (self.width, self.height) = g.font.size(self.text)

    def draw(self, g, left, top):
        text_surface = g.font.render(self.text, True, g.fg, g.bg)
        g.surface.blit(text_surface, (self.left + left, self.top + top))

Damit bekommt in der TextBox auch die Einteilung in layout() und draw() mehr Sinn. layout() berechnet die Position und Größe der Text-Widgets und draw() braucht diese nun nur noch auszugeben, ohne selbst Zeilenumbrüche zu berechnen.

def layout(self, g):
    self.text_width  = 0
    self.text_height = 0

    widgetsIter = iter(self.widgets)

    try:
        widget = next(widgetsIter)
        widget.calculate_size(g)

        while True:
            # First widget in line
            widget.left = 0
            widget.top  = self.text_height

            line_width  = widget.width
            line_height = widget.height


            # Fill line with following widgets
            widget = next(widgetsIter)
            widget.calculate_size(g)
            widget.left = self.left + line_width
            widget.top  = self.text_height

            while line_width + self.WORD_GAP + widget.width < self.width:
                line_width  = line_width + self.WORD_GAP + widget.width
                line_height = max(line_height, widget.height)

                widget = next(widgetsIter)
                widget.calculate_size(g)
                widget.left = self.left + line_width
                widget.top  = self.text_height


            # Next line
            self.text_width  = max(self.text_width, line_width)
            self.text_height = self.text_height + line_height + self.LINE_GAP


    except StopIteration:
        # Last line
        self.text_width  = max(self.text_width, line_width)
        self.text_height = self.text_height + line_height
def draw(self, g):
    g.surface.fill((255, 255, 255))

    for widget in self.widgets:
        widget.draw(g, self.left - self.scroll_left, self.top - self.scroll_top)
Download: Revision 121
svn checkout --revision 121 https://svn.sven-drieling.de/repos/trunk/playground/webbrowser/ yd-playground-webbrowser-121

[Direktlink]

< Voriger Tag   Nächster Tag >

  RSS V0.91

<Juli 2013 >
01020304050607
08091011121314
15161718192021
22232425262728
293031    

Home-Produkte-Testarea-Kontakt-Datenschutz-Aktualisiert: 14-Jul-2013
(C) 2000-2018 by Sven Drieling