所以我正在使用Kivy GUI编写程序,我真的不想使用.kv文件,而是将它全部写在python文件中。问题是在MainScreen
类里面我想添加一些标签,但是根据窗口大小的变化我不能让它们的文本换行。当我尝试self.size
时,我只获得100x100。我已经尝试了Kivy教程书中的所有建议,但没有任何效果。我知道我可以使用\n
创建文本多行或设置标准标签大小,但这不是一个真正的解决方案。我需要标签大小和文本来跟踪整个窗口的更改和要包装的文本。
我简化了程序,只关注这个问题。
以下是代码:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.graphics import Rectangle, Color
class MainScreen(FloatLayout):
"""MAIN WINDOW CLASS"""
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
with self.canvas.before:
Color(0.988, 0.725, 0.074, 1, mode='rgba')
self.rect = Rectangle(pos=self.pos, size=self.size)
self.bind(size=self.update_rect)
#TITLE LABEL
self.add_widget(Label(text="A very Long Sentence that needs to be wrapped.",
bold = True,
font_size="20sp",
pos_hint={'center_x': 0.5, 'center_y': .85},
size_hint=(None, None),
halign="center",
color=(0.055, 0.235, 0.541, 1)))
def update_rect(self, *args):
"""FUNCTION TO UPDATE THE RECATANGLE OF CANVAS TO FIT THE WHOLE SCREEN OF MAINSCREEN ALWAYS"""
self.rect.pos = self.pos
self.rect.size = self.size
class main(App):
"""BUILDING THE APP"""
def build(self):
return MainScreen()
if __name__ == "__main__":
main().run()
谢谢。
答案 0 :(得分:5)
首先,让我告诉你,你将使你的生活变得更加艰难,kv不难学,并且它允许kivy为你做更多繁重的工作。
在kv中,做类似
的事情Label:
text: 'blah blah ' * 1000
text_size: self.width, None
size_hint: 1, None
height: self.texture_size[1]
通常可以解决问题,因为小部件使用其容器的整个宽度,并且text_size被绑定到其宽度,每次此宽度更改时都会重新计算纹理,并且窗口小部件的高度将自动适合纹理的高度。
现在,在没有kv的情况下做同样的事。
label = Label(text='blah blah '* 1000, size_hint=(1, None))
label.bind(
width=lambda *x: label.setter('text_size')(label, (label.width, None),
texture_size=lambda *x: label.setter('height')(label, label.texture_size[1]))
也就是说,你需要明确地告诉kivy它必须对标签的各种属性的变化作出反应,并重新计算其他属性的值,而使用kv时,它会自动检测到某些值依赖于其他属性,并且会知道它需要自己绑定它们。
setter
是一个实用函数,它允许你在简单的情况下避免定义setter函数,如果没有它,在这里,你必须为每个绑定定义一个函数,并执行类似&#的操作34; self.text_size = self.width,None"在他们中间,因为lambda不允许分配。
kv存在的一个原因是,它允许自己处理代码中的表达式,并检测依赖关系,如果你在python中完成所有操作,kivy就无法检测到这样的依赖关系,因为python本身不会#39; t关心他们,并没有告诉kivy他们。
现在,如果你想告诉我们你为什么要避免使用kv,请这样做,但我很确定这些原因来自缺乏了解kv而不是真正的问题。
答案 1 :(得分:0)
因此,在对我的问题进行了大量思考并尝试不同的方法之后,我最终得到了一个正确的"只是python"溶液
首先,我的回答是基于1)官方的Kivy Tutorials建议,2)画布方法的常用操作和3)对可变范围的小心处理。
因此标签设置类似于Kivy教程书所建议的设置。需要有一个函数来更新Label位置及其文本大小(此处为setting_function
)以与Label大小绑定。我还将Label分配给变量,以便稍后可以轻松引用它。
完成所有这些更改后,我的代码如下所示:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.graphics import Rectangle, Color
class MainScreen(FloatLayout, Label):
"""MAIN WINDOW CLASS"""
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
with self.canvas.before:
Color(0.988, 0.725, 0.074, 1, mode='rgba')
self.rect = Rectangle(pos=self.pos, size=self.size)
self.bind(size=self.update_rect)
#TITLE LABEL
self.titlos = Label(text="A very Long Sentence that needs to be wrapped.",
bold = True,
text_size=(None,None),
font_size="20sp",
pos_hint={'center_x': 0.5, 'center_y': .85},
size_hint_y=None,
size = self.size,
height=self.texture_size[1],
halign="center",
valign = "middle",
color=(0.055, 0.235, 0.541, 1))
self.add_widget(self.titlos)
self.titlos.bind(size=self.setting_function)
def setting_function(self, *args):
"""FUNCTION TO UPDATE THE LABEL TO ADJUST ITSELF ACCORDING TO SCREEN SIZE CHANGES"""
self.titlos.pos_hint = {'center_x': 0.5, 'center_y': .85}
self.titlos.text_size=self.size
def update_rect(self, *args):
"""FUNCTION TO UPDATE THE RECATANGLE OF CANVAS TO FIT THE WHOLE SCREEN OF MAINSCREEN ALWAYS"""
self.rect.pos = self.pos
self.rect.size = self.size
class main(App):
"""BUILDING THE APP"""
def build(self):
return MainScreen()
if __name__ == "__main__":
main().run()
上面的代码确实符合我在问题中设置的要求。它很容易用于您自己的项目。只需要处理变量'范围和使用大量的打印消息进行检查。
最后我想用Python来解决这个问题的原因(而不仅仅是使用kivy语言来处理像蛋糕这样的问题)是因为我想要在运行时动态改变变量,用作Label参数。我也必须找出因为我很固执。
谢谢。
答案 2 :(得分:0)
我会利用奇怪的OOP。
您可以像这样创建类:
class WrappedLabel(Label):
# Based on Tshirtman's answer
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(
width=lambda *x:
self.setter('text_size')(self, (self.width, None)),
texture_size=lambda *x: self.setter('height')(self, self.texture_size[1]))
然后在您想要“包装行为”的代码的任何部分使用您的类。 示例:
my_label = WrappedLabel(text="A very L" + "o"*200 + "ng Sentence that needs to be wrapped.",
bold=True,
font_size="20sp")