将函数变量传递给标签
Posted
技术标签:
【中文标题】将函数变量传递给标签【英文标题】:Pass function variable to label 【发布时间】:2017-07-08 21:03:46 【问题描述】:我在 Kivy 框架上苦苦挣扎了一段时间。我在网上找不到我的问题的答案。
我有两个文件:main.py 和 .kv 文件。 在 main.py 文件中,我在 Boxlayout 中有函数。
例如:
class Box(BoxLayout):
def change(self):
variable = 0
while variable < 10:
text = "Some text " + str(variable)
variable += 1
如你所见,有一个字符串变量“text”,这个变量在每个循环中都不一样。
现在在 .kv 文件中我有一个标签。 例如:
Box:
BoxLayout:
Button:
id: butt
text: ""
on_press: root.change()
Label:
id: label_text
我希望按钮运行函数 change(),并且希望看到标签中显示的“文本”变量的值。 所以用户点击按钮后,他会看到标签上的文字发生变化: “一些文本 0”、“一些文本 1”、“一些文本 2”....“一些文本 9”。
我曾尝试在 main.py 文件中使用标签 ID,例如:
(内部变化函数)
label = self.ids['label_text']
self.count = str(variable)
label.text = "Some text " + self.count
但最终一无所获。 我想我可以在函数末尾使用“返回文本”来做到这一点,但我不想只传递循环中的最后一个“文本”变量。我希望标签在循环期间变量更改时更改文本。
请指教!
【问题讨论】:
【参考方案1】:from kivy.properties import StringProperty
并将您的标签文本定义为label_text = StringProperty()
,这样当您的逻辑发生更改时,它将在 GUI 中更新。
在您的.kv
文件中将text: root.label_text
添加到Label
属性和您的.py
文件中:
class Box(BoxLayout):
label_text = StringProperty()
def change(self):
variable = 0
while variable < 10:
self.label_text = "Some text " + str(variable)
variable += 1
这是关于在 GUI 中更新标签文本值的问题的答案。但不要使用while True
之类的循环或您在代码中使用的循环,因为它会阻止kivy 的GUI 线程自我更新。而是使用 kivy Clock (from kivy.clock import Clock
) 来安排任务并以特定的时间间隔运行它,这样 GUI 线程就不会被阻塞。类似的东西
class Box(BoxLayout):
label_text = StringProperty()
interval = 0.5 # Second
offset = 0
def change(self):
# You ask the clock to update the label's value every self.interval (0.5) second
self.event = Clock.schedule_interval(self.update_label_text, self.interval)
def update_label_text(self, dt):
if self.offset < 10:
self.label_text = "some_text" + str(self.offset)
self.offset += 1
else:
# Finally ask the clock to forget about updating
Clock.unschedule(self.event)
【讨论】:
谢谢。这解决了我的问题,但是……我仍然不是 100% 清楚这到底是如何工作的。你能推荐一些好的kivy教程吗? @Maciejjy 如果它有效,接受并投票回答会很好:) 你拿了这个吗? kivy.org/docs/tutorials/pong.html 当然。但我不能投票。收到一些消息,对于代表少于 15 的用户,不要更改帖子分数。 没关系。教程呢?你拿了吗? 只是检查一下。看起来不错,它涵盖了我需要的东西。谢谢!【参考方案2】:在标签中显示文本仍然存在一些问题。使用简短的功能,一切似乎都很好,但我有很多打开文件、ifs 和写入数据库的功能:
def add_to_base(self, dt):
self.adding = "Adding to database..."
with open("new_links.txt", "r", encoding='utf-8') as f:
for line in f:
working on html here
xxx = got list of string here
for x in xxx:
if ....
zzz = got another list with string
for i in xxx:
if
.
.
Lots of elif's
write element to database
print("Added to databes")
if element is last element:
Clock.unschedule(self.event)
当然,这不是实际代码,只是对它的工作方式进行建模。 我想从此函数显示和更新“self.adding”文本。 在 .kv 文件中,我有带有文本的标签:self.adding 属性。 在运行这个 add_to_base 函数时:
def update_base(self):
self.event = Clock.schedule_interval(self.add_to_base, self.interval)
问题是,文本显示在标签上,但在此函数的最后。此函数需要很长时间才能完成(大约需要 15 分钟来处理元素并将它们添加到数据库中),并且当函数完成时,会显示文本。我想在一开始就显示这个文本。
【讨论】:
函数add_to_base()
会阻塞kivy GUI 线程,直到它完成。正如我所说,避免使用 for
和 while
运行此类循环,并使用 kivy Clock 为您安排它们。我建议将文件的所有行添加到Queue()
,然后安排一个间隔从Queue()
读取并对其进行操作,而不是您所做的阻止GUI 线程的那个。阅读关于 python Queue()
哦,好的。所以如果我们有很长的函数要结束(比如 15 分钟),那么 kivy.Clock 不能比每 15 分钟更快地刷新这个函数的任何变量?在这种情况下,间隔并不重要,因为它小于函数时间?
不知何故,我的意思是把任务分解成更小的任务,然后让时钟每隔一段时间完成每个任务。以上是关于将函数变量传递给标签的主要内容,如果未能解决你的问题,请参考以下文章
将变量传递给函数\使用该变量返回一个新值\重复直到值达到 0