我是Python新手,目前正在尝试将tkinter用作第一个GUI。我习惯了不上课。这是我第一次使用import tkinter as tk
而不是import *
import tkinter as tk
def update():
pass
#Game.statsFrame #doesn't work Game.statsFrame.stat1_amountLabel too
#Game.stat1_amountLabel #doesnt work < want to use update_idletasks() or
#just type new cofnig...
#just errors like: "Game' has no attribute 'statsFrame" etc #Game
class character:
name = ""
experience = 0
level = 0
gold = 0
stat1 = 0
stat2 = 0
stat3 = 0
stat4 = 0
stat5 = 0
avaiblePoints = 0
def add_stat1(self):
if self.avaiblePoints >= 1:
self.stat1 += 1
self.avaiblePoints -= 1
update()
else:
pass
def add_stat2(self):
if self.avaiblePoints >= 1:
self.stat2 += 1
self.avaiblePoints -= 1
update()
[...]
myChar = character()
myChar.avaiblePoints = 3
class Game:
def __init__(self, parent):
self.myParent = parent
self.myGame = tk.Frame(parent)
self.myGame.grid()
self.statsFrame = tk.Frame(self.myGame).grid()
self.stat1Label = tk.Label(self.statsFrame)
self.stat1Label.config(text="Strength:")
self.stat1Label.grid(column=1, row=1)
self.stat1_amountLabel = tk.Label(self.statsFrame)
self.stat1_amountLabel.config(text=myChar.stat1)
self.stat1_amountLabel.grid(column=2, row=1)
self.add_stat1Button = tk.Button(self.statsFrame)
self.add_stat1Button.config(text="+", command=myChar.add_stat1)
self.add_stat1Button.grid(column=3, row=1)
root = tk.Tk()
myapp = Game(root)
root.mainloop()
但是我无法进入(例如)stat1Label
并在其中使用update_idletasks()
更改文本。就像它不存在。错误表明Game
没有像stat1Label这样的属性。
我想使用它,因为我已经读过__init__
方法更好,并且我想在页面之间切换。我不知道,当我不在tkinter中使用类时,某些事情(像这样)更容易并且没有问题。我很困惑。
答案 0 :(得分:2)
使用import tkinter as tk
代替可怕的“ star”导入,并尝试使用类来组织代码,这是非常好的。刚开始时可能会有些混乱,但是它会使您的代码更具模块化,这将极大地帮助您,尤其是在GUI很大时。
您的代码有一些问题。最重要的是这一行:
self.statsFrame = tk.Frame(self.myGame).grid()
.grid
方法(以及.pack
和.place
)都返回None
。因此,该行将None
保存到self.statsFrame
,而不是Frame小部件。因此,当您以后尝试使用self.statsFrame
做某事时,它不会做您期望的事。
另一个问题是您的text
的{{1}}属性无法跟踪self.stat1_amountLabel
的值,因此,当您更改myChar.stat1
的值时,您需要明确用新值更新标签。另外,您可以使用myChar.stat1
属性和IntVar
来保存角色的属性。有关信息,请参见Label
config docs中textvariable
的条目。
您的textvariable
类具有一堆属性,例如character
,name
等作为类属性。这不是一个好主意,因为类属性由类的所有实例共享。但是您可能希望每个字符实例都具有自己的实例属性。因此,应为experience
提供一个character
方法,以在其中设置这些属性。 OTOH,可以将类属性用于默认值,这些默认值会被实例属性覆盖。
无论如何,这是您的代码的经过修复的版本,其中包含一个用于更新强度统计信息的按钮。我将统计信息放在列表中,而不是拥有一堆必须单独管理的独立命名统计信息。而且我为__init__
提供了一种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
的{{1}}属性中。
这是一个新版本,可用于单独的名为dict
的属性。正如我在评论中说的那样,与使用列表保存统计信息相比,以这种方式进行操作更为复杂(效率更低)。
Game