Я изучаю ООП и делаю калькулятор. У меня есть классы для основной программы (родительской программы), кнопок и записей.
Основная программа:
class Program(tk.Tk):
def __init__(self, title, size):
super().__init__()
self.title(title)
self.geometry(f"{size[0]}x{size[1]}")
# Program elements split into widget type
self.entries = Entries(self)
self.output = Output(self)
self.buttons = Buttons(self)
Записи:
class Entries(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.place(x = 0, y = 0)
# Calling widget generator and placer functions
self.entryGen()
self.entryPlacer()
def entryGen(self): # Create entry widgets
self.firstTerm = ttk.Entry(self)
self.commonDifference = ttk.Entry(self)
self.numberOfTerms = ttk.Entry(self)
def entryPlacer(self): # Place entry widgets
self.firstTerm.pack()
self.commonDifference.pack()
self.numberOfTerms.pack()
Кнопки:
class Buttons(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.place(x = 0, y = 0)
self.buttonGen()
self.buttonPlacer()
def buttonGen(self):
self.clear = ttk.Button(self, text = "Clear", command = lambda: self.clear)
self.calculate = ttk.Button(self, text = "Calculate", command = lambda: self.calculate)
def buttonPlacer(self):
self.clear.pack()
self.calculate.pack()
def clear(self):
pass
def calculate(self):
entries = Entries()
try:
print(entries.firstTerm.get() + entries.commonDifference.get() + entries.numberOfTerms.get()) # Just some test code to see if it works, which it doesnt
except:
pass
Я ожидаю, что когда я создам ссылку на класс Entries() в своем классе Buttons(), я смогу получить доступ к переменным, созданным в классе Entries(). Это не так, и я не могу понять, почему. Я просмотрел похожие исправления, и ни одно из них не работает.
@Guy OP запускает эти другие методы в init, все должно быть в порядке ... но код, который они показали, использует Entries (), в то время как init принимает родителя, поэтому он должен сломаться еще до этого вывода
@tomasv 1. Вы выполняете Entries (), но инициализация в этом классе говорит, что вам нужно передать родителя - поэтому код должен завершиться с ошибкой перед строкой печати. Если он не падает, значит, вы используете другой код, который вы нам показали. 2. Удалите пробу и голое за исключением того, что вы скрываете ошибку. Пусть ошибка приведет к сбою вашего приложения и просто покажите нам, что она говорит.
Ваш класс Buttons
не будет иметь прямого доступа к вашему классу Entries
, если вы не передадите экземпляр entries
(или хотя бы экземпляр entries
) ему в __init__
Однако у него есть доступ к классу Program
через parent
Подход, который я использовал в прошлом, выглядит следующим образом:
class Buttons(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.entries = parent.entries
Таким образом, ваш дочерний класс Buttons
может получить доступ к атрибутам экземпляра Entries
через их общий родительский класс через экземпляр entries
, созданный в Program.__init__()
.
Вы можете обновить класс Entries
__init__
аналогичным образом, чтобы он тоже мог получить доступ к атрибутам из parent
Я также склонен использовать подход, описанный в этом ответе, создавая словарь «общих» переменных в моем корневом классе приложения.
В вашем коде есть несколько проблем:
вы не должны создавать еще один экземпляр Entries
внутри Buttons.calculate()
. Предложить передать экземпляр Buttons
при его создании;
функция self.calculate()
фактически не вызывается в выражении command=lambda: self.calculate
. Вместо этого используйте command=self.calculate
. Та же проблема для command=lambda: self.clear
;
если три входных данных являются числами, вам необходимо преобразовать их в числа, прежде чем выполнять расчет.
Обновленный код:
import tkinter as tk
from tkinter import ttk
class Program(tk.Tk):
def __init__(self, title, size):
super().__init__()
self.title(title)
self.geometry(f"{size[0]}x{size[1]}")
# Program elements split into widget type
self.entries = Entries(self)
self.output = Output(self)
self.buttons = Buttons(self, self.entries) ### pass self.entries to class Buttons
class Entries(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.place(x = 0, y = 0)
# Calling widget generator and placer functions
self.entryGen()
self.entryPlacer()
def entryGen(self): # Create entry widgets
self.firstTerm = ttk.Entry(self)
self.commonDifference = ttk.Entry(self)
self.numberOfTerms = ttk.Entry(self)
def entryPlacer(self): # Place entry widgets
self.firstTerm.pack()
self.commonDifference.pack()
self.numberOfTerms.pack()
class Buttons(ttk.Frame):
def __init__(self, parent, entries): ### added argument entries
super().__init__(parent)
self.place(x = 200, y = 0)
self.entries = entries ### save the passed entries
self.buttonGen()
self.buttonPlacer()
def buttonGen(self):
self.clear = ttk.Button(self, text = "Clear", command = self.clear) ### remove lambda
self.calculate = ttk.Button(self, text = "Calculate", command = self.calculate) ### remove lambda
def buttonPlacer(self):
self.clear.pack()
self.calculate.pack()
def clear(self):
pass
def calculate(self):
try:
### convert inputs to numbers before calculation
print(float(self.entries.firstTerm.get()) + float(self.entries.commonDifference.get()) + float(self.entries.numberOfTerms.get()))
except Exception as ex:
### better show the execption
print(ex)
Спасибо за помощь, работает отлично! Меня смущает, как он не заполняет переменные автоматически, когда вы вводите self.entries.firstTerm, почти как будто его не существует, но, тем не менее, он работает.
Вам нужно определить переменные в
__init__
. Они не определяются без вызова функций.