【问题标题】:connecting my custom widget to my screen manager将我的自定义小部件连接到我的屏幕管理器
【发布时间】:2019-07-04 00:29:14
【问题描述】:

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

这被引用: state: "down" if root.manager.current == 'Screenname' else "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'

【问题讨论】:

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


    【解决方案1】:

    我会将您的根小部件设为布局小部件(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 端引用它,如果您从 App 对象引用它,请使用 self.root.ids.the_menu_id。如果您在其他类型的对象中,您可以通过首先导入 App (import App) 然后使用 App.get_running_app().root.ids.the_menu_id 来执行相同操作

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

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

    【讨论】:

      【解决方案2】:

      问题

      • 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'
      

      输出

      【讨论】:

        猜你喜欢
        • 2022-11-13
        • 2012-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多