将自定义窗口小部件连接到屏幕管理器

时间:2019-06-17 19:54:30

标签: python python-3.x kivy kivy-language

我正在尝试使用Python和kivy构建应用程序。 在我的kv文件中,我想创建一个自定义小部件(MenuFloatLayout) 可以被其他屏幕引用。基本上,它是每个屏幕上的菜单栏。此栏由几个切换按钮组成,这些按钮处于按下状态,并且如果您当前在该按钮所链接的屏幕上,则这些按钮处于禁用状态。

此引用由: 状态:如果root.manager.current =='Screenname',则为“ down”,否则为“ normal”

问题是: root.manager.current不再链接到通常的屏幕管理器, 因为我的自定义小部件现在是根。

周围有工作吗? 还是有更简单的方法将切换按钮状态链接到用户所在的屏幕?

我是编程和Python的新手,很高兴为您提供任何帮助或提示!谢谢!

Python文件:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager


class StartWindow(Screen):
    pass


class PortfolioOverview(Screen):
    pass


class Portfolio(Screen):
    pass


class Market(Screen):
    pass


class Economics(Screen):
    pass


class PortfolioTools(Screen):
    pass


class WindowManager(ScreenManager):
    pass


kv = Builder.load_file("vigiles.kv")


class VigilesApp(App):
    def build(self):
        return kv


if __name__ == "__main__":
    VigilesApp().run()

和kv文件:

WindowManager:
    StartWindow:
    PortfolioOverview:
    Portfolio:
    Market:
    Economics:
    PortfolioTools:

<MenuFloatLayout@FloatLayout>:
    Label:
        text: "Portfolio"
        markup: True
        size_hint: 0.5, None
        height: 30
        pos_hint:{"top":1, "left":1}

    TextInput:
        text: "Search"
        multiline: False
        size_hint: 0.5, None
        height: 30
        pos_hint:{"top":1, "right":1}

    ScrollView:
        size_hint: None, None
        do_scroll_y: False
        do_scroll_x: True
        size: 500, 150

        GridLayout:
            rows: 1
            size_hint_y: None

            ToggleButton:
                group: "pmenu"
                text: 'Overview'
                state: "down" if root.manager.current == 'poverview' else "normal"
                disabled: True if root.manager.current == 'poverview' else False
                background_disabled_down: "atlas://data/images/defaulttheme/button_pressed"
                disabled_color: 1, 1, 1, 1
                on_release: app.root.current = "poverview"

            ToggleButton:
                group: "pmenu"
                text: 'Portfolio'
                state: "down" if root.manager.current == 'portfolio' else "normal"
                disabled: True if root.manager.current == 'portfolio' else False
                background_disabled_down: "atlas://data/images/defaulttheme/button_pressed"
                disabled_color: 1, 1, 1, 1
                on_release: app.root.current = "portfolio"

            ToggleButton:
                group: "pmenu"
                text: 'Market'
                state: "down" if root.manager.current == 'market' else "normal"
                disabled: True if root.manager.current == 'market' else False
                background_disabled_down: "atlas://data/images/defaulttheme/button_pressed"
                disabled_color: 1, 1, 1, 1
                on_release: app.root.current = "market"

            ToggleButton:
                group: "pmenu"
                text: 'Economics'
                state: "down" if root.manager.current == 'economics' else "normal"
                disabled: True if root.manager.current == 'economics' else False
                background_disabled_down: "atlas://data/images/defaulttheme/button_pressed"
                disabled_color: 1, 1, 1, 1
                on_release: app.root.current = "economics"

            ToggleButton:
                group: "pmenu"
                text: 'Tools'
                state: "down" if root.manager.current == 'ptools' else "normal"
                disabled: True if root.manager.current == 'ptools' else False
                background_disabled_down: "atlas://data/images/defaulttheme/button_pressed"
                disabled_color: 1, 1, 1, 1
                on_release: app.root.current = "ptools"


<StartWindow>:
    name: "start"
    BoxLayout:
        canvas:
            Rectangle:
                size: self.size
        color: 1, 1, 1, 0
        id: login_layout
        orientation: 'vertical'
        padding: [10,10,10,10]
        spacing: 30

        Label:
            text: 'some text'
            font_size: 32
            color: 0, 0, 0, 1

        BoxLayout:
            orientation: 'vertical'

            Label:
                text: 'Login'
                font_size: 18
                halign: 'left'
                text_size: root.width-20, 20
                color: 0, 0, 0, 1

            TextInput:
                id: login
                multiline:False
                font_size: 28

        BoxLayout:
            orientation: 'vertical'
            Label:
                text: 'Password'
                halign: 'left'
                font_size: 18
                text_size: root.width-20, 20
                color: 0, 0, 0, 1

            TextInput:
                id: password
                multiline:False
                password:True
                font_size: 28

        Button:
            text: 'Connect'
            font_size: 24
            on_release: app.root.current = "poverview"



<PortfolioOverview>:
    name: "poverview"
    MenuFloatLayout:

<Portfolio>:
    name: "portfolio"
    MenuFloatLayout:

<Market>:
    name: "market"
    MenuFloatLayout:

<Economics>:
    name: "economics"
    MenuFloatLayout:

<PortfolioTools>:
    name: "ptools"
    MenuFloatLayout:

