Kivy 简明教程
Kivy - Button Position
将控件放置在适当的位置是设计符合人体工学用户界面的关键所在。在 Kivy 中,按钮的定位(以及其他控件的定位)主要受布局的控制。在本章节中,我们将学习如何在 Kivy 应用窗口的指定位置放置按钮。
第一个决定定位的因素是布局。在 Kivy 中,布局是用于以特定方式排列控件的容器。例如,
-
BoxLyout 顺序放置控件,垂直或水平顺序均可。
-
如果您使用 GridLayout ,则控件位置由 rows 和 cols 属性决定。
-
FloatLayout 没有对放置做出限制。您可以通过指定绝对坐标将按钮或任何其他控件放置在任何位置。
Window size
要将按钮放置在特定位置,我们首先定义应用程序窗口的大小。“size”属性的 Window 对象可帮助您设置所需的大小。
from kivy.core.window import Window
Window.size = (720,400)
Kivy 的窗口坐标系定义了控件的位置及其发送给他们的触摸事件。它在窗口的左下角放置 (0, 0)。窗口的右上角与 (1,1) 相对应,这很明显。
Button 类从 Widget 类继承了“pos”和“pos_hint”属性。它们有助于确定按钮在窗口表面上的位置。
Position properties
pos - 该属性是水平和垂直轴上的坐标值“x”和“y”的元组,基于窗口的左下角来衡量。例如,
button = Button(text ='Hello world', pos =(20, 20))
pos_hint - 该属性为控件的位置提供提示。它允许您在父布局内设置控件的位置。该属性是一个最多包含 8 个键来确定位置的字典 -
-
x
-
y
-
left
-
right
-
top
-
bottom
-
center_x
-
center_y
键“x”、“right”和“center_x”将使用父宽度。键“y”、“top”和“center_y”将使用父高度。例如,如果您希望按钮的顶部位于其父布局的高度的 10%,则可以编写 -
button = Button(text ='Hello world', pos_hint={'top': 0.1})
“pos_hint”是 ObjectProperty。并非所有布局都使用它。
Layouts supporting positioning
-
FloatLayout - 支持 “pos_hint”属性。这些值介于 0 和 1 之间的数字,表明与窗口大小的比例。
-
RelativeLayout - 定位属性(pos、x、center_x、right、y、center_y 和 top)相对于布局大小,而不是窗口大小。
-
BoxLayout - 仅“x”键(x、center_x 和 right)在垂直方向上起作用,而(y、center_y、top)在水平方向上起作用。固定的定位属性(pos、x、center_x、right、y、center_y 和 top)也适用相同的规则。
在以下代码中,我们在上方的垂直 BoxLayout 内放置了水平 BoxLayout 和 FloatLayout。水平的 BoxLayout 包含四个按钮:LEFT、RIGHT、TOP 和 BOTTOM。在 FloatLaout 内,我们有一个用“pos”属性放置的按钮。
App 类有一个名为 movebtn() 的方法,该方法可识别被按下按钮的标题,并更改按钮的“x”或“y”位置
def movebtn(self,instance):
if instance.text =='RIGHT':
self.btn.pos[0]=self.btn.pos[0]+10
if instance.text == 'LEFT':
self.btn.pos[0] = self.btn.pos[0]-10
if instance.text == 'UP':
self.btn.pos[1] = self.btn.pos[1]+10
if instance.text == 'DOWN':
self.btn.pos[1] = self.btn.pos[1]-10
按 RIGHT 和 LEFT 按钮会导致“x”位置增加或减少 10 个像素。类似地,TOP 和 BOTTOM 按钮将“y”值更改为 ±10。
Example 1
complete code 如下所示 -
from kivy.app import App
from kivy.uix.button import Button
from kivy.config import Config
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
Config.set('graphics', 'width', '720')
Config.set('graphics', 'height', '400')
Config.set('graphics', 'resizable', '1')
class MovableButtonApp(App):
def movebtn(self,instance):
if instance.text =='RIGHT':
self.btn.pos[0]=self.btn.pos[0]+10
if instance.text == 'LEFT':
self.btn.pos[0] = self.btn.pos[0]-10
if instance.text == 'UP':
self.btn.pos[1] = self.btn.pos[1]+10
if instance.text == 'DOWN':
self.btn.pos[1] = self.btn.pos[1]-10
def build(self):
mblo = BoxLayout(orientation='vertical')
blo = BoxLayout(orientation ='horizontal')
b1 = Button(text='LEFT')
b1.bind(on_press=self.movebtn)
b2 = Button(text = 'RIGHT')
b2.bind(on_press=self.movebtn)
b3 = Button(text = 'UP')
b3.bind(on_press=self.movebtn)
b4 = Button(text = 'DOWN')
b4.bind(on_press=self.movebtn)
blo.add_widget(b1)
blo.add_widget(b2)
blo.add_widget(b3)
blo.add_widget(b4)
mblo.add_widget(blo)
flo = FloatLayout()
self.btn = Button(text='Movable Button', size_hint= (.350, .150))
flo.add_widget(self.btn)
mblo.add_widget(flo)
return mblo
MovableButtonApp().run()
Output
运行程序时,顶部应显示四个按钮,左下角要有一个可移动按钮。单击按钮,即可查看可移动按钮如何改变其位置。
以下是演示按钮定位使用方法的另一个示例。让我们定义一个扩展了 Button 类别的 MovableButton 类别。我们定义了 on_touch_down()、on_touch_up() 和 on_touch_move() 方法来处理触摸事件。
on_touch_down() 方法检查触摸事件是否在按钮范围内发生,通过将小部件设置为当前触摸目标来处理触摸事件。
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
touch.grab(self)
return True
return super().on_touch_down(touch)
如果触摸事件正由我们的按钮处理,则使用 on_button_move() 方法更新其位置 -
def on_touch_move(self, touch):
if touch.grab_current == self:
self.pos = (self.pos[0] + touch.dx, self.pos[1] + touch.dy)
最后,释放作为当前触摸目标的按钮,并处理触摸事件。
def on_touch_up(self, touch):
if touch.grab_current == self:
touch.ungrab(self)
return True
return super().on_touch_up(touch)
build() 方法仅使用位于 left_bottom 位置的按钮构建窗口
def build(self):
return MovableButton(text='Drag me', size_hint= (.250, .100))
Example 2
complete code 如下所示 -
from kivy.app import App
from kivy.uix.button import Button
from kivy.config import Config
from kivy.uix.floatlayout import FloatLayout
Config.set('graphics', 'width', '720')
Config.set('graphics', 'height', '300')
Config.set('graphics', 'resizable', '1')
class MovableButton(Button):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
touch.grab(self)
return True
return super().on_touch_down(touch)
def on_touch_move(self, touch):
if touch.grab_current == self:
self.pos = (self.pos[0] + touch.dx, self.pos[1] + touch.dy)
# Override the on_touch_up method to update
# the widget's position when the touch event ends
def on_touch_up(self, touch):
if touch.grab_current == self:
touch.ungrab(self)
return True
return super().on_touch_up(touch)
class TestApp(App):
def build(self):
return MovableButton(text='Drag me', size_hint=(.250, .100))
if __name__ == "__main__":
TestApp().run()