在kivy中引用和使用来自其他类的对象时遇到问题

2024-09-30 14:32:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我不熟悉python和面向对象编程。我用kivy做GUI,有很多页面、屏幕管理器、屏幕和类。我在访问和更新来自不同屏幕和类的对象时遇到问题

我认为这是引用对象id的方式,但我没有正确理解

如果有人能给我提供指导和帮助,我将非常感激。非常感谢。对不起,代码太长了,我尽量缩短了

我在更新id进程\u的背景色时遇到问题

我试图使用这一行引用它(不确定我是否正确)——>WindowWithMenuTemplate.process\u可用。background\u color=1,1,1

它来自类ProcessIndicatorTemplate 在带有菜单模板的窗口内 附加到AccWindow屏幕 进入窗口管理器屏幕

它返回的错误是

WindowWithMenuTemplate.process_available.background_color = 1, 1, 1, 1
 AttributeError: 'kivy.properties.ObjectProperty' object has no attribute 'background_color'

用python

import os
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.spinner import Spinner
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock
import requests
from base64 import b64encode, b64decode
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
import time
import numpy as np
import pandas as pd

class AccWindow(Screen):
    def __init__(self, **kwargs):
        super(AccWindow, self).__init__(**kwargs)

        acc0_user_record = ObjectProperty(None)

    def acc0_login_btn(self, acc_no):
        # i shorten this function as an illustration to ask, else the code is very long. the rest of codes is 
        # working except this specific line is not working below which i am trying to change another class object 
        # background color when i press this login_btn
        WindowWithMenuTemplate.process_available.background_color = 1, 1, 1, 1
        # this line below works
        self.acc0_user_record.background_color = 0, 0, 0, 0

class WindowWithMenuTemplate(FloatLayout):
    def __init__(self, **kwargs):
        super(WindowWithMenuTemplate, self).__init__(**kwargs)

        process_available = ObjectProperty(None)
        process_in_automation = ObjectProperty(None)
        process_in_manual = ObjectProperty(None)

class BackgroundColorLabelTemplate(Label):
    pass

class ProcessIndicatorTemplate(Label):
    pass

class WindowManager(ScreenManager):
    pass

class MyApp(App):
    def build(self):
        wm = WindowManager()
        return wm

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

在凯维

<WindowManager>:
    LoginWindow:
    HomeWindow:
    ExecutionWindow:
    OrdersWindow:
    AccWindow:
    SettingsWindow:

<HomeWindow>:
    name: "home_window"
    WindowWithMenuTemplate:

<ExecutionWindow>:
    name: "execution_window"
    WindowWithMenuTemplate:

<OrdersWindow>:
    name: "orders_window"
    WindowWithMenuTemplate:

<AccWindow>:
    name: "acc_window"
    acc0_user_record: acc0_user_record
    WindowWithMenuTemplate:

    GridLayout:
        cols: 4
        padding: 10, 10, 10, 10
        spacing: 10,10
        size_hint: 1, 0.834
        pos_hint: {"x": 0, "y": 0}

        GridLayout:
            cols: 1
            Label:
                text: "Acc 0"
                font_size: 11
            GridLayout:
                cols: 3
                BackgroundColorLabelTemplate:
                    id: acc0_user_record
                    text: ""
                    font_size: 11
                TextInput:
                    id: acc0_user_input
                    text: ""
                    font_size: 11
                    multiline: False
            GridLayout:
                cols: 1
                Button:
                    text: "Submit"
                    font_size: 11
                    disabled: True if acc_win_toggle_off.state == "down" and acc_win_toggle_on.state == "normal" else False
                    on_release:
                        root.acc0_login_btn("0")
                        acc_win_toggle_off.state = "down"
            GridLayout:
                cols: 1
                Button:
                    text: "Logout"
                    font_size: 11
                    disabled: True if acc_win_toggle_off.state == "down" and acc_win_toggle_on.state == "normal" else False
                    on_release:
                        root.acc0_logout_btn()
                        acc_win_toggle_off.state = "down"

