Seite 1 von 1

Speicherfunktion

Verfasst: Dienstag 17. November 2020, 13:01
von Python1995
Hallo zusammen,

ich habe ein Problem und zwar sollen wir ein kleines Statistikprogramm entwerfen, mit dem man einmal Mittelwerte eines Datensatzes und einmal Maximas eines Datensatzes bestimmen kann. Ich konnte das bereits in einem Menü umsetzten indem man den Datensatz öffnen kann und dann mittels des Menüs die Methoden anwenden kann und sich dann per Popup das Ergebnis ansehen kann. Soweit so gut: aber ich möchte es jetzt noch schaffen, dass das angezeigte Ergebnis, dass im Popup erscheint in einer z. B. Textdatei abgespeichert wird. Ich habe es zwar hinbekommen, dass wenn man auf speichern klickt der Dateipfad angezeigt wird, allerdings speichert es dann ein leeres Textdokument ab. Kann mir bitte jemand weiterhelfen?

Code: Alles auswählen

import tkinter as tk
from tkinter import filedialog
import pandas as pd

NORM_FONT = ("Helvetica", 10)

app = tk.Tk()
app.geometry('400x200')
app.title("Menu")

menubar = tk.Menu(app)
filemenu = tk.Menu(menubar, tearoff=0)

first_row = None
content = None
columns = [ "duration", "actor_1_facebook_likes", "num_user_for_reviews", "num_critic_for_reviews", "num_voted_users" ]

def onOpen():
    global first_row
    global content
    filename = filedialog.askopenfilename(initialdir = "/",title = "Open file",filetypes = (("Python files","*.py;*.pyw *.sec*"),("All files","*.*")))
    f = open(filename, "r", encoding="UTF-8")
    x = 0

    if content == None:
        mittelwert_menu = tk.Menu(menubar, tearoff=0)
        for column in columns:
            mittelwert_menu.add_command(label=column, command=lambda: onMittelwert(column))
        menubar.add_cascade(label="Mittelwert bestimmen", menu=mittelwert_menu)

        maximum_menu = tk.Menu(menubar, tearoff=0)
        for column in columns:
            maximum_menu.add_command(label=column, command=lambda: onMaximum(column))
        menubar.add_cascade(label="Maximum bestimmen", menu=maximum_menu)

    content = []
    for line in f:
        if x == 0:
            first_row = line
        else:
            content.append(line)
        x += 1
    f.close()

 
def onMittelwert(column_to_look_for):
    columns = first_row.split('\t') # Erstellt eine Liste der Spalten anhand der ersten Zeile in der Datei
    index = columns.index(column_to_look_for) # Berechnet die Position der Spalte in der Liste
    mittelwert_sum = 0 # Zähler für den Mittelwert
    line_sum = 0 # Zählt die Anzahl der Zeilen

    for line in content:
        row = line.split('\t') # Erstellt eine Liste der Spalten anhand der aktuellen Zeile in der Datei
        value = row[index] # Liest den gesuchten Wert aus der aktuellen Zeile
        if value != '':
            mittelwert_sum += float(value) # Erhöht die Mittelwert Summe
            line_sum += 1

    popupmsg('Mittelwert "' + column_to_look_for + '": ' + str(mittelwert_sum / line_sum)) 

def onMaximum(column_to_look_for):
    columns = first_row.split('\t') # Erstellt eine Liste der Spalten anhand der ersten Zeile in der Datei
    index = columns.index(column_to_look_for) # Berechnet die Position der Spalte in der Liste
    current_max = 0 # Aktuelles Maximum
    title_max = None

    for line in content:
        row = line.split('\t') # Erstellt eine Liste der Spalten anhand der aktuellen Zeile in der Datei
        value = row[index] # Liest den gesuchten Wert aus der aktuellen Zeile
        if value != '':
            value = float(value)
            if (current_max < value):
                current_max = value # Neues Maximum festlegen
                title_max = row[0]
                
            
    popupmsg('Maximum "' + column_to_look_for + '" ' + title_max.strip() + ': ' + str(current_max))
    

    
def onSave():
    name=filedialog.asksaveasfile(mode='w',defaultextension=".txt") 
    text2save = result
    name.write(text2save)
    name.close
            
def popupmsg(msg):
    popup = tk.Tk()
    popup.wm_title("!")
    label = tk.Label(popup, text=msg, font=NORM_FONT)
    label.pack(side="top", fill="x", pady=10)
    B1 = tk.Button(popup, text="Schließen", command = popup.destroy)
    B1.pack()
    B2 = tk.Button(popup, text="Speichern", command = onSave)
    B2.pack()
    popup.mainloop()
    

filemenu.add_command(label="Öffnen...", command=onOpen)
filemenu.add_command(label="Schließen", command=app.destroy)

menubar.add_cascade(label="Datei", menu=filemenu)

