我正在尝试使用带有a的自定义小部件GridLayout,但结果始终是角落中的一个非常小的网格,而不是整个窗口中的网格扩展.
示例代码:
import kivy
kivy.require('1.5.1')
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
class MyWidget(Widget):
def __init__(self):
super(MyWidget, self).__init__()
grid_layout = GridLayout(cols=3)
grid_layout.add_widget(Button(text='A'))
grid_layout.add_widget(Button(text='B'))
grid_layout.add_widget(Label(text='text'))
grid_layout.add_widget(Label(text='other'))
grid_layout.add_widget(Button(text='text'))
self.add_widget(grid_layout)
class MyApp(App):
def build(self):
float =
return MyWidget()
MyApp().run()
Run Code Online (Sandbox Code Playgroud)
因为它Widget的默认值size_hint是(1,1)它应该在整个窗口中展开,而且GridLayout也是.为什么这不会发生?我怎样才能获得我想要的结果?
`class MyWidget(Widget):`
Run Code Online (Sandbox Code Playgroud)
你的根小部件是MyWidget从一个继承Widget,而不是从布局之一,因此不控制它的孩子的尺寸如前所述这里,"该size_hint是使用值的元组的布局来管理他们的孩子的大小".
您的根小部件确实占用了窗口的整个空间.您可以通过向画布中添加一个Rectangle来测试这个,MyWidget例如::
with self.canvas.before:
Color(1,0,0,1)
Rectangle(pos=self.pos, size=self.size)
Run Code Online (Sandbox Code Playgroud)
你应该熟悉canvas,canvas.before和canvas.after.它们基本上是指令组,前面的组是在窗口小部件的画布指令之前和之后的组之后绘制的.
Kivy的一个关键不同之处在于小部件的大小调整/布局会延迟到下一帧,所以如果你只是将上面的代码片段添加到你的代码中,那么::
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import *
class MyWidget(Widget):
def __init__(self, **kwargs):
# I'd make sure to pass of kwargs through to the super
# as there are widgets's that process their initial
# arguments through.
super(MyWidget, self).__init__(**kwargs)
grid_layout = GridLayout(cols=3)
grid_layout.add_widget(Button(text='A'))
grid_layout.add_widget(Button(text='B'))
grid_layout.add_widget(Label(text='text'))
grid_layout.add_widget(Label(text='other'))
grid_layout.add_widget(Button(text='text'))
self.add_widget(grid_layout)
with self.canvas.before:
Color(1,0,0,1)
Rectangle(pos=self.pos, size=self.size)
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
Run Code Online (Sandbox Code Playgroud)
这只会在窗口小部件的初始位置和大小处显示一个红色矩形,此时它的默认位置和大小分别为(0,0)和(100,100).
为了使红色rect符合小部件的大小,我们应该将它的大小绑定到小部件的大小,就像这样::
...
grid_layout.add_widget(Button(text='text'))
self.add_widget(grid_layout)
with self.canvas.before:
Color(1,0,0,1)
self.rect = Rectangle(pos=self.pos, size=self.size)
self.bind(size=self.update_rect)
def update_rect(self, instance, value):
self.rect.pos = self.pos
self.rect.size = self.size
class MyApp(App):
def build(self):
...
Run Code Online (Sandbox Code Playgroud)
由于上面代码的输出将显示,您的小部件占用了整个窗口的大小.但是,这并不能解决您的问题,并且子布局仍然保留在原始位置和原始大小.这是因为如上所述,小部件不能控制其子节点的大小.
这里有两个选择,要么更新窗口小部件子项的大小和位置,就像更新rect一样(很快会让多个孩子感到复杂),或者使用其中一个布局作为根窗口小部件.
这也可以用kv这样完成::
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
Builder.load_string('''
# this is the rule for MyWidget that defines
# what MyWidget looks like i.e.drawing
# instructions and widgets etc
<MyWidget>:
canvas.before:
Color:
rgba: 1, 0, 0, 1
Rectangle:
# this implicitly binds the size of the
# rect to the size of the widget
size: self.size
# self here still refers to the widget as Rectangle is only a
# graphics instruction and not a widget
pos: self.pos
GridLayout:
cols: 3
# root here refers to the `MyWidget`, bind the size of the
# GridLayout to the size of your root widget
size: root.size
Button:
text: 'A'
Button:
text: 'B'
Label:
text: 'text'
Label:
text: 'other'
Button:
text: 'text'
''')
class MyWidget(Widget):
pass
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
Run Code Online (Sandbox Code Playgroud)
上面的示例将子项的大小绑定到它的父窗口小部件的大小.我仍然建议使用布局作为根窗口小部件,并且不要犹豫是否嵌套布局.
| 归档时间: |
|
| 查看次数: |
3872 次 |
| 最近记录: |