Tkinter - получение значений из динамически генерируемых виджетов - обратный вызов - PullRequest
0 голосов
/ 20 июня 2019

Я пытаюсь создать графический интерфейс через Tkinter, который будет рассчитывать производительность на основе некоторого пользовательского ввода. В зависимости от количества систем, которые выбирает пользователь, у меня появляется такое количество опционных меню для типа инвертора и количество виджетов ввода, всплывающих для модулей на строку, строк на инвертор и инверторов на систему. Смотрите рисунок для примера, если пользователь выбирает 2 системы.

Я использую функцию обратного вызова для получения выбранного пользователем количества систем в режиме реального времени для динамической генерации виджетов инвертора / модуля, описанных выше.

Моя проблема в том, что я не могу получить значения из этих виджетов. Моя попытка отображается в функции расчета погоды.

Я предполагаю, что проблема в том, что я генерирую виджеты / переменные в функции обратного вызова. Однако я не смог найти способ динамически генерировать количество виджетов на основе пользовательского ввода вне функции обратного вызова.

Любая помощь с этим будет принята с благодарностью!

  class Window:  

# Define User Inputs:  
    def __init__(self, master):  
        master.title('Production Analysis Tool')  

 # EQUIPMENT PARAMETERS         

    # callback function to create entry boxes based on number of systems  
        def callback(*args):  
            self.system_size = int(self.system_size_raw.get())  

        # Modules per String  
            self.L3 = Label(root, text = "Number of Modules Per String").grid(row=20, column=1, sticky=E)  
            self.modules_string_raw = IntVar(root)  
            modules_per_string =[]  
            for i in range(self.system_size):  
                self.label = Label(root, text = "System {}".format(i+1)).grid(row=21+i, column=1, sticky=E)  
                self.widget = Entry(root).grid(row=21+i, column=2, sticky=W)  
                modules_per_string.append(self.widget)  

    # Number of Systems  
        self.L1 = Label(root, text = "Number of Systems").grid(row=1, column=1, sticky=E)  
        self.system_size_raw = IntVar(root)  
        choices = [1,2,3,4,5,6,7,8,9,10]  
        self.popupMenu2 = OptionMenu(root, self.system_size_raw, *choices).grid(row=1, column=2, sticky=W)  
        self.system_size_raw.trace("w", callback)  


#Calculation Function  

    def weather_calculation(self):     

    # Get Values from User Input  

        self.mod_strings = np.float(self.modules_string_raw.get())  

root = Tk()  
root.configure()  
window = Window(root)  
root.mainloop()

Example GUI

Ответы [ 2 ]

1 голос
/ 20 июня 2019

Все, что вам нужно сделать, это сохранить ссылку на ваши Entry виджеты в списке. Затем вы можете перебрать этот список, чтобы получить значение каждого виджета.

Похоже, вы уже сохраняете виджеты в переменную списка modules_per_string. Все, что вам нужно сделать, это сделать этот глобальный или объектный атрибут, а не локальную переменную, чтобы другие функции могли ссылаться на него.

0 голосов
/ 21 июня 2019

Как сказал Брайан Оукли, составьте список для виджетов для хранения каждого объекта записей и метки в два списка.

Например:

import tkinter as tk
class Demo:
    def __init__(self):
        self.root = tk.Tk()
        self.root.geometry("600x600")
        systems_label = tk.Label(self.root, text="No Of Systems:")
        systems_label.place(x=100, y=20)

        no_Of_System_Ent = tk.Entry(self.root, width=15)
        no_Of_System_Ent.place(x=200, y=20)

        submit_Button = tk.Button(self.root, text="Submit", command=lambda: self.process(no_Of_System_Ent.get()))
        submit_Button.place(x=350,y=20)

    def display(self,sys_len): 
        for i in range(sys_len):
              buffer = self.obj_of_entries[i].get()
              print(buffer)

    def delete(self,sys_len):
         for i in range(sys_len):
              self.obj_of_entries[i].destroy()
              self.obj_of_labels[i].destroy()

    def process(self,length_sys):
         self.obj_of_entries = []
         self.obj_of_labels = []
         y_pos = 80
         for i in range(int(length_sys)):
              #Adding objects of label in list 'obj_of_labels'
              self.obj_of_labels.append(tk.Label(self.root,text="System "+str(i)))
              self.obj_of_labels[len(self.obj_of_labels)-1].place(x=100,y=y_pos)

              #Adding objects of entry in list 'obj_of_entries'
              self.obj_of_entries.append(tk.Entry(self.root,width=15))
              self.obj_of_entries[len(self.obj_of_entries)-1].place(x=200,y=y_pos)

              #Increments Y by 50
              y_pos = y_pos + 50

              self.delete_Button = tk.Button(self.root, text="Delete All", command=lambda: self.delete(int(length_sys)))
              self.delete_Button.place(x=200,y=400)

              self.print_Button = tk.Button(self.root, text="Print All", command=lambda: self.display(int(length_sys)))
              self.print_Button.place(x=350,y=400) 

ob=Demo()

В этом примере:

Я создал запись и кнопку в функции инициализации, чтобы не получать ни одной системы от пользователя.

def __init__(self):
    self.root = tk.Tk()
    self.root.geometry("600x600")

    systems_label = tk.Label(self.root, text="No Of Systems:")
    systems_label.place(x=100, y=20)

    no_Of_System_Ent = tk.Entry(self.root, width=15)
    no_Of_System_Ent.place(x=200, y=20)

    submit_Button = tk.Button(self.root, text="Submit", command=lambda: self.process(no_Of_System_Ent.get()))
    submit_Button.place(x=350,y=20)

После нажатия кнопки «Отправить» он перейдет к функции обработки.

Ps: length_sys - это номер системы.

def process(self,length_sys):
    self.obj_of_entries = []
    self.obj_of_labels = []
    y_pos = 80
    for i in range(int(length_sys)):
        #Adding objects of label in list 'obj_of_labels'
        self.obj_of_labels.append(tk.Label(self.root,text="System "+str(i)))
        self.obj_of_labels[len(self.obj_of_labels)-1].place(x=100,y=y_pos)

        #Adding objects of entry in list 'obj_of_entries'
        self.obj_of_entries.append(tk.Entry(self.root,width=15))
        self.obj_of_entries[len(self.obj_of_entries)-1].place(x=200,y=y_pos)

        #Increments Y by 50
        y_pos = y_pos + 50

        self.delete_Button = tk.Button(self.root, text="Delete All", command=lambda: self.delete(int(length_sys)))
        self.delete_Button.place(x=200,y=400)

Он добавит запись и метку obj в соответствующий список и поместит текущий obj в окно GUI. Наконец, он увеличит ось y на 80, так что следующая метка и запись упадут до предыдущей.

Если пользователь нажимает кнопку «Удалить все», он будет удалять все объекты списка как записей, так и меток.

Ps: sys_len - это номер системы.

def delete(self,sys_len):
    for i in range(sys_len):
        self.obj_of_entries[i].destroy()
        self.obj_of_labels[i].destroy()

Чтобы увидеть содержимое, используйте этот код:

(Он будет печататься в оболочке Python, чтобы вы могли видеть, верны ли данные.)

def display(self,sys_len): 
    for i in range(sys_len):
        buffer = self.obj_of_entries[i].get()
        print(buffer)

Кажется, я решил сомнение. Ciao!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...