Text Widget zeilenweise auslesen

Fragen zu Tkinter.
Antworten
Graf_Dracula
User
Beiträge: 20
Registriert: Donnerstag 17. Februar 2011, 16:05

Hallöle,

ich habe ein Text-Widget, wo ich allerdings vorher nicht weiß, wie viele Eingaben (Zeilen) der user befüllen wird.

All diese Zeilen muss ich in eine Liste einlesen ... nur wie ???

Aus dem hier:

Code: Alles auswählen

textWidget =
|-------------------------|
| Text1                   |
| Text2                   |      
| Text3                   |     
|-------------------------|
... muss also das hier werden:

Code: Alles auswählen

bla = ['Text1', 'Text2', 'Text3']
Ich dachte erst, dass ich das ganz einfach so machen könnte, geht aber ned:

Code: Alles auswählen

i = 0
for (line in textWidget):
    bla[i] = line
Mir ist schon klar, dass ich mittels textWidget.get('1.0', '1.end') die Erste Zeile auslesen kann, da ich aber keine Ahnung habe, wie ich die Anzahl der Zeilen in dem Widget auslesen kann, wüsste ich im Moment nicht, wie ich das anstellen soll, dass der bei einer leeren Zeile dann aufhört.

.
Graf_Dracula
User
Beiträge: 20
Registriert: Donnerstag 17. Februar 2011, 16:05

Also ich habs jetzt zwar hinbekommen, aber schön sieht das ganze irgendwie nicht aus ... das geht doch bestimmt auch einfacher - oder?

Code: Alles auswählen

    bla= []
    i = 0
    iStart = str(i+1) + ".0"
    iEnd   = str(i+1) + ".end"
    line = textWidget.get(iStart, iEnd)
    while not (line == ""):
        bla.append(line)
        i += 1
        iStart = str(i+1) + ".0"
        iEnd   = str(i+1) + ".end"
        line = textWidget.get(iStart, iEnd)
BlackJack

@Graf_Dracula: Also grundsätzlich kann man solche Schleifen kürzer formulieren wenn man eine Endlosschleife daraus macht, die man dann mit ``break`` verlässt, wenn die Abbruchbedingung erfüllt ist. Dann kann man die Code-Wiederholung vor der Schleife nämlich vermeiden. Die verstösst nämlich gegen das DRY-Prinzip ("Don't Repeat Yourself").

Du könntest auch einfach den kompletten Text auslesen und dann an den Zeilenenden aufteilen. `str`- beziehungsweise `unicode`-Exemplare haben extra eine Methode dafür.
Benutzeravatar
daemonTutorials
User
Beiträge: 171
Registriert: Sonntag 6. Februar 2011, 12:06
Kontaktdaten:

Code: Alles auswählen

    bla= []
    i = 0
    while 1:
        iStart = str(i+1) + ".0"
        iEnd   = str(i+1) + ".end"
        bla.append(textWidget.get(iStart, iEnd))
        i += 1
        if textWidget.get(iStart, iEnd) = "":
            break
        else:
            continue
        
Das wäre meiner Meinung eleganter!
LG Maik
BlackJack

@daemonTutorials: ``while 1`` ist unelegant weil man ja eigentlich ``while True`` meint. Dass die Zeile aus dem Text-Widget zweimal ausgelesen wird ist auch nicht so schön und der ``else``-Zweig ist überflüssig. Immer eins zu `i` addieren für den Zugriff auf die Zeile ist auch nicht schön weil man ja `i` selbst nie braucht, sondern *immer* ``i + 1``. Da könnte man auch gleich mit einem um eins höheren `i` beginnen. Die Laufvariable `i` von der Schleife zu trennen und das alles von Hand zu machen ist grundsätzlich auch nicht elegant.

Folgender (ungetesteter) Code macht nicht ganz das selbe, denn die Leerzeile am Ende auch an die Liste anzuhängen erscheint mir überflüssig:

Code: Alles auswählen

    lines = list()
    for i in itertools.count(1):
        line = text_widget.get('%d.0' % count, '%d.end' % count)
        if not line:
            break
        lines.append(line)
Graf_Dracula
User
Beiträge: 20
Registriert: Donnerstag 17. Februar 2011, 16:05

Das Problem ist ja halt, dass ich aus einem TextWidget eben nicht Zeilenweise auslesen kann, sondern nur über diesen Umweg der Zeilen und Spalten (1.0 bis 1.end)

Wenn jemand eine Möglichkeit kennt, direkt eine komplette Zeile des TextWidgets auszulesen ... nur her damit ...

Um die leere Zeile am Ende nicht in meiner bla-Variable zu haben, habe ich die Abbruchbedingung jetzt erst mal hochgezogen:

Code: Alles auswählen

    bla= []
    i = 0
    while 1:
        iStart = str(i+1) + ".0"
        iEnd   = str(i+1) + ".end"
        if textWidget.get(iStart, iEnd) = "": break
        bla.append(textWidget.get(iStart, iEnd))
        i += 1
Funktionieren tuts so, nur wird halt immer noch, wie 'BlackJack' schon anmerkte das Widget 2 mal abgefragt ...


.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Warum lest ihr nicht einfach das Textwidget von 1.0 bis "end" aus und splittet dann den Text an "\n" in die einzelnen Zeilen.
Der Index im Textwidget richtet sich ja auch danach. Ist schließlich "Zeile.Spalte", wobei die Zeilen anhand "\n" gezählt werden, ist dieses nicht vorhanden gilt es immer noch als dieselbe Zeile, auch wenn durch eine "wrap"-Konfig also zB. ein automatischen Zeilenumbruch dies anders aussieht.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@Xynon1: Das habe ich weiter oben ja auch schon vorgeschlagen.

@Graf_Dracula: Wie man das doppelte Abfragen vermeidet (und das ``while 1`` und das selbst verwalten von `i`), habe ich doch im letzten Beitrag gezeigt.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@BlackJack
Oha, stimmt sry, aber das ist ziemlich Untergegangen und was sprach gleich nochmal dagegen es so zumachen ?
Ist doch nun wirklich das einfachste und effizienteste.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Antworten