Text zeilenweise ausgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Unr3al
User
Beiträge: 4
Registriert: Dienstag 9. Mai 2006, 12:53

Hallo,

ich habe eine Datei, aus der ich Text in einem Label zeilenweise ausgeben will. Geschehen soll das Ganze nach dem man auf den Button "Nächste Zeile" gedrückt hat. Wenn das Dateiende erreicht ist, soll "Dateiende erreicht" ausgegeben werden.

Das habe ich bis jetzt hinbekommen:

Code: Alles auswählen

from Tkinter import *

def dateilesen():
    datei = open('text.txt','r')
    while 1:
        line = datei.readline()
        if not line:
            print "Ende der Datei erreicht"
            break
        ausgabe.configure(text=line),
        break
    datei.close()


fenster = Tk()
fenster.title('Test 4')
fenster.label = Label(master=fenster, text='Zeilenleser',
                      font=('Arial',16, 'bold underline'),fg='blue')
fenster.label.pack()

fenster.button = Button(master=fenster,text='Naechste Zeile',
                        font=('Arial',12,'bold'),command=dateilesen)
fenster.button.pack(side=RIGHT,padx=5)

ausgabe = Label(master=fenster,font=('Arial',12),
                fg='blue',bg='yellow',height='2', width='50', relief='sunken')
ausgabe.pack(padx='10',pady='10')

fenster.mainloop()
Das Problem dabei ist, dass momentan nur die erste Zeile ausgegeben wird. Mir ist bewusst, dass meine dateilesen()-Funktion wohl nicht richtig ist, finde aber keine Lösung. Außerdem würde ich gerne wissen, wie ich die Zeilen linksbündig ausgegeben bekommen. Für jede Hilfe bin ich im Voraus sehr dankbar.

Viele Grüße,
Unr3al
mr.hide
User
Beiträge: 108
Registriert: Montag 29. August 2005, 14:02

So weit ich das sehe, hast du ein break zuviel... in der while schleife
Grüße
Matthias

- Fluchen befreit von Kummer und Leid -
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

Das Hauptproblem ist, dass deine Methode dateilesen gar nicht weiß, welche Zeile die nächste sein soll. So wie ich deinen Code verstehe, soll auf einen Button gedrückt werden und dann soll die nächste Zeile ausgegeben werden. Dabei solltest du der Methode eben sagen welches die nächste Zeile ist. Ich würde das komplett anders lösen. Ich würde die Methode nur 1x aufrufen und dann wenn möglich alle Zeilen (natürlich ist dies abhängig von der Dateigröße) in eine Liste schreiben und dann in dieser Liste nur "weiterwandern" für die Ausgabe, etwa so:

Code: Alles auswählen

from Tkinter import *

dateiinhalt = []
CurLine = 0
MaxLine = 0

def dateilesen():
    datei = open('text.txt','r')
    while 1:
        dateiinhalt.Append(datei.readline())
        MaxLine += 1
        if not line:
            print "Ende der Datei erreicht"
            break
    datei.close()

def NextRowOut():
    CurLine += 1
    if(CurLine < MaxLine):         
        ausgabe.configure(text=dateiinhalt[CurLine])
    else print "keine weitern Zeilen"

dateilesen()
fenster = Tk()
fenster.title('Test 4')
fenster.label = Label(master=fenster, text='Zeilenleser',
                      font=('Arial',16, 'bold underline'),fg='blue')
fenster.label.pack()

fenster.button = Button(master=fenster,text='Naechste Zeile',
                        font=('Arial',12,'bold'),command=NextRowOut)
fenster.button.pack(side=RIGHT,padx=5)

ausgabe = Label(master=fenster,font=('Arial',12),
                fg='blue',bg='yellow',height='2', width='50', relief='sunken')
ausgabe.pack(padx='10',pady='10')

fenster.mainloop()
PS: ungetesteter Quelltext
Unr3al
User
Beiträge: 4
Registriert: Dienstag 9. Mai 2006, 12:53

Erst einmal vielen Dank für Hilfe. Der Interpreter spuckt ein Paar Fehler aus, mit manchen werde ich nicht fertig und zwar:
UnboundLocalError: local variable 'MaxLine' referenced before assignment
UnboundLocalError: local variable 'CurLine' referenced before assignment

Wie kann ich sie umgehen?

Viele Grüße,
Unr3al
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi Unr3al!

Bitte erwarte nicht zu viel. Ich wollte nur eine kleine Übung machen, damit ich nicht alles vergesse, bevor ich es zum ersten Mal brauche. Da ist mir deine Aufgabenstellung gerade recht gekommen. Dein Beispiel war mit Tkinter meines ist mit wxPython. Und als Anfänger gleich mit mehreren GUI-Toolkits konfrontiert zu werden ist auch nicht toll. Sorry!

