Tkinter передает результат функции обратного вызова в другой класс - PullRequest
1 голос
/ 13 марта 2019

Интересно, как передать возвращаемое значение из одного класса в другой класс в tkinter. В моей программе у меня есть класс DataChosenForm, где я хочу выбрать опцию в Combobox и передать этот результат другому классу ReturnData, чтобы установить переменную в Label.

import tkinter as tk
from tkinter import ttk

class DataChosenForm(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        chosen = tk.LabelFrame(self, text="wybór")
        chosen.grid(row=0)
        self.combo = ttk.Combobox(chosen)
        self.combo['values'] = ('wizz', 'ryanair', 'lot')
        self.combo.grid(row=0, column=2, padx=80, pady=10)
        self.combo.bind("<<ComboboxSelected>>", self.callback)

    def callback(self, event=None):
        if event.widget.get() == 'wizz':
            print('wizz')
            return 'wizz'
        elif event.widget.get() == 'ryanair':
            print('ryanair')
            return 'ryanair'
        elif event.widget.get() == 'lot':
            print('lot')
            return 'lot'

class ReturnData(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        var = tk.StringVar()
        message_box = tk.LabelFrame(self, text="wynik")
        message_box.grid(row=1)
        mb = tk.Label(message_box, textvariable=var,anchor='nw')
        mb.pack(padx=120, pady=30)

class Application(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("program do wyszukiwania cen lotów")
        self.geometry('300x200')
        self.resizable(width=False, height=False)
        DataChosenForm(self).grid(row=0, column=0)
        ReturnData(self).grid(row=1)


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

Ответы [ 2 ]

1 голос
/ 13 марта 2019

Вы можете сначала отобразить комбинированный список DataChosenForm(self).grid(row=0, column=0), не вызывая ReturnData в классе Application.

Затем в методе callback() соберите выбор choice = event.widget.get() и передайте его ReturnData. Это будет означать, однако, что LabelFrame отображается только после выбора.

import tkinter as tk
from tkinter import ttk

class DataChosenForm(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        chosen = tk.LabelFrame(self, text="wybór")
        chosen.grid(row=0)
        self.combo = ttk.Combobox(chosen)
        self.combo['values'] = ('wizz', 'ryanair', 'lot')
        self.combo.grid(row=0, column=2, padx=80, pady=10)
        self.combo.bind("<<ComboboxSelected>>", self.callback)

    def callback(self, event=None):
        choice = event.widget.get()
        print(choice)
        ReturnData(self, choice).grid(row=1)

class ReturnData(tk.Frame):
    def __init__(self, parent, choice):
        super().__init__(parent)
        message_box = tk.LabelFrame(self, text="wynik")
        message_box.grid(row=1)
        mb = tk.Label(message_box, text=choice, anchor='nw')
        mb.pack(padx=120, pady=30)

class Application(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("program do wyszukiwania cen lotów")
        self.geometry('300x200')
        self.resizable(width=False, height=False)
        DataChosenForm(self).grid(row=0, column=0)

if __name__ == "__main__":
    app = Application()
    app.mainloop()
0 голосов
/ 13 марта 2019

Я думаю, что @Julia имеет в основном правильную архитектуру для вашего приложения tkinter, но ее ответ мог бы быть улучшен с помощью tkinter Variable - потому что все виджеты, связанные с одним, будут автоматически обновлять отображаемое значение всякий раз, когда Variableизменилось (одним из них или что-то еще).

Вот небольшая документация по Переменным классам .Обратите внимание, что, поскольку у ttk.Combobox есть все методы виджетов tk.Entry, здесь приведена небольшая документация о них (что также иллюстрирует «шаблон» использования StringVar в сочетании с одним, поэтому он также применяетсяttk.Combobox s).

Как правило, вы можете указать виджету использовать tkinter Variable, указав его экземпляр в качестве аргумента ключевого слова опции textvariable= при создании виджета.Вы также можете установить опцию, используя интерфейс частичного словаря, который поддерживает большинство виджетов, поэтому назначения, такие как widget['textvariable'] = variable, являются еще одним способом их использования - в приведенном ниже коде используются оба этих способа.

Вот код Джулиимодифицировано для использования tk.StringVar.Обратите внимание, что Combobox не не требуется функция обратного вызова для привязки к нему события <<ComboboxSelected>>, поэтому вся эта сложность была устранена.

import tkinter as tk
from tkinter import ttk

class DataChosenForm(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        choice = tk.LabelFrame(self, text="wybór")
        choice.grid(row=0)
        self.combo = ttk.Combobox(choice)
        self.combo['textvariable'] = parent.var  # Use shared variable.
        self.combo['values'] = ('wizzair', 'ryanair', 'lot')
        self.combo.grid(row=0, column=2, padx=80, pady=10)

class ReturnData(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        message_box = tk.LabelFrame(self, text="wynik")
        message_box.grid(row=1)
        mb = tk.Label(message_box, textvariable=parent.var,  # Use shared variable.
                      anchor='nw', width=20)
        mb.pack(padx=120, pady=30)

class Application(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("program do wyszukiwania cen lotów")
        self.geometry('300x200')
        self.resizable(width=False, height=False)
        self.var = tk.StringVar(value='Dokonać wyboru')  # Create shared variable.

        DataChosenForm(self).grid(row=0, column=0)
        ReturnData(self).grid(row=1)

if __name__ == "__main__":
    app = Application()
    app.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...