【问题标题】:Pass input value to dialog and send to screen将输入值传递给对话框并发送到屏幕
【发布时间】:2022-01-19 16:34:18
【问题描述】:

我有以下代码,我希望能够在其中单击导航抽屉,选择用户下的状态,输入名称,然后发送到当前填充的给定屏幕。

main.py

from kivy.uix.behaviors import CoverBehavior
from kivy import utils
from kivy.properties import ObjectProperty, ListProperty, NumericProperty, StringProperty, BooleanProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivymd.theming import ThemableBehavior
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivymd.uix.list import MDList
#from models import ServerInfo
from navigation_drawer import navigation_helper
Window.fullscreen = 'auto'
class ItemWidget(BoxLayout):
    sid = NumericProperty()
    name = StringProperty()
    work = NumericProperty()
    is_disabled = BooleanProperty()
    description = StringProperty()
    has_issue = BooleanProperty()

class MainWidget(FloatLayout):
    recycleView = ObjectProperty()
    items = ListProperty()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.items = [
            #ServerInfo(1, "server1", 95, "desc", is_disabled=False, has_issue=False),
        ]
        # Put the servers with issues on top, otherwise sort by name
        self.items = sorted((s for s in self.items), key=lambda x: (not(x.has_issue),x.name))

    # Load the server information when the recycleView is called
    def on_recycleView(self, widget, parent):

        self.recycleView.data = [
            m.get_dictionary() for m in self.items
        ]


class Content(BoxLayout):
    pass


class DemoApp(MDApp):
    class ContentNavigationDrawer(BoxLayout):
        pass

    class DrawerList(ThemableBehavior, MDList):
        pass

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.dialog = None
        # set main interface
        self.manager = ScreenManager()
        self.current_user = ""

        # return main interface
        #return self.manager

    def build(self):
        screen = Builder.load_string(navigation_helper)
        return screen

    def on_start(self):
        pass

    def dialog_close(self, *args):
        self.dialog.dismiss(force=True)

    def set_current_user(self,user,sm):
        self.current_user = user
        # Send over to given screen
        # ???? = sm


    def show_user_input_dialog(self,user,screen):
        #print(sm.current)
        if not self.dialog:
            self.dialog = MDDialog(
                title="Input Username:",
                type="custom",
                content_cls=Content(),
                buttons=[
                    MDFlatButton(
                        text="CANCEL",
                        theme_text_color="Custom",
                        text_color=self.theme_cls.primary_color,
                        on_release=self.dialog_close
                    ),
                    MDFlatButton(
                        text="OK",
                        theme_text_color="Custom",
                        text_color=self.theme_cls.primary_color,
                        #on_release=self.set_current_user(user,screen)
                        on_release=self.dialog_close
                    ),
                ],
            )
            # Send to user management page with current user now populated
            # Fails as sm is a str instead of ScreenManager()
            #sm.current = 'user_management'
        self.dialog.open()


DemoApp().run()

navigation_drawer.py

