我正在使用calculator tutorial from RealPython,并且每当父窗口小部件的宽度小于我的Label小窗口中的texture_size时,我都希望缩放Label子窗口小部件的画布。在我的代码中,我的Lable位于布局中,因此其位置和大小取决于其父项。
[我正在KvLang that scales a child widget well中获取一些代码,并在Python中实现它,以便更好地理解Kivy的编码。
[每当父窗口小部件位置发生变化时,我都会调用我孩子的check_canvas()方法来运行其画布指令,在那里我调用Scale,但它似乎对我的Label中的文本没有任何作用。
如何使用Python代码中的Scale调整myTextInput画布的大小? (我有意避免使用KvLang)
这是我的代码中涉及我要完成的部分
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.graphics import PushMatrix,PopMatrix,Scale
class myTextInput(Label):
def __init__(self, **kwargs):
super(myTextInput,self).__init__(**kwargs)
def check_canvas(self):
if self.texture_size[0] < self.width:
self._scale = 1
else:
self._scale = float(self.width) / self.texture_size[0]
self.text = 'my scale text here (%d, %.2f)' % (self.width, self._scale)
with self.canvas.before:
PushMatrix()
Scale(
origin = self.center,
x = self._scale or 1,
y = self._scale or 1
)
with self.canvas.after:
PopMatrix()
class MainApp(App):
def build(self):
self.operators = ["/", "*", "+", "-"]
self.last_was_operator = None
self.last_button = None
main_layout = BoxLayout(orientation="vertical")
self.solution = myTextInput(font_size= main_layout.height * 0.5)
def callback_size(instance, value):
print('The widget', instance, 'sized to', value)
print('The widget', instance, 'texture_size[0] is', instance.texture_size[0])
#What I have noted here is that the texture_size[0] and size
#are responsive but not _scale and canvas operations.
#I made check_canvas() to 'enforce' a check on _scale and canvas operation but
#although now I see _scale changing, canvas operations are not showing any result
instance.check_canvas()
print('The widget', instance, '_scale is', instance._scale)
self.solution.bind(size = callback_size)
main_layout.add_widget(self.solution)
self.solution = myTextInput(font_size= main_layout.height * 0.5)
在执行该行时将font_size
的myTextInput
设置为main_layout
高度的一半。由于该行以build()
方法执行,因此在实际显示main_layout
之前,其height
是默认的100
,因此font_size
设置为50
。不管font_size
的大小如何,myTextInput
都不会改变。Scale
指令仅更改myTextInput
的大小,而不更改font_size
。如果您在kv
中设置:
font_size: main_layout.height * 0.5
((假设main_layout
中定义了kv
),则每当font_size
的height
更改时,都会调整main_layout
。那是对kv
语言的补充。如果您使用Python进行此操作,则必须自己进行处理。您可以通过在font_size
方法中添加代码来调整check_canvas()
来做到这一点:
def check_canvas(self, main_layout): if self.texture_size[0] < self.width: self._scale = 1 else: self._scale = float(self.width) / self.texture_size[0] self.text = 'my scale text here (%d, %.2f)' % (self.width, self._scale) # adjust the font_size self.font_size = main_layout.height * 0.1 with self.canvas.before: PushMatrix() Scale( origin = self.center, x = self._scale or 1, y = self._scale or 1 ) with self.canvas.after: PopMatrix()
请注意,修改后的check_canvas()
以main_layout
作为参数,因此对该方法的调用必须在callback_size()
中更改为:
instance.check_canvas(main_layout)
我已经将font_size
的系数从0.1
更改为0.5
,因为这看起来很大。
Matrix
的方法,但是计算字体大小以适合myTextInput
的宽度:from kivy.core.text import Label as CoreLabel
.
.
.
def check_canvas(self):
if self.texture_size[0] < self.width:
self._scale = 1
else:
self._scale = float(self.width) / self.texture_size[0]
self.text = 'my scale text here (%d, %.2f)' % (self.width, self._scale)
# adjust the font_size
self.font_size = self.calculate_font_to_fit(self.text, self.width)
# need to clear the canvas instructions, or they just keep accumulating
self.canvas.before.clear()
self.canvas.after.clear()
with self.canvas.before:
PushMatrix()
Scale(
origin = self.center,
x = self._scale or 1,
y = self._scale or 1
)
with self.canvas.after:
PopMatrix()
def calculate_font_to_fit(self, text, width):
# use core.text.Label to calculate size of a Label with given font and text
self.core_label = CoreLabel(text=text, font_name=self.font_name, font_size = self.font_size)
self.core_label.refresh()
curr_width = self.core_label.texture.width
new_font_size = int(self.font_size)
if curr_width > width:
# reduce font size
while curr_width > width:
new_font_size -= 1
self.core_label = CoreLabel(text=text, font_name=self.font_name, font_size = new_font_size)
self.core_label.refresh()
curr_width = self.core_label.texture.width
elif curr_width < width:
# increase font size
while curr_width < width:
old_font_size = new_font_size
new_font_size += 1
self.core_label = CoreLabel(text=text, font_name=self.font_name, font_size = new_font_size)
self.core_label.refresh()
curr_width = self.core_label.texture.width
new_font_size = old_font_size
return new_font_size