Wenn du mit meinem Beispiel nicht zurecht kommst --> einfach ignorieren. Es gibt auch andere Möglichkeiten um dein Problem zu lösen. Man muss nicht Yield nehmen.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
Liest Zeile für Zeile
"""

import wx

class MyFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Zeilenleser", size = (300, 200))
        
        panel = wx.Panel(self)
        self.box = wx.BoxSizer(wx.VERTICAL)

        self.label = wx.StaticText(panel, -1, "Seavas")
        self.label.SetBackgroundColour("white")
        self.box.Add(self.label, 1, wx.ALL | wx.EXPAND, 6)
        
        self.button = wx.Button(panel, -1, u"Nächste Zeile")
        self.box.Add(self.button, 0, wx.ALL | wx.EXPAND, 3)
        self.button.Bind(wx.EVT_BUTTON, self.on_button)
        
        panel.SetSizer(self.box)
        
        self.lines = self.read_lines()
        self.label.SetLabel(self.lines.next())


    def read_lines(self):
        """
        Liest die Datei Zeilenweise aus.
        """
        
        f = file("hallo.txt", "rU")
        
        for line in f:
            yield line

        f.close()


    def on_button(self, event):
        """
        Schreibt den Text in das Label
        """
        
        try:
            line = self.lines.next()
        except StopIteration:
            line = "Fertig!!!\n"
            self.button.Enable(False)
        
        self.label.SetLabel(
            self.label.GetLabel() + line
        )
        
        self.box.Layout()


app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Unr3al
User
Beiträge: 4
Registriert: Dienstag 9. Mai 2006, 12:53

Hallo gerold,

ich danke dir, da ich aber wxPython noch gar nicht kenne, bleibe ich erst einmal bei Tkinter.

Ich habe den Code jetzt bearbeitet und es funktioniert nur noch eine Sache nicht, und zwar die Liste dateiinhalt hat in der Funktion dateilesen() richtigen Inhalt, in der Funktion NextRowOut() ist die Liste leer. Ich vermute, dass es irgendwas mit Sichtbarkeiten zu tun hat, kann den Fehler aber trotzdem nicht finden, vielleicht kann jemand mit mehr Erfahrung mir helfen.

Hier ist noch einmal der Code der beide Funktionen:

Code: Alles auswählen

from Tkinter import *

dateiinhalt = []
CurLine = 0
MaxLine = 0

def dateilesen():
    global MaxLine
    datei = open('test.txt','r')
    while 1:
        dateiinhalt = datei.readline()
        #dateiinhalt.append(datei.readline())
        MaxLine += 1
        print MaxLine
        print dateiinhalt
        if not dateiinhalt:
            break
    datei.close()

def NextRowOut():
    global CurLine
    CurLine += 1
    print dateiinhalt
    if(CurLine < MaxLine):         
        ausgabe.configure(text=dateiinhalt[CurLine])
    else: ausgabe.configure(text="Ende der Datei erreicht")

dateilesen()
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

versuchs mal so:

Code: Alles auswählen

dateiinhalt = []
CurLine = 0
MaxLine = 0

def dateilesen():
    global MaxLine
    datei = open('test.txt','r')
    inhalt = []
    while 1:
        inhalt.append(datei.readline())
        MaxLine += 1
        print MaxLine
        if not inhalt[MaxLine-1]:
            break
    datei.close()
    return inhalt

def NextRowOut():
    global CurLine
    CurLine += 1
    print dateiinhalt[CurLine]
    if(CurLine < MaxLine):         
        ausgabe.configure(text=dateiinhalt[CurLine])
    else: ausgabe.configure(text="Ende der Datei erreicht")

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

Unr3al hat geschrieben:Hallo gerold, ich danke dir, da ich aber wxPython noch gar nicht kenne, bleibe ich erst einmal bei Tkinter.
Hi Unr3al!

Kein Problem. Das habe ich mir schon gedacht. Hier noch mein Tkinter-Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import Tkinter as tk

class MeinFenster(tk.Tk):
    
    def __init__(self):
        """
        Baut das Fenster auf und zeigt es an.
        """
        
        # Fenster initialisieren
        tk.Tk.__init__(self)
        
        # Fenstertitel
        self.title("Test 4")
        
        # Überschrift
        self.label = tk.Label(
            self, text = 'Zeilenleser', 
            font = ('Arial',16, 'bold underline'), fg = 'blue'
        )        
        self.label.pack()
        
        # Button
        self.button = tk.Button(
            master = self, text = 'Naechste Zeile',
            font = ('Arial', 12, 'bold'), command = self.read_line
        )
        self.button.pack(side = tk.RIGHT, padx = 5)
        
        # Ausgabefeld
        self.ausgabe = tk.Label(
            self, font = ('Arial',12), fg='blue', bg = 'yellow', 
            height = '2', width = '50', relief = 'sunken'
        )
        self.ausgabe.pack(padx = '10', pady = '10')
        
        # Datei komplett in Liste einlesen lassen
        self.read_file()


    def read_file(self):
        """
        Datei komplett einlesen
        """

        f = file("hallo.txt", "rU")
        self.lines = f.readlines()
        f.close()


    def read_line(self):
        """
        Bei jedem Aufruf dieser Methode wird der erste Eintrag aus der
        Liste entfernt und in das Ausgabe-Label geschrieben.
        """
        
        if len(self.lines) > 0:
            line = self.lines.pop(0)
        else:
            line = "Ende der Datei erreicht\n"
            
        self.ausgabe.configure(text = line)


if __name__ == "__main__":
    mein_fenster = MeinFenster()
    tk.mainloop()
Der Nachteil dieses Code ist, dass das Textfile komplett eingelesen und im Speicher gehalten wird. Das ist bei so einem Beispiel natürlich kein Problem, aber wenn die Textdatei groß ist, dann wird der Speicher komplett zugemüllt. Dann würde ich eine Methode wählen, die die Datei offen hält und immer nur bei Bedarf eine einzelne Zeile ausliest.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Unr3al
User
Beiträge: 4
Registriert: Dienstag 9. Mai 2006, 12:53

Hallo gerold,

vielen Dank, dein Code funktioniert einwandfrei.

Viele Grüße,
Unr3al
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Unr3al hat geschrieben:dein Code funktioniert einwandfrei.
Hi Unr3al!

Das war mir klar. :P ;-)

Die Frage ist -- Verstehst du den Code und kannst du daraus etwas lernen?

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten