gpt4 book ai didi

python - 如何从 tkinter 中的特定网格位置检索值?

转载 作者:行者123 更新时间:2023-12-01 08:00:09 25 4
gpt4 key购买 nike

我正在开发我的第一个 GUI 项目,并且我已将我的代码放在帖子的底部(这是一项正在进行的工作,因此请容忍代码中的任何丑陋或低效率)。

我正在制作一个 GURPS 角色表,它将自动为我的玩家创建角色,然后(尽管尚未实现)生成一个格式良好的 PDF。

按照程序当前的工作方式,我有一些函数可以根据属性、派生属性或技能中所需的排名执行成本计算。按下“计算”按钮,然后会显示出获得所需级别的属性或技能的点成本。

我使用类定义末尾附近的 while 循环生成行。循环调用函数,告诉程序创建执行某种类型计算的行。

根据选择,所有输出值都显示在每行的第 4 列中。我想知道是否有一种方法可以让我轻松找到这些列和行的值,而无需跟踪这些值。也许是一种方法,例如 .grid(column,row).get() 或可以返回某个特定网格位置中的任何内容的方法。

class Character_sheet:
#Our default class which will house our character sheet.
def __init__(self):

#Total Point Calculator?
def sum_of_values():
list = self.grid_slaves(column=3)
sum = 0
for each in list:
sum += int(each["text"])
total_cost.set(sum)


#Generators for Rows and Columns.
def attr_widget_10(index):
#The below syntax/structure works.
def attr_10():
cost.set((rank.get()-10)*10)
return None
rank = IntVar()
rank.set(10)
cost = IntVar()
input = ttk.Entry(self.window, textvariable = rank).grid(column=2, row=index)
ttk.Button(self.window, text='Calculate', command=attr_10).grid(column=3,row=index)
ttk.Label(self.window, width=7, textvariable=cost).grid(column=4,row=index)
return None

def attr_widget_20(index):
def attr_20():
cost.set((rank.get()-10)*20)
return None
rank = IntVar()
rank.set(10)
cost = IntVar()
input = ttk.Entry(self.window, textvariable = rank).grid(column=2, row=index)
ttk.Button(self.window, text='Calculate', command=attr_20).grid(column=3,row=index)
ttk.Label(self.window, width=7, textvariable=cost).grid(column=4,row=index)

def derived_attr_widget(dictionary, index):
return None

def skill_widget(dictionary, index):
return None

def total_cost():

return None

#Basic window functions.
self.root = tk.Tk()
self.root.title('GURPS Character Sheet')
self.window = ttk.Frame(self.root)
self.window.grid()
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)

"""Core Functionality:
Below are labels for set attributes. Each references an appropriate calculator.
This does not address skills.

For now, inputs start on row 1.
"""
#Labels for attributes and derived attributes.
#ATTRIBUTES
ttk.Label(self.window, width=10, text='Strength').grid(column=1, row=1)
ttk.Label(self.window, width=10, text='Health').grid(column=1, row=2)
ttk.Label(self.window, width=10, text='Intelligence').grid(column=1, row=3)
ttk.Label(self.window, width=10, text='Dexterity').grid(column=1, row=4)
#DERIVED ATTRIBUTES
ttk.Label(self.window, width=10, text='HP').grid(column=1,row=5)
ttk.Label(self.window, width=10, text='FP').grid(column=1,row=6)
ttk.Label(self.window, width=10, text='Will').grid(column=1,row=7)
ttk.Label(self.window, width=10, text='Perception').grid(column=1,row=8)
ttk.Label(self.window, width=10, text='Basic Speed').grid(column=1,row=9)
ttk.Label(self.window, width=10, text='Basic Move').grid(column=1,row=10)



index = 1
while index <= 2:
attr_widget_10(index)
index += 1
while index <= 4:
attr_widget_20(index)
index += 1
total_cost = IntVar()
#ttk.Button(self.window, text='Total Cost', command=sum_of_values).grid(column=2,row=index+1)
#ttk.Label(self.window, width=7, textvariable=total_cost).grid(column=4,row=index+1)


###CREATES WINDOW###
self.window.mainloop()

最佳答案

有几点需要注意:

  • stovfl 的评论回答了所写的问题
  • 我完全同意 Furas 关于将 gui 与逻辑完全分离的评论。你的代码应该被重构 - imo - 以便工作表 GUI 应该作为统计的抽象集合与字符分开,并且也应该与执行/管理 GUI 的代码分开(目前全部在 Character_sheet类)。

