Wie Datei lesen und Texte in Eingabefelder schreiben?

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
marlon_germany
User
Beiträge: 33
Registriert: Samstag 30. April 2022, 23:32

Hallo Allerseits,

Die Idee dahinter ist, dass ich ein Programm mit leeren Text Feldern habe, wo ich Text hinein schreibe. Dann möchte ich per Knopfdruck den Text automatisch zwischen speichern/als Entwurf speichern (in eine Text Datei). Wenn ich nun das Programm schließe und erneut öffne, möchte ich automatisch per Knopfdruck den Text vom letzten Mal in die Eingabefelder reinschreiben lassen/reinladen lassen.

PS: am besten wäre natürlich noch die Option, Dass der Text nicht mehr automatisch in eine festgelegte Datei gespeichert wird, sondern dass man selber über einen („Speichern unter“ Dialog) selbst entscheiden kann, wo und in welche Datei der Text gespeichert werden soll.

Bisher habe ich das Programm soweit gebracht, dass ich den Text im Eingabefeld automatisch in einen Word-Datei speichern lasse. Es gibt Momente da möchte ich dann aber vielleicht einfach schnell das Programm schließen können, um dann beim wieder öffnen an der gleichen Stelle weiterzuschreiben.

Könnt ihr mir bitte zeigen, wie der komplette Code aussehen muss, damit das Programm die eingegebenen Texte in Textfeld 1 und Textfeld 2 automatisch als Entwurf speichert? Also wenn ich auf "Entwurf speichern" drücke sollen die eingegebenen Texte in eine Text oder Word Datei gespeichert werden und wenn ich auf "Entwurf laden" drücke, kann ich den Text da weiterschreiben, wo ich zuletzt aufgehört hatte.

Hier ist der bisherige Code:

Code: Alles auswählen

from pathlib import Path

import PySimpleGUI as sg
# this one long import has the effect of making the code more compact as there is no 'sg.' prefix required for Elements
from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, Check, Button, B, Btn, ButtonMenu, Canvas, Column, Col, Combo, Frame, Graph, Image, InputText, Input, In, Listbox, LBox,  Menu, Multiline, ML, MLine, OptionMenu, Output, Pane, ProgressBar,  Radio, Slider, Spin, StatusBar, Tab, TabGroup, Table, Text, Txt, T, Tree, TreeData,  VerticalSeparator, Window, Sizer

from docxtpl import DocxTemplate

document_path = Path(__file__).parent / "my_text_file.docx"
doc = DocxTemplate(document_path)

col1 = Column([[Frame('Text Field 1:', [[Column([[Multiline( key='text1', size=(15,20)),]],size=(150,400))]])]], pad=(0,0))

col2 = Column([[Frame('Text Field 2:', [[Column([[Multiline( key='text2', size=(15,20)),]],size=(150,400))]])]], pad=(0,0))




layout = [ [col1, col2 ],
           [sg.Button("Save Draft"), sg.Button("Load Draft")],
           [sg.Button("Export Text to File"), sg.Exit()],

           ]
            

window = sg.Window("Text Editor", layout, element_justification="right")

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == "Exit":
        break
    if event == "Export Text to File":

        # Render the template, save new word document & inform user
        doc.render(values)
        output_path = Path(__file__).parent / "my_text_file2.docx"
        doc.save(output_path)
        sg.popup("File Saved!", f"Datei Speicherort: {output_path}")

window.close()
Liebe Grüße Marlon
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Es ist wichtig, ein Programm zu strukturieren, in dem man Funktionen definiert. Es sollte nicht zu viel in einer Zeile stehen, weil man das dann nicht mehr lesen kann.
Das `DocxTemplate` sollte dann erzeugt werden, wenn es auch gebraucht wird.
Für einen „Speichern unter“-Dialog gibt es sg.FileSaveAs.

Code: Alles auswählen

from pathlib import Path
import PySimpleGUI as sg
from docxtpl import DocxTemplate

DOCUMENT_TEMPLATE = Path(__file__).parent / "my_text_file.docx"