目标是将我的自定义窗口小部件链接回我的屏幕管理器,或者找到一个更简单的解决方案以将切换按钮状态链接到当前屏幕。

AttributeError:'MenuFloatLayout'对象没有属性'manager'

2 个答案:

答案 0 :(得分:0)

我会将您的根窗口小部件设为布局窗口小部件(GridLayoutBoxLayoutFloatLayout),然后让屏幕管理器仅占用实际屏幕的一部分。尝试更改

WindowManager:
    StartWindow:
    PortfolioOverview:
    Portfolio:

收件人:

GridLayout:
    # Play with using a FloatLayout or BoxLayout instead of GridLayout if you want
    cols: 1
    MenuFloatLayout:
        id: the_menu_id
    WindowManager:
        StartWindow:
        PortfolioOverview:
        Portfolio:

这样,您的菜单将继续存在,并且屏幕管理器仅更改实际屏幕的一部分。

通过给MenuFloatLayout一个id,您可以引用它。要从Python端引用它,如果要从self.root.ids.the_menu_id对象引用它,请使用App。如果您使用的是其他类型的对象,则可以先导入Appimport App),然后使用App.get_running_app().root.ids.the_menu_id

要从屏幕上引用它,可以使用app关键字。例如:app.root.ids.the_menu_id

引用菜单id的所有三种方式基本上是相同的。

答案 1 :(得分:0)

问题

  • MenuFloatLayout的实例过多
  • 使用大量资源,例如内存,这会使应用变大且性能不佳

解决方案

  • 创建一个MenuFloatLayout实例
  • 每个屏幕都引用MenuFloatLayout的一个和唯一一个实例
  • 使用嵌套的ScreenManager。这第一个ScreenManager用于控制身份验证/登录屏幕。第二个ScreenManager用于在不同屏幕之间导航。
  • ToggleButton创建一个dynamic class

示例

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager


class StartWindow(Screen):
    pass


class PortfolioOverview(Screen):
    pass


class Portfolio(Screen):
    pass


class Market(Screen):
    pass


class Economics(Screen):
    pass


class PortfolioTools(Screen):
    pass


class WindowManager(ScreenManager):
    pass


Builder.load_file("main.kv")


class TestApp(App):
    def build(self):
        return WindowManager()


if __name__ == "__main__":
    TestApp().run()

main.kv-kv文件

<WindowManager>:
    sm2: sm2
    StartWindow:
    Screen:
        name: 'connect'

        ScreenManager:
            id: sm2
            PortfolioOverview:
            Portfolio:
            Market:
            Economics:
            PortfolioTools:

        MenuFloatLayout:


<CustomToggleButton@ToggleButton>:    # dynamic class
    group: "pmenu"
    state: "normal" if app.root is None else "down" if app.root.sm2.current == self.text.lower() else "normal"

    background_disabled_down: "atlas://data/images/defaulttheme/button_pressed"
    disabled_color: 1, 1, 1, 1

    on_state:
        if self.state == "down": self.disabled = True
        else: self.disabled = False

    on_release:
        app.root.sm2.current = self.text.lower()


<MenuFloatLayout@FloatLayout>:    # dynamic class
    Label:
        text: "Portfolio"
        markup: True
        size_hint: 0.5, None
        height: 30
        pos_hint:{"top":1, "left":1}

    TextInput:
        hint_text: "Search"
        multiline: False
        size_hint: 0.5, None
        height: 30
        pos_hint:{"top":1, "right":1}

    ScrollView:
        size_hint: None, None
        do_scroll_y: False
        do_scroll_x: True
        size: 500, 150

        GridLayout:
            rows: 1
            size_hint_y: None

            CustomToggleButton:
                text: 'Overview'
                state: 'down'   # default

            CustomToggleButton:
                text: 'Portfolio'

            CustomToggleButton:
                text: 'Market'

            CustomToggleButton:
                text: 'Economics'

            CustomToggleButton:
                text: 'Tools'


<StartWindow>:
    name: "start"
    BoxLayout:
        canvas:
            Rectangle:
                size: self.size
        color: 1, 1, 1, 0
        id: login_layout
        orientation: 'vertical'
        padding: [10,10,10,10]
        spacing: 30

        Label:
            text: 'some text'
            font_size: 32
            color: 0, 0, 0, 1

        BoxLayout:
            orientation: 'vertical'

            Label:
                text: 'Login'
                font_size: 18
                halign: 'left'
                text_size: root.width-20, 20
                color: 0, 0, 0, 1

            TextInput:
                id: login
                multiline:False
                font_size: 28

        BoxLayout:
            orientation: 'vertical'
            Label:
                text: 'Password'
                halign: 'left'
                font_size: 18
                text_size: root.width-20, 20
                color: 0, 0, 0, 1

            TextInput:
                id: password
                multiline:False
                password:True
                font_size: 28

        Button:
            text: 'Connect'
            font_size: 24
            on_release:
                root.manager.current = 'connect'



<PortfolioOverview>:
    name: "overview"
    Label:
        text: 'Screen - Overview'

<Portfolio>:
    name: "portfolio"
    Label:
        text: 'Screen - Portfolio'

<Market>:
    name: "market"
    Label:
        text: 'Screen - Market'

<Economics>:
    name: "economics"
    Label:
        text: 'Screen - Economics'

<PortfolioTools>:
    name: "tools"
    Label:
        text: 'Screen - Portfolio Tools'

输出

Result