虽然我将把 Character_sheet 完全解开给您,但我们至少可以帮助您开始开发用于访问 GUI 中的值的模式。

前 4 行中的每一行代表用户可以更改并与您已创建的标签相关的统计信息。其中两个统计数据的成本修正值为 10,另外两个统计数据的修正值为 20。

## Place in the global space for the time being
BASE_STATISTICS = ["Strength","Health","Intelligence","Will"]
## Note that prior to Python 3.7 dictionary order was not guaranteed, so
## collections.OrderedDict would be preferable for versions before that
STATISTIC_COSTS = {"Strength":10,"Health":10,"Intelligence":20,"Will":20}

( collections.OrderedDict )

据推测,每个给定的字符表都有自己独立的小部件和这些统计数据的值。同样,您应该重写代码以使其更加独立,但现在我们将保留尽可能多的代码。

## Place at the top of Character_sheet.__init__
## The value for each stat is a dictionary in order to store arbitrary data until the code is reworked further
self.base_stats = {stat:{} for stat in BASE_STATISTICS}

通过这些添加,我们现在有了一个框架,可以引用您正在创建的小部件行并确定这些统计信息的成本修改器。

## This will replace the Label and attr_widget_X loops and functions
## You can place it where the Attributes labels currently are, and delete both attr_widget_x functions
## enumerate pairs each element of an iterable with a sequential integer
for i,stat in enumerate(BASE_STATISTICS):
## These IntVars are useful, so we'll keep them around
rank = IntVar()
rank.set(10)
cost = IntVar()

## We'll set up the gui just like you did, just with a minor tweak
ttk.Label(self.window, width=10, text=stat).grid(column=1, row=i)
ttk.Entry(self.window, textvariable = rank).grid(column=2, row=i)
## I've removed the Generate button for reasons I'll get into below
ttk.Label(self.window, width=7, textvariable=cost).grid(column=3,row=i)

## Here we save all our references so that we can come back to them later
## self.base_stats[stat]['row'] will tell us which row of the grid the widgets are located
## self.base_stats[stat]['rank'] will now give us direct access to the rank IntVar at all times
## self.base_stats[stat]['cost'] likewise gives us easy access to the cost IntVar whenever we need it
self.base_stats[stat].update({'row':i,'rank': rank,'cost':cost})

( enumerate )

Tkinter 使您可以访问不同的信号类型;专门针对我们的用途,tkinter 变量 可以使用它们的 trace method 进行绑定(bind)。通过使用'w'模式,只要Variable发生变化,就会调用给定的回调(函数)。使用此功能,我们无需不断点击生成按钮,从而使 GUI 的响应速度更快。

## This should go right after "cost = IntVar()"
## The lambda statement here is technically the function that is being passed to trace
## The lambda itself is capturing all information it gets passed as e
## stat = stat creates a reference within the lambda definition to the current value of stat
## (as you iterate, the stat value in the local scope will change, so we need to preserve it)
## and then calling self.updatestat and passing that the stat we're updating.
rank.trace('w',lambda *e,stat = stat: self.updatestat(stat))

( lambda )

现在我们可以添加 Character_sheet.updatestat 以便它真正发挥作用:

def updatestat(self,stat):
""" Queries the current value of the stat's rank and then sets the cost appropriately """
## Get the IntVar for the given stat from your stats dict
rankvar = self.base_stats[stat]['rank']
## Since we're using an Entry (instead of e.g.- a spinbox), there's
## no garauntee that it contains a valid integer, so we use try/except
## to catch the mistake
try:
rank = rankvar.get()
rank = int(rank)
except:
## We'll reset the value if it's invalid
rank = 10
rankvar.set(rank)

## Use STATISTIC_COSTS to determine the cost modifier
## Calculate cost
cost = (rank - 10)*STATISTIC_COSTS[stat]

## find our IntVar for the given stat
costvar = self.base_stats[stat]['cost']
## Set it to cost
costvar.set(cost)

## Note that "return None" is the implicit default

这让您更接近将 GUI 与编程逻辑分离,同时允许您像您试图做的那样引用行和列中的这些值(即 - self.stats['Strength ']['rank'].get())

关于python - 如何从 tkinter 中的特定网格位置检索值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55773766/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com