Kivy - 按钮位置
将小部件放置在适当的位置是设计符合人体工程学的用户界面的关键。在 Kivy 中,按钮(以及其他小部件)的定位主要由使用的布局控制。在本章中,我们将学习如何将按钮放置在 Kivy 应用程序窗口的某个位置。
决定定位的第一个因素是布局。在 Kivy 中,布局是用于以特定方式排列小部件的容器。例如 −
BoxLyout 按垂直或水平顺序顺序放置小部件。
如果您使用 GridLayout,小部件的位置由 rows 和 cols 属性决定。
FloatLayout 对放置没有任何限制。您可以通过分配按钮或任何其他小部件的绝对坐标将其放置在任何位置。
窗口大小
要将按钮放置在某个位置,我们首先定义应用程序窗口的大小。Window 对象的"size"属性可帮助您设置所需的大小。
from kivy.core.window import Window Window.size = (720,400)
Kivy 的窗口坐标系定义了小部件的位置以及发送给它们的触摸事件。它将 (0, 0) 放置在窗口的左下角。显然,窗口的右上角对应于 (1,1)。
Button 类从 Widget 类继承了"pos"和"pos_hint"属性。它们有助于确定按钮在窗口表面上的位置。
位置属性
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。并非所有布局都使用它。
支持定位的布局
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。上方水平框包含四个按钮: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
按下"右"和"左"按钮会导致"x"位置增加或减少 10 个像素。同样,按下"上"和"下"按钮会使"y"值改变 ±10。
示例 1
下面给出了完整代码 −
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()
输出
运行程序时,您应该看到顶部有四个按钮,左下角有一个可移动按钮。按下按钮,可看到可移动按钮改变其位置。
这是另一个演示按钮定位用法的示例。让我们定义一个扩展 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))
示例 2
下面给出了完整代码 −
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()
输出
运行上述代码。按住鼠标按钮并将按钮拖到窗口的任意位置。