#python #tkinter
#python #tkinter
Вопрос:
Я пытаюсь заставить Tkinter вернуть значение из поля ввода, но, похоже, у меня не получается заставить его работать.
Это моя первая попытка попробовать Tkinter, s
Exception in Tkinter callback
Traceback (most recent call last):
File "C:UsersrikAppDataLocalProgramsPythonPython38-32libtkinter__init__.py", line 1883, in __call__
return self.func(*args)
File "n:regnskabAfregningRIKUdviklingguiapp2.py", line 43, in step_1
periode_2 = get_period(self)
NameError: name 'get_period' is not defined
import tkinter as tk
from tkinter import ttk
class Mainframe(tk.Tk):
def __init__(self, *args, **kvargs):
super().__init__(*args, **kvargs)
self.title("app")
UserInputFrame(self).grid(row=1, column=0)
ControlsFrame(self).grid(row=2, column=0)
ButtonFrame(self).grid(row=3, column=0)
class UserInputFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
self.user_input_year = tk.StringVar(value="2021")
label_entry_year = ttk.Label(self, text="Year")
self.entry_year = ttk.Entry(self, textvariable=self.user_input_year)
label_entry_year.grid(row=2, column=0, sticky="W", padx=10, pady=5)
self.entry_year.grid(row=2, column=1, sticky="EW")
def get_period(self):
print(self.entry_year.get())
class ControlsFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
step_1_button = ttk.Button(self, text="Step 1", command=self.step_1)
step_1_button.grid(row=10, column=0, sticky="EW")
def step_1(self):
periode_2 = get_period(self)
print("step 1")
class ButtonFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
quit_button = ttk.Button(self, text="Quit", command=quit)
quit_button.grid(row=4, column=1, sticky="EW")
def quit(self):
app.destroy
app = Mainframe()
app.mainloop()
Комментарии:
1. вы должны учиться
OOP
.get_period
это не отдельная функция, а функция внутри классаUserInputFrame
, поэтому вам нужно будет получить экземплярUserInputFrame
, отправить его в качестве аргументаControlsFrame
и затем использоватьinstance_of_control_frame.get_period()
Вы не можете получить доступ к функции одного класса из другого класса.
Ответ №1:
Вы должны изучить ООП 🙂
get_period()
это не отдельная функция, а функция внутри класса UserInputFrame
, и вы пытаетесь получить к ней доступ в классе ControlsFrame
. Таким образом, вы не можете получить доступ к функции для одного класса в другом классе.
Вам нужно будет получить экземпляр UserInputFrame
,
user_input_frame = UserInputFrame(self)
user_input_frame.grid(row=1, column=0)
отправьте его в качестве аргумента в ControlsFrame
ControlsFrame(self, user_input_frame).grid(row=2, column=0)
храните его в переменной класса
class ControlsFrame(ttk.Frame):
def __init__(self, container, user_input_frame):
super().__init__(container)
self.user_input_frame = user_input_frame
и тогда вы сможете им воспользоваться
def step_1(self):
self.user_input_frame.get_period() # without `self` in `get_period()`
ИЛИ лучший метод
Вы должны ссылаться UserInputFrame
на переменную класса в Mainframe
self.user_input_frame = UserInputFrame(self)
self.user_input_frame.grid(row=1, column=0)
и тогда другие объекты (созданные в Mainframe
) могут получить доступ Mainframe
(который является его paret / master), используя self.master
, а затем они могут получить доступ к элементам, Mainframe
подобным self.master.userinputframe
periode_2 = self.master.user_input_frame.get_period() # without `self` in `get_period()`
import tkinter as tk
from tkinter import ttk
class Mainframe(tk.Tk):
def __init__(self, *args, **kvargs):
super().__init__(*args, **kvargs)
self.title("app")
self.user_input_frame = UserInputFrame(self)
self.user_input_frame.grid(row=1, column=0)
ControlsFrame(self).grid(row=2, column=0)
ButtonFrame(self).grid(row=3, column=0)
class UserInputFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
self.user_input_year = tk.StringVar(value="2021")
label_entry_year = ttk.Label(self, text="Year")
self.entry_year = ttk.Entry(self, textvariable=self.user_input_year)
label_entry_year.grid(row=2, column=0, sticky="W", padx=10, pady=5)
self.entry_year.grid(row=2, column=1, sticky="EW")
def get_period(self):
#print(self.entry_year.get())
return self.entry_year.get()
class ControlsFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
step_1_button = ttk.Button(self, text="Step 1", command=self.step_1)
step_1_button.grid(row=10, column=0, sticky="EW")
def step_1(self):
# `self.master` gives access to parent object which here is `Masterframe` (because you used `Masterframe` as `self` when you created `ControlsFrame(self)`
periode_2 = self.master.user_input_frame.get_period() # without `self` in `get_period()`
print("step 1")
class ButtonFrame(ttk.Frame):
def __init__(self, container):
super().__init__(container)
quit_button = ttk.Button(self, text="Quit", command=self.quit)
quit_button.grid(row=4, column=1, sticky="EW")
def quit(self):
app.destroy()
app = Mainframe()
app.mainloop()
Кстати: в ButtonFrame
ты забыл self.
в command=self.quit
и ()
в app.destroy()
РЕДАКТИРОВАТЬ: как заметил @acw1668, функция get_period()
не возвращает значение из записи — она только печатает его — поэтому ей нужно return
def get_period(self):
return self.entry_year.get()
Комментарии:
1. Пожалуйста, обратите внимание, что
get_period()
возвратNone
. Измените его наdef get_period(self): return self.entry_year.get()
.2. @acw1668 хороший момент 🙂 Я добавил его в ответ
3. большое спасибо — заставил его работать со вторым методом. Почему вы считаете, что это превосходит первое?
4. вторая версия универсальна — все классы имеют доступ к
user_input_frame
. Таким же образом вы можете получить доступself.master.user_input_frame
ButtonFrame
в. Если вы добавите другой виджет в главное окно, у него также будет доступself.master.user_input_frame
. И аналогичным образом вы можете установитьself.control_frame = ControlsFrame(...)
, и другие виджеты будут иметь доступ кcontrol_frame
использованиюself.master.control_frame
.