app.config(menu=menubar)

app.mainloop()

Re: Speicherfunktion

Verfasst: Dienstag 17. November 2020, 19:53
von ElektroBerry

Code: Alles auswählen

def onSave():
    name=filedialog.asksaveasfile(mode='w',defaultextension=".txt") 
    text2save = result
    name.write(text2save)
    name.close
Wo kommt die Variable "result" her?
Die Information könnte man der Funktion als Parameter mitgeben.
Eine main() Funktion würde hier die Übersichtlichkeit erhöhen und die Textdatei kann man mit "with open" öffnen.
Ein weitere Verbesserungsmöglichkeit wäre es die Globalen Variablen zu vermeiden.

Code: Alles auswählen

def onSave(text2save):
    name=filedialog.asksaveasfile(mode='w',defaultextension=".txt") 
    with open(name, "w") as file:
    	file.write(text2save)

Re: Speicherfunktion

Verfasst: Mittwoch 18. November 2020, 09:38
von Sirius3
global hat in einem sauberen Programm nichts verloren. columns zum Beispiel, gibt es einmal als globale Variable, oder doch als Konstante? In onMittelwert wird eine lokale Variable columns erzeugt, aber dann doch mit einem Wert aus dem globalen columns verglichen.

Es ist unüblich, dass während des Programmlaufs neue Menüpunkte hinzukommen. Der übliche Weg ist es, diese auszugrauen.
Die Benutzung von lambda ist in Deinem Menü auch falsch, benutze functools.partial.

Es darf nur eine Tk-Instanz geben, in popupmsg sollte ein Dialog erzeugt werden, kein Tk-Objekt.

Eigentlich kommt man bei GUI-Programmen nicht um Klassendefinitionen rum.

Dateien öffnet man mit dem with-Statement und die erste Zeile ermittelt man vor der for-Schleife und macht keine Fallunterscheidung innerhalb:

Code: Alles auswählen

    with open(filename, encoding="UTF-8") as lines:
        first_row = next(lines)
        content = list(lines)
Das ganze umgesetzt, ungetestet:

Code: Alles auswählen

import tkinter as tk
from tkinter import filedialog
from tkinter.messagebox import showinfo
from functools import partial

NORM_FONT = ("Helvetica", 10)
COLUMNS = ["duration", "actor_1_facebook_likes", "num_user_for_reviews", "num_critic_for_reviews", "num_voted_users"]

class Calculator(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.first_row = None
        self.content = None
        
        self.geometry('400x200')
        self.title("Menu")
        menubar = tk.Menu(self)
        filemenu = tk.Menu(menubar, tearoff=0)
        filemenu.add_command(label="Öffnen...", command=self.on_open)
        filemenu.add_command(label="Schließen", command=self.destroy)
        menubar.add_cascade(label="Datei", menu=filemenu)

        mittelwert_menu = tk.Menu(menubar, tearoff=0)
        for column in COLUMNS:
            mittelwert_menu.add_command(label=column, command=partial(self.on_mittelwert, column))
        menubar.add_cascade(label="Mittelwert bestimmen", menu=mittelwert_menu)

        maximum_menu = tk.Menu(menubar, tearoff=0)
        for column in COLUMNS:
            maximum_menu.add_command(label=column, command=partial(self.on_maximum, column))
        menubar.add_cascade(label="Maximum bestimmen", menu=maximum_menu)

        menubar.entryconfig(2, state=tk.DISABLED)
        menubar.entryconfig(3, state=tk.DISABLED)
        self.config(menu=menubar)
        self.menubar=menubar

    def on_open(self):
        filename = filedialog.askopenfilename(initialdir="/", title="Open file", filetypes = (("Python files","*.py;*.pyw *.sec*"),("All files","*.*")))
        with open(filename, encoding="UTF-8") as lines:
            self.first_row = next(lines).split('\t')
            self.content = [line.split('\t') for line in lines]
        self.menubar.entryconfig(2, state=tk.NORMAL)
        self.menubar.entryconfig(3, state=tk.NORMAL)

    def on_mittelwert(self, column_to_look_for):
        index = first_row.index(column_to_look_for)
        values = []
        for row in content:
            value = row[index]
            if value != '':
                values.append(float(value))
        mittelwert = sum(values) / len(values)
        showinfo("Mittelwert", f'Mittelwert "{column_to_look_for}": {mittelwert:.2f}')
        
    def on_maximum(self, column_to_look_for):
        index = first_row.index(column_to_look_for)
        values = []
        for row in content:
            value = row[index]
            if value != '':
                values.append((float(value), row[0]))
        maximum, title = max(values)
        showinfo("Maximum", f'Maximum "{column_to_look_for}" {title_max.strip()}: {maximum}')
    

def main():
    app = Calculator()
    app.mainloop()

if __name__ == '__main__':
    main()