def generate_layout():
    col1 = sg.Column([
        [
            sg.Frame('Text Field 1:', [
                [
                    sg.Column([
                        [
                            sg.Multiline(key='text1', size=(15,20)),
                        ]
                    ], size=(150,400))
                ]
            ])
        ]
    ], pad=(0,0))

    col2 = sg.Column([
        [
            sg.Frame('Text Field 2:', [
                [
                    sg.Column([
                        [
                            sg.Multiline(key='text2', size=(15,20)),
                        ]
                    ], size=(150,400))
                ]
            ])
        ]
    ], pad=(0,0))

    return [
        [col1, col2],
        [sg.Button("Save Draft"), sg.Button("Load Draft")],
        [sg.FileSaveAs("Export Text to File2", key='export_filename', enable_events=True), sg.Exit()],
    ]


def save_doc(values):
    output_path = values.pop("export_filename")
    doc = DocxTemplate(DOCUMENT_TEMPLATE)
    # Render the template, save new word document & inform user
    doc.render(values)
    doc.save(output_path)
    sg.popup("File Saved!", f"Datei Speicherort: {output_path}")


def main():
    layout = generate_layout()
    window = sg.Window("Text Editor", layout, element_justification="right")

    while True:
        event, values = window.read()
        print(event,values)
        if event == sg.WIN_CLOSED or event == "Exit":
            break
        if event == "export_filename":
            save_doc(values)
    window.close()


if __name__ == "__main__":
    main()
Du kannst ja bereits DOCX-Dateien schreiben, das Prinzip ist Dir also klar. Für das Zwischenspeichern würde ich json.dump/json.load empfehlen, weil damit die Struktur von `values` erhaltenbleibt.
marlon_germany
User
Beiträge: 33
Registriert: Samstag 30. April 2022, 23:32

Vielen herzlichen Dank für deine Antwort und die ganzen Tipps Sirius3 :wink:
Die json.dump Methode kannte ich noch nicht, obwohl ich mir das Python-Lernen Ebook gekauft habe, konnte ich dort nichts darüber finden.
Das hätte noch sehr lange dauern können bis auf den Weg gekommen wäre. Hatte bereits viel aber vergeblich nach einer Lösung gesucht.

Ich beschäftige mich jetzt erstmal mit "json" und berichte, wenn ich es hoffentlich bald geschafft habe.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Übrigens, anstatt Path(__file__).parent / "foo.docx" kann man auch schreiben: Path(__file__).with_name("foo.docx"). Ist somit vielleicht ein bisschen verständlicher.
marlon_germany
User
Beiträge: 33
Registriert: Samstag 30. April 2022, 23:32

Ich glaube ich brauche bitte nochmal Eure Hilfe. Ich habe es zwar geschafft Daten in eine JSON Datei per json.dump zu speichern (Beispiel):

Code: Alles auswählen

import json
k2 = {}
k2['api'] = "api_key=" + input("enter key")

with open("sample.json", "w") as outfile:
    json.dump(k2, outfile, indent=4)
print("success")
und auch die Daten wieder auszulesen über json.load:

Code: Alles auswählen

import json
#File I/O Open function for read data from JSON File
with open('C:/Users\-/Desktop/JSON/sample.json') as file_object:
        # store file data in object
        data = json.load(file_object)
print(data)
,sodass ein Text über „print“ angezeigt wird.

Aber wie ist es möglich, den Textinhalt der .json-Datei (oder gerne auch alternativ .txt-Datei) in das Input Feld von einem sg.Multiline oder sg.Text Bereich zu laden? Also das was eigentlich über print in der Konsole als Text ausgegeben wird, stattdessen in der GUI im gewünschten Input-Feld angezeigt wird.

PS: ich habe übrigens 2 Bücher zu Python gekauft und eine Woche zahlreiche Stunden nach der Lösung gesucht, wie so ein Code aussehen könnte (Google+YouTube)…aber leider ohne Erfolg.

(Ich habe Begriffe wie „Insert file output to input“, „File content to input“, „txt file to sg.text“, „txt file to sg.multiline, „txt file to textbox“, „file content to text field“, „insert file content to input field“, „write text from file to input field“, „append file content tousw. bei Google ausprobiert und zahlreiche Foren und Videos durchschaut…aber nichts gefunden)

Und mithilfe von Tkinter habe ich bereits herausgefunden, wie man Dateiinhalte aus Text-Dateien liest und in eine Textbox hineinlädt.