<SettingsWindow>:
    name: "settings_window"
    WindowWithMenuTemplate:

<WindowWithMenuTemplate>:
    process_available: process_available
    process_in_automation: process_in_automation
    process_in_manual: process_in_manual

    ActionBar:
        pos_hint: {"x": 0, "top":1}
        ActionView:
            use_separator: False
            ActionPrevious:
                title: "My"
                with_previous: True
                on_release:
                    app.root.current = "home_window"
            ActionButton:
                text: "Execution"
                on_release:
                    app.root.current = "execution_window"
            ActionButton:
                text: "Orders"
                on_release:
                    app.root.current = "orders_window"
            ActionGroup:
                text: "Options"
                mode: "spinner"
                ActionButton:
                    text: "Acc"
                    on_release:
                        app.root.current = "acc_window"
                ActionButton:
                    text: "Settings"
                    on_release:
                        app.root.current = "settings_window"
                ActionButton:
                    text: "Logout"
                    on_release:
                        app.root.current = "login_window"

    GridLayout:
        size_hint: 0.1, 0.05
        pos_hint: {"x": 0.9, "top": 0.922}
        cols: 3
        ProcessIndicatorTemplate:
            id: process_available
        ProcessIndicatorTemplate:
            id: process_in_automation
        ProcessIndicatorTemplate:
            id: process_in_manual

<BackgroundColorLabelTemplate>:
    background_color: 0,0,0,0
    canvas.before:
        Color:
            rgba: root.background_color
        Rectangle:
            size: self.size
            pos: self.pos

<ProcessIndicatorTemplate>:
    background_color: 0,0,0,0
    canvas.before:
        Color:
            rgba: root.background_color
        Ellipse:
            size: self.size
            pos: self.pos

Tags: textfromimportselfsizeonrootwindow
3条回答

晚上下班后,我很兴奋能尝试一下。我可以和你确认一下,这是否有效

在屏幕中时,为了让我能够跨屏幕访问其他屏幕对象。在Kivy ScreenManager下,我将通过以下方式为所有屏幕提供id:

self.manager.get_screen('screen name').ids.<desired widget id>.<desired method or properties>
or
self.root.manager.get_screen('screen name').ids.<desired widget id>.<desired method such as def XXX() or properties such as text>

app = App.get_running_app()
app.root.manager.get_screen('screen name').ids.<desired widget id>.<desired method such as def XXX() or properties such as text>

这就是我现在的想法。我将尝试使用它。:)

必须在实例级别而不是类级别访问属性值,因此

WindowWithMenuTemplate.process_available.background_color = 1, 1, 1, 1

导致错误。解决此问题的一种方法是通过向kv中的WindowWithMenuTemplate添加一个id来引用实例:

<AccWindow>:
    name: "acc_window"
    acc0_user_record: acc0_user_record
    WindowWithMenuTemplate:
        id: wwmt

然后在python代码中使用它:

def acc0_login_btn(self, acc_no):
    # i shorten this function as an illustration to ask, else the code is very long. the rest of codes is
    # working except this specific line is not working below which i am trying to change another class object
    # background color when i press this login_btn
    # WindowWithMenuTemplate.process_available.background_color = 1, 1, 1, 1
    self.ids.wwmt.process_available.background_color = 1, 1, 1, 1
    # this line below works
    self.acc0_user_record.background_color = 0, 0, 0, 0

如果这对任何人都有帮助,我找到了下面的解决方案

app = App.get_running_app()
app.root.get_screen(app.root.current).ids.wwmt.ids.process_available.background_color = [1, 1, 1, 1]

Bascaly root得到了你的屏幕管理器。 get_screen指的是该屏幕小部件,然后在每个当前小部件上,使用ID来获取内部ID,然后引用所需的小部件,然后在其上再次使用ID等等,直到您达到要修改的属性或方法

这是我的理解,不确定我是否完全正确

相关问题 更多 >