Seite 1 von 1

Textformatierungsprogramm hat eine unheimliche Endlosschleife

Verfasst: Montag 3. Oktober 2016, 14:12
von Anagkai
Ich möchte mit pygame png-Bilder inklusive formatiertem Text aus anderen png-Bildern und nicht formatiertem Text erstellen. Damit bin ich fast fertig, allerdings habe ich noch Probleme mit der Funktion zum Formatieren.
Die Funktion soll mit einer gegeben Breite die Positionen der Wörter so berechnen, dass sich eine Blocksatzformatierung ergibt. Allerdings hat die Funktion eine Endlosschleife, deren Existenz ich mir nicht erklären kann. Ich habe bei meinen Untersuchungen herausgefunden, dass die Variable n, die für das Ende der while-Schleife ja maßgeblich ist, immer wieder 0 wird. Außerdem habe ich print-Statements eingebaut um den Verlauf zu verfolgen, dabei wurde ein print-Statement, das in der Funktion ÜBER der while-Schleife ist, regelmäßig wieder aufgerufen, NACHDEM schon Code in der while-Schleife ausgeführt wurde. Auch das ist mir unerklärlich.
Das ist die Funktion, dabei ist textblock[1] der zu formatierende String.

Code: Alles auswählen

    def formattextblock(self, textblock, y0, size):
        x = self.vtext[3]
        y = y0
        n = 0
        w = 0
        shortstring = ""
        longstring = ""
        
        textfont = pygame.font.SysFont("georgia", size)   
        wordlist = textblock[1].split(" ")
        lines = []
        
        length = len(wordlist)
        while n < length:
            longstring = shortstring + wordlist[n]
            testlong = textfont.render(longstring, True, (0,0,0))
            if (testlong.get_width() + self.vtext[8]*(w-1) <= self.vtext[2]) and n < length - 1:
                shortstring = longstring
                w += 1
                n += 1
            else:
                if n == length - 1:
                    w += 1
                testshort = textfont.render(shortstring, True, (0,0,0))
                if w > 1:
                    actualinter = (self.vtext[2]-testshort.get_width())/(w-1)
                else:
                    actualinter = 0
                line = []
                nstart = n - w 
                while nstart < n:
                    word = [x, y, wordlist[nstart]]
                    line.append(word)
                    testword = textfont.render(wordlist[nstart], True, (0,0,0))
                    x += (testword.get_width() + actualinter)
                    nstart += 1
                lines.append(line)
                x = self.vtext[3]
                if n < length - 1:
                    y += (size + self.vtext[5])
                else: 
                    y += (size + self.vtext[9])
                longstring = ""
                shortstring = ""
                w = 0
                
        return lines, y                   
Vielen Dank schon mal für jede Hilfe.

Re: Textformatierungsprogramm hat eine unheimliche Endlosschleife

Verfasst: Montag 3. Oktober 2016, 15:04
von BlackJack
@Anagkai: Schreib mal ein Beispiel das man tatsächlich ausprobieren kann. Denn das was Du beschreibst kann nicht passieren. `n` kann innerhalb der Schleife nicht wieder 0 werden und etwas davor kann auch nicht ausgeführt werden. Das könnte nur passieren wenn die Methode irgendwo rekursiv aufgerufen wird. Dann ist das natürlich ein anderes `n` aber das ist dann natürlich 0 und es wird auch wieder der Code vor der Schleife ausgeführt.

Das `vtext`-Attribut mit den vielen magischen Indexzahlen hilft übrigens nicht unbedingt um das ganze lesbar und verständlich zu machen.

Re: Textformatierungsprogramm hat eine unheimliche Endlosschleife

Verfasst: Montag 3. Oktober 2016, 15:21
von Anagkai

Code: Alles auswählen

import pygame
from pygame.locals import *

pygame.init()