navigation_helper = """
Screen:
    MDNavigationLayout:
        ScreenManager:
            id: screenManager
            Screen:
                name: "monitor"
                BoxLayout:
                    orientation: 'vertical'
                    MDToolbar:
                        title: 'Administration'
                        left_action_items: [["menu", lambda x: nav_drawer.set_state('toggle')]]
                        elevation:5
                    MainWidget:
            Screen:
                name: "user_management"
                BoxLayout:
                    orientation: 'vertical'
                    MDToolbar:
                        title: 'Administration'
                        left_action_items: [["menu", lambda x: nav_drawer.set_state('toggle')]]
                        elevation:5
                    UserManagement:
            

        MDNavigationDrawer:
            id: nav_drawer

            ContentNavigationDrawer:
                orientation: 'vertical'
                padding: "2dp"
                spacing: "2dp"
                ScrollView:
                    DrawerList:
                        id: md_list
                        MDList:
                            TwoLineIconListItem:
                                text: "Monitor"
                                secondary_text: "Monitor servers"
                                on_release: screenManager.current = 'monitor'
                                IconLeftWidget:
                                    icon: "monitor"
                            MDLabel:
                                padding: dp(10), dp(0)
                                text: "Users"
                                bold: True
                                font_size: dp(22)
                                size_hint_y: None
                            OneLineIconListItem:
                                text: "Status"
                                on_release: app.show_user_input_dialog('abc999','user_management')
                            
                            
<Content>
    orientation: "vertical"
    spacing: "12dp"
    size_hint_y: None
    height: "60dp"
    MDTextField:
        id: username_input
        hint_text: "Username"

<UserManagement@BoxLayout>:
    Label:
        text: "Users"

                               
<MainWidget>:
    id: mainWidgetId2
    recycleView: recycleView
    CoverImage:
        source: 'images/monitor.png'
        # Darken the photo
        canvas:
            Color:
                rgba: 0, 0, 0, .6
            Rectangle:
                pos: self.pos
                size: self.size
    BoxLayout:
        padding: dp(20)
        spacing: dp(10)
        BoxLayout:
            orientation: "horizontal"
            BoxLayout:
                canvas.before:
                    Color:
                        rgba: 1,1,1,.1
                    # Use a float layout to round the corners
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                RecycleView:
                    id: recycleView
                    viewclass: 'ItemWidget'
                    RecycleGridLayout:
                        cols: 1
                        default_size: self.parent.width / 5, dp(60)
                        default_size_hint: 1, None
                        size_hint_y: None
                        height: self.minimum_height
                        width: self.minimum_width
                        spacing: dp(155), dp(0)
        BoxLayout:
            orientation: "vertical"
            spacing: dp(10)
            BoxLayout:
                spacing: dp(10)
                BoxLayout:
                    canvas.before:
                        Color:
                            rgba: 1,1,1,.1
                        # Use a float layout to round the corners
                        RoundedRectangle:
                            pos: self.pos
                            size: self.size
                    Label:
                        text: "APPS"
                BoxLayout:
                    canvas.before:
                        Color:
                            rgba: 1,1,1,.1
                        # Use a float layout to round the corners
                        RoundedRectangle:
                            pos: self.pos
                            size: self.size
                    Label:
                        text: "OTHER"
            BoxLayout:
                canvas.before:
                    Color:
                        rgba: 1,1,1,.1
                    # Use a float layout to round the corners
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                Label:
                    text: "MOUNTS"

            BoxLayout:
                canvas.before:
                    Color:
                        rgba: 1,1,1,.1
                    # Use a float layout to round the corners
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                Label:
                    text: "RECENT ACTIVITY"

<CoverImage@CoverBehavior+Image>:
    reference_size: self.texture_size

<ItemWidget>:
    BoxLayout:
        #size_hint_max_x: dp(360)
        size_hint_min_x: dp(150)
        orientation: "horizontal"
        BoxLayout:
            orientation: "horizontal"
            Button:
                # Use the on_press to print troubleshooting info, otherwise comment out
                on_press: print(self.background_color)
                padding: dp(10), dp(10)
                text_size: self.size
                font_size: dp(22) if root.has_issue else dp(18)
                background_color: .5,1,1,.6 #utils.get_random_color(alpha=.6)
                halign: "left"
                valign: "top"
                size: 1,1
                # Show last 4 of server name
                text: str(root.name).upper()[-4:]
                bold: True
                color: (1,0,0) if root.has_issue else (1,1,1)
            Button:
                background_color: .5,1,1,.6
                text_size: self.size
                valign: "center"
                halign: "center"
                text: str(root.work)
                padding: dp(8), dp(8)
                bold: True if root.work > 90 else False
                color: (1,0,0) if root.work > 90 else (1,1,1) # Red if greater than 90


"""

问题:

  1. 如何从中获取值,以便我可以传递该值而不是 abc999 的硬编码用户名
MDTextField:
        id: username_input
  1. 如何从
  2. 发送到给定屏幕(此处为 user_management)
    def set_current_user(self,user,sm):
        self.current_user = user
        # Send over to given screen
        # ???? = sm

您可以在下面的两个 on_release 上切换评论以查看问题

                    MDFlatButton(
                        text="OK",
                        theme_text_color="Custom",
                        text_color=self.theme_cls.primary_color,
                        #on_release=self.set_current_user(user,screen)
                        on_release=self.dialog_close

【问题讨论】:

    标签: python kivy kivy-language kivymd


    【解决方案1】:

    您可以通过将set_current_user() 修改为:

    def set_current_user(self, button):
        self.current_user = self.dialog.content_cls.ids.username_input.text
        self.dialog_close()
        self.root.ids.users.add_widget(Label(text=self.current_user))
        sm = self.root.ids.screenManager
        sm.current = 'user_management'
    

    以上代码需要在kv中的UserManagerment中添加一个id

                    UserManagement:
                        id: users
    

    这只是添加了一个带有用户名的新Label

    【讨论】:

    • 我已将按钮更改为 *args 并更改了 on_release=set_current_user 但我在标签添加 self.root.ids.users.add_widget(Label(text=self.current_user)) 文件中得到以下信息“kivy\properties.pyx”,第 864 行,在 kivy.properties.ObservableDict.__getattr__ AttributeError: 'super' object has no attribute 'getattr'
    • 您是否添加了users id?
    • 是的,我添加了 id(并在测试时将 *args 改回按钮)。行为没有变化
    • 如果我打印 self.root.ids 我只会得到 screenManager、nav_drawer 和 md_list
    • 你添加到正确的地方了吗?不要将其添加到&lt;UserManagement@BoxLayout&gt;: 规则中。
    猜你喜欢
    • 2017-05-12
    • 2013-07-06
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2013-08-27
    • 2021-09-28
    • 1970-01-01
    相关资源
    最近更新 更多