Seite 1 von 1

Anfangswerte in Label's/Entry's entfernen

Verfasst: Donnerstag 23. April 2020, 11:22
von Particledust
Ich habe eine GUI erstellt, in der man Werte (x-Werte) manuell eingeben können. Wenn man einen Wert x1 eingibt, wird mithilfe von trace automatisch

f(x1)=x1^2=y1 und Mittelwert(y) = (1/5 Summe_{i=1}^{5} y_i)

berechnet. Also jedes Mal, wenn ein x-Wert eingibt, wird also der entsprechende y-Wert und Mittelwert(y) berechnet. Der untenstehende Code funktioniert. Wenn man ihn startet und in ersten Eintrag x1 Zehn schreibt, erhält man:

Bild

Ich möchte die Anfangswerte 0.0 von einigen Zellen entfernen. Das Fenster soll beim Start folgendermaßen aussehen:

Bild

Um das gewünschte Ergebnis zu erhalten, fügte ich ganz am Ende vor mainloop()

Code: Alles auswählen

for i in range(1,5):
    y_values[i].set("")
    cells[(i,0)].delete(0,END)
ein. Wenn man den Code mit dieser Änderung startet, dann funktioniert das Programm nicht mehr richtig. Wenn man einen x-Wert eingibt, wird nur der dazugehörige y-Wert berechnet, aber nicht mehr der Mittelwert(y).

Weiß jemand von euch warum der Code mit y_values.set(""), cells[(i,0)].delete(0,END) nicht mehr korrekt funktioniert und wie man dieses Problem lösen kann?

Hier ist der vollständige Code aus der ersten Abbildung:

Code: Alles auswählen

from tkinter import *
import tkinter as tk

# compute y-values 
def f(name, index, mode):
    try:
        for i in range(5):
            y_values[i].set(x_values[i].get()**2)
    except tk.TclError:
        pass
    
# compute mean
def statistic(name, index, mode):
    try:
        y_sum = 0
        for i in range(5):
            y_sum += y_values[i].get()
        y_normalized = y_sum / 5
        mean.set(y_normalized)
    except tk.TclError:
            pass

root = Tk()
Label(root, text = "x-values",padx = 10).grid(row = 0, column = 0)
Label(root, text = "y-values",padx = 10).grid(row = 0, column = 1)
Label(root, text = "Mean y", padx = 10).grid(row = 0, column = 2)
# Create Variables 
x_values, y_values = ["x%d" % x for x in range(5)], ["y%d" % x for x in range(5)]
for i in range (5):                     
    x_values[i], y_values[i] = DoubleVar(), DoubleVar()
mean = DoubleVar()

# Create Table 
rows, columns, cells = 5, 2, {}
for i in range(columns):
    for j in range(rows):
        if i == 0: # x-values that can be entered
            b = Entry(root, textvariable=x_values[j])
            b.grid(row = j+1, column = i, sticky = W + E)
            cells[(j,i)] = b
        else: # y-values that are computed by f
            b = Label(root, textvariable=y_values[j])
            b.grid(row = j+1, column = i, sticky = W + E)
            cells[(j,i)] = b

label_mean = Label(root, textvariable = mean).grid(row = 1, column = 2, rowspan = 5)

# Traces to trigger the above functions
for i in range(5):
    x_values[i].trace('w', f)
    y_values[i].trace('w', statistic)

mainloop()

Re: Anfangswerte in Label's/Entry's entfernen

Verfasst: Donnerstag 23. April 2020, 12:00
von Sirius3
*-Importe sind böse, weil man damit unkontrolliert Namen in den eigenen Namensraum schaufelt. Dabei importierst Du doch tk-Inter richtig, nutzt das aber nicht.

Alles was eine Funktion braucht, sollte sie über ihre Argumente bekommen: f fehlt x_values und y_values, statistic y_values und mean.
Man erzeugt keine Listen mit Dummy-Werten, um sie dann sofort mit richtigen Werten zu überschreiben.

Wenn Du außer Zahlen auch Leer ausgeben willst, dann ist DoubleVar falsch, und Du brauchst StrVar.

Re: Anfangswerte in Label's/Entry's entfernen

Verfasst: Donnerstag 23. April 2020, 13:01
von Sirius3
Heißt natürlich StringVar.

Code: Alles auswählen

import tkinter as tk
from functools import partial

# compute y-values 
def f(name, index, mode, x_values, y_values):
    for x, y in zip(x_values, y_values):
        try:
            v = float(x.get()) ** 2
        except ValueError:
            v = ''
        y.set(v)
    
# compute mean
def statistic(name, index, mode, y_values, mean):
    y_sum = 0
    count = 0
    for y in y_values:
        try:
            y_sum += float(y.get())
            count += 1
        except ValueError:
            pass
    mean.set(y_sum / count)

def main():
    root = tk.Tk()
    tk.Label(root, text = "x-values",padx = 10).grid(row = 0, column = 0)
    tk.Label(root, text = "y-values",padx = 10).grid(row = 0, column = 1)
    tk.Label(root, text = "Mean y", padx = 10).grid(row = 0, column = 2)

    # Create Table 
    x_values = []
    y_values = []
    mean = tk.StringVar()
    for j in range(1, 6):
        # x-values
        var = tk.StringVar(root)
        var.trace('w', partial(f, x_values=x_values, y_values=y_values))
        x_values.append(var)
        tk.Entry(root, textvariable=var).grid(row=j, column=0, sticky=tk.W + tk.E)
        # y-values that are computed by f
        var = tk.StringVar(root)
        var.trace('w', partial(statistic, y_values=y_values, mean=mean))
        y_values.append(var)
        tk.Label(root, textvariable=var).grid(row=j, column=1, sticky=tk.W + tk.E)

    tk.Label(root, textvariable = mean).grid(row=1, column=2, rowspan=5)
    root.mainloop()

if __name__ == '__main__':
    main()

Re: Anfangswerte in Label's/Entry's entfernen

Verfasst: Donnerstag 23. April 2020, 16:16
von Particledust
Vielen Dank für den überarbeiteten Code und deine Ratschläge. Letztere versuche ich meinen nächsten Aufgaben umzusetzen!