def formattextblock(textblock, y0, size):
    x = 250
    y = y0
    n = 0
    w = 0
    shortstring = ""
    longstring = ""
    
    textfont = pygame.font.SysFont("georgia", size)   
    wordlist = textblock.split(" ")
    lines = []
    
    length = len(wordlist)
    while n < length:
        print([n,w])
        longstring = shortstring + wordlist[n]
        testlong = textfont.render(longstring, True, (0,0,0))
        if(testlong.get_width()+20*(w-1) <= 2450 and n < length - 1):
            shortstring = longstring
            w += 1
            n += 1
        else:
            if n == length - 1:
                w += 1
            testshort = textfont.render(shortstring, True, (0,0,0))
            if w > 1:
                actualinter = (2450-testshort.get_width())/(w-1)
            else:
                actualinter = 0
            line = []
            nstart = n - w 
            while nstart < n:
                word = [x, y, wordlist[nstart]]
                line.append(word)
                testword = textfont.render(wordlist[nstart], True, (0,0,0))
                x += (testword.get_width() + actualinter)
                nstart += 1
            lines.append(line)
            x = 250
            if n < length - 1:
                y += (size + 20)
            else: 
                y += (size + 30)
            longstring = ""
            shortstring = ""
            w = 0
            
    return lines, y                   
    
formattextblock("This text for testing purposes is multiple lines long. This text for testing purposes is multiple lines long", 3000, 100)
Hier die Standalone-Version. Auch die produziert eine Endlosschleife.

Re: Textformatierungsprogramm hat eine unheimliche Endlosschleife

Verfasst: Montag 3. Oktober 2016, 16:17
von BlackJack
@Anagkai: Da wird `n` aber nicht 0. Es geht bis 17, also bis zum letzten Index weil es 18 Worte sind. Nur im ersten ``if``-Zweig wird n hochgezählt. Jetzt schau Dir mal an wann der ausgeführt wird. Also was dort die Bedingung an `n` ist, und was die Bedingung ist um die Schleife zu verlassen.

Re: Textformatierungsprogramm hat eine unheimliche Endlosschleife

Verfasst: Montag 3. Oktober 2016, 16:26
von Anagkai
Es muss natürlich

Code: Alles auswählen

while n < len(wordlist) - 1
heißen. Da war ich auch schon drauf gekommen, allerdings hat es nichts geholfen, deshalb habe ich es wieder geändert. Mir ist aber inzischen aufgefallen, dass zusätzlich in der übergeordneten Funktion eine Endlosschleife war, weil ich beim Iterieren über die Textblöcke das n+=1 vergessen habe.

Allerdings wird jetzt nur eine Zeile Text richtig formatiert und der Rest fehlt.

Re: Textformatierungsprogramm hat eine unheimliche Endlosschleife

Verfasst: Montag 3. Oktober 2016, 16:38
von BlackJack
@Anagkai: Vielleicht hilft es ja die Funktion anders aufzubauen. Für meinen Geschmack macht die zu viel und ist zu unübersichtlich. Formuliere den Algorithmus in Worten, dann hast gute Funktionsnamen für die einzelnen Schritte.

Re: Textformatierungsprogramm hat eine unheimliche Endlosschleife

Verfasst: Dienstag 4. Oktober 2016, 21:46
von Sirius3
@Anagkai: die vielen Bedingungen und Zweige machen das Lesen und Verstehen sehr schwer. Du solltest das Problem in mehrere Teilprobleme zerlegen. Z.B. Berechnen der Wortbreite, und Aufteilen der Wörter auf eine Zeile und das Sammeln der Wörter bis eine Zeile voll ist:

Code: Alles auswählen

WIDTH = 2450
MIN_SPACE_WIDTH = 20

def create_line(line, y):
    space_width = (WIDTH - sum(w for w,_ in line)) / (len(line) - 1) if len(line) > 1 else 0
    result = []
    x = 250
    for word_width, word in line:
        line.append([x, y, word])
        x += width + space_width
    return result

def formattextblock(textblock, y0, size):
    y = y0
    textfont = pygame.font.SysFont("georgia", size)
    words = ((textfont.render(w, True, (0,0,0)).get_width(), w)
        for w in textblock.split())
    lines = []
    current_line = []
    current_line_width = 0
    for word_width, word in words:
        if current_line_width + word_width > WIDTH:
            lines.append(create_line(current_line, y))
            current_line = []
            current_line_width = 0
            y += size + 20
        current_line.append((width, word_word))
        current_line_width += width + MIN_SPACE_WIDTH
    lines.append(create_line(current_line, y))
    return lines, y + size + 30