Расчет среднего числа в Tkinter

У меня 10 полей entry в которых должны отображаться показания прибора. После этого вычисляется среднее значение.

Вопрос:

Если заполнены все десять полей, то вычисления проводятся верно - сумма из 10 полей деленная на 10. Как сделать чтобы при заполнении только 3 или n полей сумма указанная в них делилась на количество заполненных полей?

Код:

import tkinter as tk
from tkinter import ttk
from tkinter import *
import os
from docxtpl import DocxTemplate


class ReportMain(tk.Tk):
    """docstring for MainWindow"""

    def __init__(self):
        super().__init__()
        self.title("")
        self.configure(bg='palegreen')
        self.geometry('880x650+100+100')
        self.resizable(False, False)
        self.style = ttk.Style()
        self.style.configure(".", background="aliceblue", foreground="black")

        # Создание рамки:

        self.frame = tk.Frame(self, bg='aliceblue', bd=2)
        c = Canvas(self.frame, bg='aliceblue')
        c.config(width=845, height=635)
        c.pack(side=LEFT)
        c.bind_all("<MouseWheel>", lambda event: c.yview_scroll(int(-1 * (event.delta / 120)), "units"))

        def innerFrameGo(_):
            c.configure(scrollregion=c.bbox('all'))

        self.tkp_frm = tk.Frame(c, background='aliceblue')
        self.tkp_frm.bind("<Configure>", innerFrameGo)
        self.tkp_frm_id = c.create_window(0, 0, window=self.tkp_frm, anchor=NW, width=1000, height=2500)
        # self.tkp_frm.pack(fill='x')
        Scrb = Scrollbar(self.frame, orient=VERTICAL)
        Scrb.pack(side=RIGHT, fill=Y)
        c.configure(yscrollcommand=Scrb.set)
        Scrb.config(command=c.yview)
        self.frame.pack()

        # ИСХОДНЫЕ ДАННЫЕ:
        self.ibd = ttk.Label(self.tkp_frm, text='ВВОД ИСХОДНЫХ ДАННЫХ:')
        self.ibd.grid(row=2, column=2)
        self.table1 = ttk.Label(self.tkp_frm, text='Таблица №1: ', font=('Calibri', 12, 'bold'))
        self.table1.grid(row=14, column=1, sticky='w', ipadx=20, pady=5, padx=15)

        # Блок №1:
        def auto_update1(*args):
            try:
                value = float(self.devicereadings_ent.get().replace(',', '.'))
                result = value
                self.str2_var.set(f"{result:.2f}")
            except ValueError:
                self.str2_var.set("")

        self.devicereadings = ttk.Label(self.tkp_frm, text='показания №1 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings.grid(row=19, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str1_var = tk.StringVar()
        self.devicereadings_ent = ttk.Entry(self.tkp_frm, textvariable=self.str1_var)
        self.devicereadings_ent.grid(row=19, column=2, columnspan=2, ipadx=110)
        self.devicereadings_ent.insert(0, "0")

        self.arithmeticmean = ttk.Label(self.tkp_frm, text='Результат: ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean.grid(row=20, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str2_var = tk.StringVar()
        self.arithmeticmean_ent = ttk.Entry(self.tkp_frm, textvariable=self.str2_var, state="readonly")
        self.arithmeticmean_ent.grid(row=20, column=2, columnspan=2, ipadx=110)
        self.str1_var.trace_add("write", auto_update1)

        # Блок №2:
        def auto_update2(*args):
            try:
                value2 = float(self.devicereadings2_ent.get().replace(',', '.'))
                result2 = value2
                self.str4_var.set(f"{result2:.2f}")
            except ValueError:
                self.str4_var.set("")

        self.devicereadings2 = ttk.Label(self.tkp_frm, text='показания №2 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings2.grid(row=22, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str3_var = tk.StringVar()
        self.devicereadings2_ent = ttk.Entry(self.tkp_frm, textvariable=self.str3_var)
        self.devicereadings2_ent.grid(row=22, column=2, columnspan=2, ipadx=110)
        self.devicereadings2_ent.insert(0, "0")

        self.arithmeticmean2 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean2.grid(row=23, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str4_var = tk.StringVar()
        self.arithmeticmean2_ent = ttk.Entry(self.tkp_frm, textvariable=self.str4_var, state="readonly")
        self.arithmeticmean2_ent.grid(row=23, column=2, columnspan=2, ipadx=110)
        self.str3_var.trace_add("write", auto_update2)

        # Блок №3:
        def auto_update3(*args):
            try:
                value3 = float(self.devicereadings3_ent.get().replace(',', '.'))
                result3 = value3
                self.str6_var.set(f"{result3:.2f}")
            except ValueError:
                self.str6_var.set("")

        self.devicereadings3 = ttk.Label(self.tkp_frm, text='показания №3 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings3.grid(row=25, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str5_var = tk.StringVar()
        self.devicereadings3_ent = ttk.Entry(self.tkp_frm, textvariable=self.str5_var)
        self.devicereadings3_ent.grid(row=25, column=2, columnspan=2, ipadx=110)
        self.devicereadings3_ent.insert(0, "0")

        self.arithmeticmean3 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean3.grid(row=26, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str6_var = tk.StringVar()
        self.arithmeticmean3_ent = ttk.Entry(self.tkp_frm, textvariable=self.str6_var, state="readonly")
        self.arithmeticmean3_ent.grid(row=26, column=2, columnspan=2, ipadx=110)
        self.str5_var.trace_add("write", auto_update3)

        # Блок №4:
        def auto_update4(*args):
            try:
                value4 = float(self.devicereadings4_ent.get().replace(',', '.'))
                result4 = value4
                self.str8_var.set(f"{result4:.2f}")
            except ValueError:
                self.str8_var.set("")

        self.devicereadings4 = ttk.Label(self.tkp_frm, text='показания №4 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings4.grid(row=28, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str7_var = tk.StringVar()
        self.devicereadings4_ent = ttk.Entry(self.tkp_frm, textvariable=self.str7_var)
        self.devicereadings4_ent.grid(row=28, column=2, columnspan=2, ipadx=110)
        self.devicereadings4_ent.insert(0, "0")

        self.arithmeticmean4 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean4.grid(row=29, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str8_var = tk.StringVar()
        self.arithmeticmean4_ent = ttk.Entry(self.tkp_frm, textvariable=self.str8_var, state="readonly")
        self.arithmeticmean4_ent.grid(row=29, column=2, columnspan=2, ipadx=110)
        self.str7_var.trace_add("write", auto_update4)

        # Блок №5:
        def auto_update5(*args):
            try:
                value5 = float(self.devicereadings5_ent.get().replace(',', '.'))
                result5 = value5
                self.str10_var.set(f"{result5:.2f}")
            except ValueError:
                self.str10_var.set("")

        self.devicereadings5 = ttk.Label(self.tkp_frm, text='показания №5 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings5.grid(row=31, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str9_var = tk.StringVar()
        self.devicereadings5_ent = ttk.Entry(self.tkp_frm, textvariable=self.str9_var)
        self.devicereadings5_ent.grid(row=31, column=2, columnspan=2, ipadx=110)
        self.devicereadings5_ent.insert(0, "0")

        self.arithmeticmean5 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean5.grid(row=32, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str10_var = tk.StringVar()
        self.arithmeticmean5_ent = ttk.Entry(self.tkp_frm, textvariable=self.str10_var, state="readonly")
        self.arithmeticmean5_ent.grid(row=32, column=2, columnspan=2, ipadx=110)
        self.str9_var.trace_add("write", auto_update5)

        # Блок №6:
        def auto_update6(*args):
            try:
                value6 = float(self.devicereadings6_ent.get().replace(',', '.'))
                result6 = value6
                self.str12_var.set(f"{result6:.2f}")
            except ValueError:
                self.str12_var.set("")

        self.devicereadings6 = ttk.Label(self.tkp_frm, text='показания №6 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings6.grid(row=34, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str11_var = tk.StringVar()
        self.devicereadings6_ent = ttk.Entry(self.tkp_frm, textvariable=self.str11_var)
        self.devicereadings6_ent.grid(row=34, column=2, columnspan=2, ipadx=110)
        self.devicereadings6_ent.insert(0, "0")

        self.arithmeticmean6 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean6.grid(row=35, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str12_var = tk.StringVar()
        self.arithmeticmean6_ent = ttk.Entry(self.tkp_frm, textvariable=self.str12_var, state="readonly")
        self.arithmeticmean6_ent.grid(row=35, column=2, columnspan=2, ipadx=110)
        self.str11_var.trace_add("write", auto_update6)

        # Блок №7:
        def auto_update7(*args):
            try:
                value7 = float(self.devicereadings7_ent.get().replace(',', '.'))
                result7 = value7
                self.str14_var.set(f"{result7:.2f}")
            except ValueError:
                self.str14_var.set("")

        self.devicereadings7 = ttk.Label(self.tkp_frm, text='показания №7 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings7.grid(row=37, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str13_var = tk.StringVar()
        self.devicereadings7_ent = ttk.Entry(self.tkp_frm, textvariable=self.str13_var)
        self.devicereadings7_ent.grid(row=37, column=2, columnspan=2, ipadx=110)
        self.devicereadings7_ent.insert(0, "0")

        self.arithmeticmean7 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean7.grid(row=38, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str14_var = tk.StringVar()
        self.arithmeticmean7_ent = ttk.Entry(self.tkp_frm, textvariable=self.str14_var, state="readonly")
        self.arithmeticmean7_ent.grid(row=38, column=2, columnspan=2, ipadx=110)
        self.str13_var.trace_add("write", auto_update7)

        # Блок №8:
        def auto_update8(*args):
            try:
                value8 = float(self.devicereadings8_ent.get().replace(',', '.'))
                result8 = value8
                self.str16_var.set(f"{result8:.2f}")
            except ValueError:
                self.str16_var.set("")

        self.devicereadings8 = ttk.Label(self.tkp_frm, text='показания №8 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings8.grid(row=40, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str15_var = tk.StringVar()
        self.devicereadings8_ent = ttk.Entry(self.tkp_frm, textvariable=self.str15_var)
        self.devicereadings8_ent.grid(row=40, column=2, columnspan=2, ipadx=110)
        self.devicereadings8_ent.insert(0, "0")

        self.arithmeticmean8 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean8.grid(row=41, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str16_var = tk.StringVar()
        self.arithmeticmean8_ent = ttk.Entry(self.tkp_frm, textvariable=self.str16_var, state="readonly")
        self.arithmeticmean8_ent.grid(row=41, column=2, columnspan=2, ipadx=110)
        self.str15_var.trace_add("write", auto_update8)

        # Блок №9:
        def auto_update9(*args):
            try:
                value9 = float(self.devicereadings9_ent.get().replace(',', '.'))
                result9 = value9
                self.str18_var.set(f"{result9:.2f}")
            except ValueError:
                self.str18_var.set("")

        self.devicereadings9 = ttk.Label(self.tkp_frm, text='показания №9 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings9.grid(row=43, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str17_var = tk.StringVar()
        self.devicereadings9_ent = ttk.Entry(self.tkp_frm, textvariable=self.str17_var)
        self.devicereadings9_ent.grid(row=43, column=2, columnspan=2, ipadx=110)
        self.devicereadings9_ent.insert(0, "0")

        self.arithmeticmean9 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean9.grid(row=44, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str18_var = tk.StringVar()
        self.arithmeticmean9_ent = ttk.Entry(self.tkp_frm, textvariable=self.str18_var, state="readonly")
        self.arithmeticmean9_ent.grid(row=44, column=2, columnspan=2, ipadx=110)
        self.str17_var.trace_add("write", auto_update9)

        # Блок №10:
        def auto_update10(*args):
            try:
                value10 = float(self.devicereadings10_ent.get().replace(',', '.'))
                result10 = value10
                self.str20_var.set(f"{result10:.2f}")
            except ValueError:
                self.str20_var.set("")

        self.devicereadings10 = ttk.Label(self.tkp_frm, text='показания №10 : ', font=('Calibri', 11, 'bold'))
        self.devicereadings10.grid(row=46, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str19_var = tk.StringVar()
        self.devicereadings10_ent = ttk.Entry(self.tkp_frm, textvariable=self.str19_var)
        self.devicereadings10_ent.grid(row=46, column=2, columnspan=2, ipadx=110)
        self.devicereadings10_ent.insert(0, "0")

        self.arithmeticmean9 = ttk.Label(self.tkp_frm, text='Результат : ', font=('Calibri', 11, 'bold'))
        self.arithmeticmean9.grid(row=47, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.str20_var = tk.StringVar()
        self.arithmeticmean9_ent = ttk.Entry(self.tkp_frm, textvariable=self.str20_var, state="readonly")
        self.arithmeticmean9_ent.grid(row=47, column=2, columnspan=2, ipadx=110)
        self.str19_var.trace_add("write", auto_update10)

        # CОЗДАНИЕ КНОПКИ "Расчитать":
        self.add_btn = ttk.Button(self.tkp_frm, text='Расчитать', command=self.convert).grid(row=90, column=2,
                                                                                             sticky='w')
        # Результаты вычислений:
        self.xaver = ttk.Label(self.tkp_frm, text='Среднее арифметическое из N-наблюдений : ',
                               font=('Calibri', 11, 'bold'))
        self.xaver.grid(row=94, column=1, sticky='w', ipadx=20, pady=5, padx=15)
        self.value = tk.StringVar()
        self.xaver_ent = ttk.Entry(self.tkp_frm, textvariable=self.value, state="readonly")
        self.xaver_ent.grid(row=94, column=2, columnspan=2, ipadx=110)

    # ФУНКЦИЯ РАСЧЁТА:
    def convert(self):
        # Получить исходные данные:
        devicereadings = self.devicereadings_ent.get()
        devicereadings = float(devicereadings.replace(',', '.'))
        devicereadings2 = self.arithmeticmean2_ent.get()
        devicereadings2 = float(devicereadings2.replace(',', '.'))
        devicereadings3 = self.devicereadings3_ent.get()
        devicereadings3 = float(devicereadings3.replace(',', '.'))
        devicereadings4 = self.devicereadings4_ent.get()
        devicereadings4 = float(devicereadings4.replace(',', '.'))
        devicereadings5 = self.devicereadings5_ent.get()
        devicereadings5 = float(devicereadings5.replace(',', '.'))
        devicereadings6 = self.devicereadings6_ent.get()
        devicereadings6 = float(devicereadings6.replace(',', '.'))
        devicereadings7 = self.devicereadings7_ent.get()
        devicereadings7 = float(devicereadings7.replace(',', '.'))
        devicereadings8 = self.devicereadings8_ent.get()
        devicereadings8 = float(devicereadings8.replace(',', '.'))
        devicereadings9 = self.devicereadings9_ent.get()
        devicereadings9 = float(devicereadings9.replace(',', '.'))
        devicereadings10 = self.devicereadings10_ent.get()
        devicereadings10 = float(devicereadings10.replace(',', '.'))

        # Расчет данных для вставки в документ:

        x_aver = (
                         devicereadings + devicereadings2 + devicereadings3 + devicereadings4 + devicereadings5 + devicereadings6 + devicereadings7 + devicereadings8 + devicereadings9 + devicereadings10) / 10  # Среднее арифметическое
        # Показать результаты:
        self.value.set(f"{x_aver:.2f}")


if __name__ == "__main__":
    app = ReportMain()
    app.mainloop()

Ответы (1 шт):

Автор решения: Amgarak

Связанный ответ.

Начнём с того, что у вас очень перегруженный __init__. Разумнее будет разбить класс на методы и уже их вызывать в конструкторе. Так код станет понятней, а его поддержка проще.

Для оптимизации все поля создаём через цикл с сохранением их в список, на каждое поле ввода вешаем trace_add("write", self.get_average_value) с указанием на один и тот же метод расчета.

В самом методе self.get_average_value фильтруем не пустые\корректные данные в полях ввода, вычисляем среднее значение и устанавливаем в специальное поле. И никаких кнопок или дополнительных полей создавать не нужно:

import tkinter as tk
from tkinter import ttk

class ReportMain(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("")
        self.geometry("880x650+100+100")

        self.strvars_entries = []
        self.create_entry_str(num_entries=10)

        self.result_var = self.create_result_str()
        self.result_var.set("Нет данных")
        
    def create_entry_str(self, num_entries):
        for i in range(num_entries):
            label = ttk.Label(self, text=f"Показание №{i+1}")
            label.grid(row=i, column=0, padx=10, pady=5, sticky='w')
            
            str_var = tk.StringVar()
            str_var.trace_add("write", self.get_average_value) 
            
            entry = ttk.Entry(self, textvariable=str_var)
            entry.grid(row=i, column=1, padx=10, pady=5)
            
            self.strvars_entries.append(str_var)
            
    def create_result_str(self):
        result_label = ttk.Label(self, text="Среднее значение:")
        result_label.grid(row=11, column=0, padx=10, pady=5, sticky='w')
        
        result_var = tk.StringVar()
        result_entry = ttk.Entry(self, textvariable=result_var, state="readonly")
        result_entry.grid(row=11, column=1, padx=10, pady=5)
        
        return result_var 

    def get_valid_values(self):
        values = []
        for var in self.strvars_entries:
            try:
                value = float(var.get().replace(',', '.'))
                values.append(value)
            except ValueError:
                continue  
        return values

    def get_average_value(self, *args):
        values = self.get_valid_values()
        
        if values:
            average_value = sum(values) / len(values)
            self.result_var.set(f"{average_value:.2f}")
        else:
            self.result_var.set("Нет данных")

if __name__ == "__main__":
    app = ReportMain()
    app.mainloop()

введите сюда описание изображения

→ Ссылка