Python Kivy-从父代继承?

Python Kivy-从父代继承?,python,kivy,Python,Kivy,我有一个关于Kivy内父母的尺寸遗传的问题 到目前为止,我的程序布局大致如下: GridLayout (3 cols) |-------> widget |-------> widget |-------> boxlayout (with screenmanager) |-----> relative layouts used within each screen 我遇到了一个问题,screenmanager窗口的大小都默认为100100,不管

我有一个关于Kivy内父母的尺寸遗传的问题

到目前为止,我的程序布局大致如下:

GridLayout (3 cols)
|-------> widget
|-------> widget
|-------> boxlayout (with screenmanager)
             |-----> relative layouts used within each screen
我遇到了一个问题,screenmanager窗口的大小都默认为100100,不管我做了什么更改,我认为这与相互继承的不同布局有关,但我找不到源代码

有人能看出我做错了什么,并提出解决办法吗


main.py

import kivy
from kivy.app import App
from kivy.core.window import Window
from layout import MainLayout

Window.size = (581, 142)

class MyApp(App):
    def build(self):
        self.title = 'Test'
        return MainLayout()

if __name__ == '__main__':
    MyApp().run()
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from screentest import ScreenTestWidget


class MainLayout(GridLayout):

    def __init__(self, **kwargs):
        super(MainLayout, self).__init__(**kwargs)

        layout = GridLayout(cols=3, col_default_width=200)

        layout.add_widget(Label(text='test'))
        layout.add_widget(Label(text='test'))
        layout.add_widget(ScreenTestWidget())

        self.add_widget(layout)
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen

Builder.load_string("""
<MenuScreen>:
    RelativeLayout:
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 50
            text: 'Settings'
            on_press:
                root.manager.current = 'settings'
                root.manager.transition.direction = 'down'
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 0
            text: 'Quit'
            on_press: app.stop()

<SettingsScreen>:
    RelativeLayout:
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 50
            text: 'Settings'
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 0
            text: 'Menu'
            on_press:
                root.manager.current = 'menu'
                root.manager.transition.direction = 'up'
""")


class ScreenTestWidget(BoxLayout):

    def __init__(self, **kwargs):
        super(ScreenTestWidget, self).__init__(**kwargs)

        # Create the screen manager
        sm = ScreenManager()
        sm.add_widget(MenuScreen(name='menu'))
        sm.add_widget(SettingsScreen(name='settings'))
        self.add_widget(sm)


# Declare both screens
class MenuScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass
layout.py

import kivy
from kivy.app import App
from kivy.core.window import Window
from layout import MainLayout

Window.size = (581, 142)

class MyApp(App):
    def build(self):
        self.title = 'Test'
        return MainLayout()

if __name__ == '__main__':
    MyApp().run()
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from screentest import ScreenTestWidget


class MainLayout(GridLayout):

    def __init__(self, **kwargs):
        super(MainLayout, self).__init__(**kwargs)

        layout = GridLayout(cols=3, col_default_width=200)

        layout.add_widget(Label(text='test'))
        layout.add_widget(Label(text='test'))
        layout.add_widget(ScreenTestWidget())

        self.add_widget(layout)
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen

Builder.load_string("""
<MenuScreen>:
    RelativeLayout:
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 50
            text: 'Settings'
            on_press:
                root.manager.current = 'settings'
                root.manager.transition.direction = 'down'
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 0
            text: 'Quit'
            on_press: app.stop()

<SettingsScreen>:
    RelativeLayout:
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 50
            text: 'Settings'
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 0
            text: 'Menu'
            on_press:
                root.manager.current = 'menu'
                root.manager.transition.direction = 'up'
""")


class ScreenTestWidget(BoxLayout):

    def __init__(self, **kwargs):
        super(ScreenTestWidget, self).__init__(**kwargs)

        # Create the screen manager
        sm = ScreenManager()
        sm.add_widget(MenuScreen(name='menu'))
        sm.add_widget(SettingsScreen(name='settings'))
        self.add_widget(sm)


# Declare both screens
class MenuScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass
屏幕测试.py

import kivy
from kivy.app import App
from kivy.core.window import Window
from layout import MainLayout

Window.size = (581, 142)

class MyApp(App):
    def build(self):
        self.title = 'Test'
        return MainLayout()

if __name__ == '__main__':
    MyApp().run()
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from screentest import ScreenTestWidget


class MainLayout(GridLayout):

    def __init__(self, **kwargs):
        super(MainLayout, self).__init__(**kwargs)

        layout = GridLayout(cols=3, col_default_width=200)

        layout.add_widget(Label(text='test'))
        layout.add_widget(Label(text='test'))
        layout.add_widget(ScreenTestWidget())

        self.add_widget(layout)
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen

Builder.load_string("""
<MenuScreen>:
    RelativeLayout:
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 50
            text: 'Settings'
            on_press:
                root.manager.current = 'settings'
                root.manager.transition.direction = 'down'
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 0
            text: 'Quit'
            on_press: app.stop()

<SettingsScreen>:
    RelativeLayout:
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 50
            text: 'Settings'
        Button:
            size_hint: None, None
            size: root.width, root.height * 0.5
            pos: 0, 0
            text: 'Menu'
            on_press:
                root.manager.current = 'menu'
                root.manager.transition.direction = 'up'
""")