Da ich aber gerne verstehen möchte, wie diese paar Zeilen an Code aussehen, ohne Tkinter einzubinden, würde ich mich sehr freuen, wenn mir jemand dafür einen Beispielcode zeigt.

Hier mein funktionierender Code um per Knopdruck eine JSON-Datei auszulesen und in der Konsole azeigen zu lassen:

Code: Alles auswählen

import PySimpleGUI as sg
from pathlib import Path


sg.theme('LightBlue 1')
layout = [
          [sg.Button('Print text from file'), sg.Button('Close')]
          ]

window = sg.Window('Print text from file)', layout, [200,400])

while True:
    event, values = window.read()
    print('event:', event)
    print('values:', values)
    
    if event == sg.WIN_CLOSED or event == 'Close':
        break
        
    if event == 'Print text from file':
        
        json = Path('sample.json').read_text()
        json = json.replace('\n', '')
        print (json)



window.close()




Weiter komme ich aber leider nicht.

PS: Diese folgenden Codebeispiele sind das Resultat von dem was ich im Internet gefunden habe, womit ich versucht habe, mein Anliegen zu lösen:

Beispiel 1:

Code: Alles auswählen

if event == 'Send message':
        input_text = values['-myinput-']
        response = "some response for " + input_text
        #response = kernel.respond(input_text)
        window['-mytext-'].update(input_text)
        window['-CSI-'].update(response)
Beispiel 2:

Code: Alles auswählen

if event == 'Go':
        window['-ML1-'+sg.WRITE_ONLY_KEY].print(event, values, text_color='red')
    window['-ML2-'+sg.WRITE_ONLY_KEY].print(counter)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Dein funktionierender Code funktioniert in soweit, als dass Du eine beliebige Datei in der Konsole ausgibst, dass es sich zufälligerweise um eine JSON-Datei handelt, spielt gar keine Rolle bei Dir, bzw. verwirrt den Leser nur.
Bei Deinen ersten beiden Bespielen schreibst und liest Du zwar korrekt JSON, es ist aber wenig sinnvoll, wenn man JSON hat, dann dort Strings zu speichern, die einem Key=Value-Schema entsprechen.

Wenn Du etwas in einer Textbox ausgeben willst, dann solltest Du zuerst in Dein Layout auch eine Textbox einbauen.
Und dann hast Du ja schon die update-Methode von SimpleGUI gefunden, also hast Du alle Bausteine, um Dein Problem zu lösen.
marlon_germany
User
Beiträge: 33
Registriert: Samstag 30. April 2022, 23:32

Ok, herzlichen Dank soweit schonmal.
Klingt logisch. Ich hoffe ich schaffe es dieses Mal.
Sirius3 hat geschrieben: Montag 9. Mai 2022, 06:38 Dein funktionierender Code funktioniert in soweit, als dass Du eine beliebige Datei in der Konsole ausgibst, dass es sich zufälligerweise um eine JSON-Datei handelt, spielt gar keine Rolle bei Dir, bzw. verwirrt den Leser nur.
Bei Deinen ersten beiden Bespielen schreibst und liest Du zwar korrekt JSON, es ist aber wenig sinnvoll, wenn man JSON hat, dann dort Strings zu speichern, die einem Key=Value-Schema entsprechen.

Wenn Du etwas in einer Textbox ausgeben willst, dann solltest Du zuerst in Dein Layout auch eine Textbox einbauen.
Und dann hast Du ja schon die update-Methode von SimpleGUI gefunden, also hast Du alle Bausteine, um Dein Problem zu lösen.
marlon_germany
User
Beiträge: 33
Registriert: Samstag 30. April 2022, 23:32

Ich bin es nochmal :-)

ES FUNKTIONIERT ENDLICH!!!
Die Zeilen:

Code: Alles auswählen

txt = Path('test123.txt').read_text()
txt = txt.replace('\n', '')
window['text1'].update(txt)
sind das freudige Resultat. Vielen herzlichen Dank nochmal für die Hilfe :wink: ,
ohne mir jedoch gleich die fertige Lösung zu liefern.

Trotzdem wundert es mich, dass im Internet bisher nichts vernünftiges zu finden war,
unter dem Motto "Text-Datei auslesen und in Textbox anzeigen.
Antworten