相对于布局放置和移动一组带有 kivy 的图像
Posted
技术标签:
【中文标题】相对于布局放置和移动一组带有 kivy 的图像【英文标题】:Placing and moving a group of images with kivy relative to the layout 【发布时间】:2015-07-19 23:19:00 【问题描述】:我正在尝试使用 raspberry pi 和 kivy 库创建某种交互式“墙”。
我想在另一个下方垂直显示图像(以后可能还有文本),并在按键上上下移动它们。一种滚动行为,但我想显示许多图像,所以我不想一次加载所有图像并使用滚动视图。
所以我使用 FloatLayout 并在按键后更改图像的位置。我的第一个问题是,我必须使用 Window.width / Window.height 而不是 size_hint / pos_hint 进行操作。我尝试使用 kivy FloatLayout 文档中的示例,但没有成功。
我的问题是,按键后图像会移动,但它们也会改变大小。这是我正在使用的代码。
编辑:
我意识到添加 size_hint=(None, None) 将保持图像大小。这仅表明在布局中使用图像的相对定位和大小可能会更好。如前所述,FloatLayout 文档中的示例对我不起作用。
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.core.window import Window
class Wall(FloatLayout):
def __init__(self, **kwargs):
super(FloatLayout, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
if not self._keyboard:
return
self._keyboard.bind(on_key_down=self.on_keyboard_down)
self.posts = list()
self.orientation = 'vertical'
spacing = 25
post = Image(source='test.png',
allow_stretch=True,
keep_ratio=True,
size=(Window.width * 0.2z, Window.height * 0.2),
center=(Window.width * 0.6, Window.height * 0.5))
print '#####\nOriginal size and position: width/height', post.width, post.height, ' position x/y', post.x, post.y
self.posts.append(post)
self.add_widget(post)
while self.posts[-1].y + self.posts[-1].height <= Window.height:
post = Image(source='test.jpg',
allow_stretch=True,
keep_ratio=True,
size=(Window.width * 0.2, Window.height * 0.2),
pos=(self.posts[-1].x, self.posts[-1].y + self.posts[-1].height + spacing))
print '#####\nOriginal size and position: width/height', post.width, post.height, ' position x/y', post.x, post.y
self.posts.append(post)
self.add_widget(post)
def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None
def on_keyboard_down(self, keyboard, keycode, text, modifiers):
key = keycode[1]
for post in self.children:
if key == 'up':
post.y -= 50
print '#####\nNew size and position: width/height', post.width, post.height, ' position x/y', post.x, post.y
elif keycode[1] == 'down':
post.y += 50
elif key == 'q':
App.get_running_app().stop()
#else:
# return False
#return True
return True
class MessageBoard(App):
def build(self):
return Wall()
if __name__ == '__main__':
MessageBoard().run()
【问题讨论】:
【参考方案1】:我找到了一个使用 RelativeLayout 并使用 pos_hint / size_hint 属性的解决方案。积极的副作用是,即使窗口调整大小,元素也会保持其大小/位置。
我仍然需要计算绝对坐标来确定元素的位置。缺点是,在 init() 方法中,父元素的大小是未知的,所以我必须使用窗口大小和坐标。如果我的墙不是根元素,这将失败。
元素的移动需要通过pos_hint属性的设置来完成,改变绝对坐标不会产生任何影响。
class ImageAndText(RelativeLayout):
pass
class Wall(FloatLayout):
def __init__(self, **kwargs):
super(Wall, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
if not self._keyboard:
return
self._keyboard.bind(on_key_down=self.on_keyboard_down)
self.posts = list()
post = ImageAndText()
post.size_hint = 1, 0.3
post.size = (Window.width, Window.height * 0.3) # needs to be set in order to determine the absolute size
post.center_y = Window.height * 0.5 # needs to be set in order to determine the absolute coordinates
post.pos_hint = 'center_y': 0.5
self.add_widget(post)
self.posts.append(post)
while self.posts[-1].top <= Window.height:
#print 'Old post top:', self.posts[-1].top
post = ImageAndText()
post.size_hint = 1, 0.25
post.size = (Window.width, Window.height * 0.25)
post.y = self.posts[-1].top # just above the first one
post.pos_hint = 'center_y': post.center_y/Window.height
self.add_widget(post)
self.posts.append(post)
def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None
def on_keyboard_down(self, keyboard, keycode, text, modifiers):
key = keycode[1]
for post in self.posts:
if key == 'up':
post.pos_hint = 'center_y': post.pos_hint['center_y']+0.1
elif keycode[1] == 'down':
post.pos_hint = 'center_y': post.pos_hint['center_y']-0.1
elif key == 'q':
App.get_running_app().stop()
return True
class MyTestApp(App):
def build(self):
return Wall()
if __name__ == "__main__":
MyTestApp().run()
这是描述 ImageAndText 元素的 .kv 文件。
<ImageAndText>:
Label:
font_size: '14sp'
text: 'Lorem ipsum dolor sit'
color: (1, 1, 1, 1)
text_size: (self.parent.width*0.25, None)
pos_hint: 'center_x': 1.0/6 # set the center to 1/6 of parents width
Image:
source: 'test.png'
pos_hint: 'center_x': 2.0/3, 'center_y': .5
size_hint: 0.5, 0.95 # the height will be the same as the parent, the width 0.5 because of the label
allow_stretch: True
【讨论】:
以上是关于相对于布局放置和移动一组带有 kivy 的图像的主要内容,如果未能解决你的问题,请参考以下文章