class ScreenTestWidget(BoxLayout):

    def __init__(self, **kwargs):
        super(ScreenTestWidget, self).__init__(**kwargs)

        # Create the screen manager
        sm = ScreenManager()
        sm.add_widget(MenuScreen(name='menu'))
        sm.add_widget(SettingsScreen(name='settings'))
        self.add_widget(sm)


# Declare both screens
class MenuScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass
从kivy.uix.boxlayout导入boxlayout
从kivy.lang导入生成器
从kivy.uix.screenmanager导入screenmanager,屏幕
生成器。加载\u字符串(“”)
:
相对长度:
按钮:
大小提示:无,无
尺寸:根.宽,根.高*0.5
位置:0,50
文本:“设置”
新闻界:
root.manager.current='settings'
root.manager.transition.direction='down'
按钮:
大小提示:无,无
尺寸:根.宽,根.高*0.5
位置:0,0
文本:“退出”
按:app.stop()
:
相对长度:
按钮:
大小提示:无,无
尺寸:根.宽,根.高*0.5
位置:0,50
文本:“设置”
按钮:
大小提示:无,无
尺寸:根.宽,根.高*0.5
位置:0,0
文本:“菜单”
新闻界:
root.manager.current='菜单'
root.manager.transition.direction='up'
""")
类ScreenTestWidget(BoxLayout):
定义初始(自我,**kwargs):
超级(ScreenTestWidget,self)。\uuuuuuu初始化(**kwargs)
#创建屏幕管理器
sm=屏幕管理器()
sm.add_小部件(菜单浏览(name='menu'))
sm.add_小部件(设置屏幕(name='settings'))
self.add_小部件(sm)
#声明两个屏幕
类菜单屏幕(屏幕):
通过
类别设置屏幕(屏幕):
通过

首先创建一个从GridLayout继承的MainLayout。这将填充整个屏幕。但因为您从未设置列或行,所以它永远不会工作,也不会影响子级

然后(在
mainloayout.\uuuu init\uuuu
)创建一个新的gridlayout,并将其添加到mainloayout中。MainLayout不工作,因此
size\u hint
不执行任何操作,因此GridLayout将默认为
size=100100
。默认情况下,该位置再次为
pos=0,0
。此布局有3列,列的默认宽度为200

现在,在这个GridLayout中添加2个标签和ScreenTestWidget。网格布局现在的宽度为600。一切都按其应有的方式显示出来

ScreenTestWidget在默认情况下具有
size\u hint=1,1
。因此它的大小是
size=200100
。默认情况下,内部的每个屏幕都有
size\u hint=1,1
,因为您从不更改它。然后,每个屏幕都有一个relativelayout,默认情况下它也有
size\u hint=1,1

然后,每个屏幕中的按钮具有自定义位置,并随父屏幕调整大小。父对象是相对对象。Relativelayout随屏幕调整大小。屏幕大小随ScreenTestWidget调整。ScreenTestWidget的大小由ColumnLayout调整。Columnlayout不会调整大小,因为其父级未设置cols或rows,因此无法工作。因此,它默认为
100100
(但随后每个子项的大小调整为200宽度)

要解决此问题,可以按以下方式更改代码:

class MainLayout(GridLayout):

    def __init__(self, **kwargs):
        super(MainLayout, self).__init__(**kwargs)

        # instead of creating a new Layout set the attributes of this one
        self.cols = 3
        self.col_default_width = 200

        self.add_widget(Label(text='test'))
        self.add_widget(Label(text='test'))
        self.add_widget(ScreenTestWidget())
此外,屏幕中不需要RelativeLayouts,因为屏幕已经是RelativeLayouts:

<SettingsScreen>:
    Button:
        size_hint: None, None
        size: root.width, root.height * 0.5
        pos: 0, 50
        text: 'Settings'
    Button:
        size_hint: None, None
        size: root.width, root.height * 0.5
        pos: 0, 0
        text: 'Menu'
        on_press:
            root.manager.current = 'menu'
            root.manager.transition.direction = 'up'
:
按钮:
大小提示:无,无
尺寸:根.宽,根.高*0.5
位置:0,50
文本:“设置”
按钮:
大小提示:无,无
尺寸:根.宽,根.高*0.5
位置:0,0
文本:“菜单”
新闻界:
root.manager.current='菜单'
root.manager.transition.direction='up'

或者,您也可以为主布局设置行或列。

设置
size\u hint=(无,无)
后,您将得到
[100100]
,因此可能就是这样,但除非有代码,否则很难判断错误或潜在错误。好的,我确实设置了
size\u hint:(无,无)
,还有
大小:root.width,root.height*0.5
,但高度从未填充?我尝试将
size\u hint
更改为各种数字,但它从未达到屏幕的全部高度,我认为这与GridLayout或BoxLayout限制它有关?你能给我们展示一下要复制的最小代码吗?@syntonym我更新了问题,加入了一个代码示例。如果工作正常,您可以看到screenmanager小部件上的按钮没有达到屏幕的全部高度…?感谢您详细解释正在发生的事情!我仍然对你的第一句话有点困惑——我认为主布局是网格布局?你会如何建议我解决这个问题?不确定从哪里开始…MainLayout确实是一个GridLayout,但它也在其
\uuuu init\uuuu
方法中创建了一个额外的GridLayout。如果删除该GridLayout,而使用MainLayout,它应该可以正常工作。我添加了一些代码来说明我的意思。