为什么根窗口小部件的窗口大小不一样? [英] Why does the root widget not have the same size of the window?

查看:51
本文介绍了为什么根窗口小部件的窗口大小不一样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将自定义窗口小部件与GridLayout一起使用,但结果始终是拐角处的网格非常小,而不是在整个窗口中扩展网格.

I'm trying to use a custom widget with a GridLayout, but the result is always a really small grid in a corner, instead of a grid expanding in the whole window.

示例代码:

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()

由于Widget的默认size_hint(1,1),因此它应该在整个窗口中展开,而GridLayout也应在整个窗口中展开.为什么这没有发生? 如何获得想要的结果?

Since Widget's default size_hint is (1,1) it should expand in the whole window, and the GridLayout also. Why is this not happening? How can I obtain the result I want?

推荐答案

`class MyWidget(Widget):`

您的根窗口小部件是MyWidget,它是从Widget而不是布局之一继承的,因此不能控制其子控件的大小.如 布局 以管理其子女的人数".

Your root widget is MyWidget which inherits from a Widget and not from one of the layouts and therefore does not control the size of it's children As mentioned here, "The size_hint is a tupple of values used by layouts to manage the size of their children".

您的根窗口小部件确实占据了窗口的整个空间.您可以通过将矩形添加到MyWidget的画布中来进行测试,例如::

Your root widget does take up the entire space of the window. You can test this by adding a Rectangle to the canvas of MyWidget like so ::

with self.canvas.before:
    Color(1,0,0,1)
    Rectangle(pos=self.pos, size=self.size)

您应该熟悉画布,画布.before和canvas.after .它们基本上是指令组,before组在小部件的画布指令之前绘制,而after组在after之后.

You should get familiar with canvas, canvas.before and canvas.after. They are basically groups of instructions, the before group is drawn before the canvas instructions of the widget and after group after.

尽管在Kivy中有一个关键的不同之处在于,小部件的大小调整/布局被延迟到下一帧,所以如果您将上述代码段添加到代码中,就像这样:

One key thing different in Kivy though is that widget's sizing/layout is delayed till next frame, so if you just add the above snippet to your code like so::

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()

这只会在窗口小部件的初始位置和大小处显示一个红色矩形,这在当时是默认的pos和大小,分别为(0,0)和(100,100).

This would only display a red rectangle at the initial position and size of your widget, which at the time would be it's default pos and size a.k.a (0, 0) and (100, 100) respectively.

要使红色矩形遵守小部件的大小,我们应该绑定,它的大小与小部件的大小相同,如下所示::

To make the red rect adhere to the size of the widget we should bind it's size to the size of the widget, like so::

...
        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):
...

如以上代码所示,您的窗口小部件占据了整个窗口的大小.但是,这不能解决您的问题,子布局仍然保留在原始位置.它的原始大小.这是因为小部件无法如上所述控制其子级的大小.

As the output of the above code above will show, your widget is taking up the size of the entire window. However, this doesn't solve your issue and the child layout still remains at it's original pos & of it's original size. This is cause widgets don't control the size of their children as stated above.

您在此处有两个选择,可以更新尺寸&您的小部件的一个或多个子位置的pos,例如您更新rect(很快就会有多个孩子变得复杂),或使用布局之一作为您的根小部件.

You have two choices here, either update the size & pos of your widget's child/children like you update rect(would quickly get complicated with multiple children) or use one of the Layouts as your root widget.

这也可以像这样在kv中完成:

This could also be done in kv like so::

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()

上面的示例将子级的大小绑定到其父级小部件的大小.我仍然建议使用布局作为您的根窗口小部件,不要犹豫嵌套布局.

The example above binds the size of the child to the size of it's parent widget. I'd still recommend using a layout as your root widget, and don't be hesitant of nesting layouts.

这篇关于为什么根窗口小部件的窗口大小不一样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