Прекрасно, что вы используете import tkinter as tk
вместо страшного «звездного» импорта и пытаетесь организовать свой код с помощью классов. Поначалу это может немного сбивать с толку, но делает ваш код более модульным, что очень помогает, особенно когда графический интерфейс становится большим.
Есть несколько проблем с вашим кодом. Наиболее важной является эта строка:
self.statsFrame = tk.Frame(self.myGame).grid()
Метод .grid
(и .pack
и .place
) все возвращают None
. Таким образом, эта строка сохраняет None
в self.statsFrame
, а не виджет Frame. Поэтому, когда вы позже попытаетесь сделать что-то с self.statsFrame
, это не будет делать то, что вы ожидаете.
Другая проблема заключается в том, что атрибут text
вашего self.stat1_amountLabel
не отслеживает значение myChar.stat1
, поэтому при изменении значения myChar.stat1
вам необходимо явно обновить метку с новым значением. В качестве альтернативы, вы могли бы использовать атрибут textvariable
с IntVar
для хранения статистики персонажа. См. Запись для textvariable
в документации Label
config для получения информации.
Ваш character
класс имеет целую кучу атрибутов, таких как name
, experience
и т. Д. В качестве атрибутов класса. Это не очень хорошая идея, потому что атрибуты класса являются общими для всех экземпляров класса. Но вы, вероятно, хотите, чтобы каждый экземпляр персонажа имел свои собственные атрибуты экземпляра. Таким образом, вы должны дать character
__init__
метод, в котором вы устанавливаете эти атрибуты. OTOH, можно использовать атрибуты класса для значений по умолчанию, которые переопределяются атрибутами экземпляра.
В любом случае, вот исправленная версия вашего кода с кнопкой, которая обновляет статистику силы. Я поместил статистику в список, вместо того, чтобы иметь кучу отдельных именованных статистик, которыми нужно будет управлять отдельно. И я дал Game
метод make_stat
, чтобы вы могли легко добавлять строки для других характеристик.
import tkinter as tk
class Character:
def __init__(self, availablePoints=0):
self.name = ""
self.experience = 0
self.level = 0
self.gold = 0
self.stats = [0] * 5
self.availablePoints = availablePoints
def add_stat(self, idx):
if self.availablePoints >= 1:
self.stats[idx] += 1
self.availablePoints -= 1
class Game:
def __init__(self, parent):
self.myParent = parent
self.myGame = tk.Frame(parent)
self.myGame.grid()
self.statsFrame = tk.Frame(self.myGame)
self.statsFrame.grid()
self.make_stat("Strength:", 0, 0)
def make_stat(self, text, idx, row):
label = tk.Label(self.statsFrame, text=text)
label.grid(column=1, row=row)
amount = tk.Label(self.statsFrame, text=myChar.stats[idx])
amount.grid(column=2, row=row)
def update():
myChar.add_stat(idx)
amount["text"] = myChar.stats[idx]
button = tk.Button(self.statsFrame, text="+", command=update)
button.grid(column=3, row=row)
myChar = Character(3)
root = tk.Tk()
myapp = Game(root)
root.mainloop()
Этот код все еще не идеален, но это улучшение. ;) Например, было бы хорошо дать Game
метод для создания новых персонажей, а не создавать их в глобальном контексте. Вы можете сохранить их в атрибуте dict
, равном Game
, используя имя персонажа в качестве ключа.
Вот новая версия, которая работает с отдельными именованными stat
атрибутами. Как я уже говорил в комментариях, сделать это таким образом сложнее (и менее эффективно), чем использовать список для хранения статистики.
import tkinter as tk
class Character:
def __init__(self, availablePoints):
self.name = ""
self.experience = 0
self.level = 0
self.gold = 0
self.stat1 = 0
self.stat2 = 0
self.stat3 = 0
self.stat4 = 0
self.stat5 = 0
self.availablePoints = availablePoints
class Game:
def __init__(self, parent):
self.myParent = parent
self.myGame = tk.Frame(parent)
self.myGame.grid()
self.statsFrame = tk.Frame(self.myGame)
self.statsFrame.grid()
self.make_stat("Strength:", "stat1", 1, 1)
def make_stat(self, text, stat, column, row):
label = tk.Label(self.statsFrame, text=text)
label.grid(column=column, row=row)
amount = tk.Label(self.statsFrame, text=getattr(myChar, stat))
amount.grid(column=(column+1), row=row)
def update():
if myChar.availablePoints >= 1:
v = getattr(myChar, stat) + 1
setattr(myChar, stat, v)
myChar.availablePoints -= 1
amount["text"] = v
button = tk.Button(self.statsFrame, text="+", command=update)
button.grid(column=(column+2), row=row)
myChar = Character(5)
root = tk.Tk()
myapp = Game(root)
root.mainloop()