簡體   English   中英

在 kivy 中的其他 class 引用和使用 object 時遇到問題

[英]Having problems with referencing and using object from other class in kivy

我是 python 和 object 面向編程的新手。 我在 kivy 中做我的 GUI,有很多頁面、屏幕管理器、屏幕和類。 我在從不同的屏幕和類訪問和更新對象時遇到問題。

我認為它是引用對象 id 的方式,但我沒有做對。

如果有足夠好心的人可以指導和幫助我,我將非常感激。 謝謝你。 對不起代碼,盡量縮短。

我在更新 id process_available的背景顏色時遇到問題。

我嘗試使用此行引用(不確定我是否正確)-> WindowWithMenuTemplate.process_available.background_color = 1, 1, 1, 1

這是從附加到AccWindow屏幕到WindowManager屏幕管理器的WindowWithMenuTemplate內的 class ProcessIndicatorTemplate

它返回的錯誤是

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

您必須在實例級別訪問屬性值,而不是 class 級別,所以

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

導致錯誤。 解決此問題的一種方法是通過將id添加到kv中的WindowWithMenuTemplate來引用實例:

<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

很高興晚上下班后嘗試一下。 我可以和你確認一下,這是否可行。

在屏幕中時,為了讓我可以跨屏幕訪問我的其他屏幕對象。 在 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>

這就是我現在的想法。 會嘗試一下。 :)

如果這對任何人都有幫助,我在下面找到了解決方案。

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

bascally root 獲取您的屏幕管理器。 get_screen 引用該屏幕小部件,然后在每個當前小部件上,使用 ids 獲取內部 ids,然后引用該所需的小部件,並在其上再次使用 ids 依此類推,直到您到達要修改的屬性或方法.

這是我的理解,不確定我是否完全正確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM