kivy 使用附加类来存储来自多个屏幕的数据

kivy using addtional class to store data from multiple screens(kivy 使用附加类来存储来自多个屏幕的数据)

本文介绍了kivy 使用附加类来存储来自多个屏幕的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想向我的 kivy 应用程序添加一个额外的类,它只是一个信息存储库.我不确定在哪里执行此操作,或者是否建议使用这种方法.

I want to add an additional class to my kivy app that is just an info storage depot. I'm not sure where to do this or if this approach is even advised.

该应用有多个屏幕.每个屏幕都允许用户进行选择.用户的选择就是我想要存储在附加类中的内容.附加类将存储数据,然后最终使用 MQTT 将数据发送出去.另外,我想将类定义保存在一个单独的文件中,这样我就可以将程序组织成逻辑有序的块.

The app has multiple screens. Each screen allows the user to make a selection. The user's selection is what I want to store in the additional class. The additional class will store data then ultimately use MQTT to send the data out. Also, I wanted to keep the class definition in a separate file so I could organize the program into logically ordered chunks.

(请记住,我只分享了一小部分代码,但这应该足以表达我的问题)

(keep in mind I'm sharing a small fraction of the code, but this should be representative enough to convey my question)

我的 kivy python 代码:

My kivy python code:

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from storage import Storage  # <<========================== this is the addtional class

# Screen Manager
class MyScreenManager(ScreenManager):
    pass


# Background Color
class BG(FloatLayout):
    pass


class VendorScreen(Screen):
    pass


class InvoiceScreen(Screen):
    def __init__(self, **kwargs):
        super(InvoiceScreen, self).__init__(**kwargs)
        self.invoice = ''

    def keyEntry(self, number):  # ............ Digit Pressed
        invoice = self.ids.invoice  # ......... link to kivy Label
        invoice.text += number  # ............. append number to invoice

    def keyBack(self):  # ..................... Backspace
        invoice = self.ids.invoice  # ......... link to kivy Label
        invoice.text = invoice.text[:-1]  # ... remove last digit

    def set_invoice(self):
        invoice = self.ids.invoice
        self.invoice = invoice.text


class MainControlScreen(Screen):
    pass


# Main-Execution
class mySuperApp(App):
    def build(self):
        return MyScreenManager()


if __name__ == '__main__':
    mySuperApp().run()

我的kv码:

#:kivy 1.0.9

<MyScreenManager>:
    VendorScreen:  # ........ Incoming Delivery, Screen 2b
        name: 'vendor_screen'
    InvoiceScreen: # ........ .................. Screen 3b
        name: 'invoice_screen'
    MainControlScreen:  # ... .................. Screen 4b
        name: 'main_control_screen'

<BG>
    AsyncImage:
        source: 'img/screen1_background4.png'
        size_hint: 1, 1

<VendorScreen>
    BG:
    FloatLayout:
        Button:
            text: 'name1'
            color: 1.0, 0.6, 0.0, 1
            font_size: 40
            size_hint_x: 0.45
            size_hint_y: 0.35
            pos_hint: {'x': 0.03, 'y': 0.50}
            on_release:
                root.manager.transition.direction = 'left'
                root.manager.current = 'invoice_screen'
        Button:
            text: 'name2'
            color: 1.0, 0.6, 0.0, 1
            font_size: 40
            size_hint_x: 0.45
            size_hint_y: 0.35
            pos_hint: {'x': 0.52, 'y': 0.50}
            on_release:
                root.manager.transition.direction = 'left'
                root.manager.current = 'invoice_screen'
        Button:
            text: 'name3'
            color: 1.0, 0.6, 0.0, 1
            font_size: 40
            size_hint_x: 0.45
            size_hint_y: 0.35
            pos_hint: {'x': 0.03, 'y': 0.10}
            on_release:
                root.manager.transition.direction = 'left'
                root.manager.current = 'invoice_screen'
        Button:
            text: 'name4'
            color: 1.0, 0.6, 0.0, 1
            font_size: 40
            size_hint_x: 0.45
            size_hint_y: 0.35
            pos_hint: {'x': 0.52, 'y': 0.10}
            on_release:
                root.manager.transition.direction = 'left'
                root.manager.current = 'invoice_screen'

<InvoiceScreen>
    BG:
        canvas:
            Color:
                rgba: 0.90, 0.90, 0.90, 0.5
            Rectangle:
                pos: (40, 295)
                size: (320, 35)
            Color:
                rgba: 0, 0, 0, 1
            Line:
                points: 40, 295, 360, 295, 360, 330, 40, 330, 40, 295
                width: 1
    BoxLayout:
        orientation: 'horizontal'  # break it up into left / right
        FloatLayout:
            Label:
                pos_hint: {'x':0, 'y':.25}
                font_size: 30
                text: 'Enter Invoice Number'
                color: 0.1, 0.1, 1, 1
            Label:
                id: invoice
                pos_hint: {'x':0, 'y':.15}
                font_size: 30
                text: ''  # initially blank
                color: 0, 0, 0, 1
        GridLayout:
            cols: 3  # number of columns
            rows: 4  # number of rows
            Button:
                text: '1'
                on_release: root.keyEntry('1')
            Button:
                text: '2'
                on_release: root.keyEntry('2')
            Button:
                text: '3'
                on_release: root.keyEntry('3')
            Button:
                text: '4'
                on_release: root.keyEntry('4')
            Button:
                text: '5'
                on_release: root.keyEntry('5')
            Button:
                text: '6'
                on_release: root.keyEntry('6')
            Button:
                text: '7'
                on_release: root.keyEntry('7')
            Button:
                text: '8'
                on_release: root.keyEntry('8')
            Button:
                text: '9'
                on_release: root.keyEntry('9')
            Button:
                text: '< DEL'
                on_release: root.keyBack()
            Button:
                text: '0'
                on_release: root.keyEntry('0')
            Button:
                text: 'Done'
                on_release:
                    root.set_invoice()
                    root.manager.transition.direction = 'left'
                    root.manager.current = 'main_control_screen'

<MainControlScreen>
    BG:
        canvas:
            Color:
                rgba: 0, 0, 1, 1
            Line:
                points: 500, 180, 770, 180, 770, 450, 500, 450, 500, 180
                width: 3
    FloatLayout:
        Label:  # foreground
            pos_hint: {'x': 0.30, 'y': 0.13}
            font_size: 80
            text: '5'
            color: 1.0, 0.6, 0.0, 1
        Button:
            size_hint_x: 0.2
            size_hint_y: 0.1
            pos_hint: {'x': 0.05, 'y': 0.05}
            text: 'Auto-Reject'
            on_release:
                root.manager.transition.direction = 'up'
                root.manager.current = 'vendor_screen'
        Button:
            size_hint_x: 0.2
            size_hint_y: 0.1
            pos_hint: {'x': 0.75, 'y': 0.05}
            text: 'Photo' 
            on_release:
                root.manager.transition.direction = 'left'
                root.manager.current = 'invoice_screen'

最后是我的额外课程:

from datetime import datetime, date
import calendar


class Storage(object):
    def __init__(self):
        self.invoice = 0
        self.unit_name = ''
        self.unit_number = ''
        self.receiver = ''
        self.vendor = ''
        self.day = calendar.day_name[date.today().weekday()]
        self.delivery_time = datetime.now()  
        self.package_condition = True
        self.email = ''
        self.location = ('32.0, -117.0',)
        self.duration = 0  
        self.img = 'img.jpg'

所以我的问题是,我在哪里以及如何使用我的附加类存储"?我希望所有 kivy 类都能够访问它的单个实例,但我不知道该怎么做.

So my question is, where and how do I use my addtional class 'Storage'? I want all the kivy classes to be able to access a single instance of it, but I cannot figure out how to do that.

我尝试在 mySuperApp().run() 之前实例化一个类,但我无法在其他类中访问它.我尝试使用 global 来访问该实例,但这不起作用.

I tried instantiating a class just before mySuperApp().run() but I cannot access it inside the other classes. I tried using global to access the instance, but that didn't work.

我考虑过从类继承,但我不知道如何做到这一点......我从不同屏幕中的 Storage 继承开始,但是,这不允许我访问包含所有数据的单个实例是,我不得不从多个类中提取实例变量来收集完整的数据集.然后我尝试在 Storage 中继承 mySuperApp,然后从 Storage 中运行 ScreenManager,但这不起作用.它运行了,但我无法从其他类访问实例变量.也许我需要在所有其他类中继续从 Storage 继承?

I thought about inheriting from the class, but I'm not sure how to do this... I started by inheriting from Storage in my different screens, however, that does not let me access a single instance where all my data is, rather I would have to pull instance variables from multiple classes to amass the full data set. Then I tried inheriting mySuperApp in Storage, then running the ScreenManager from Storage, but that didn't work. It ran, but I couldn't access the instance variables from the other classes. Maybe I need to keep inheriting from Storage in all the other classes?

我不确定如何处理这个问题,因为 kivy 部分只是程序的一小部分.最后,我将需要几个额外的课程,但我不明白如何或在哪里链接这些课程.获得概念后,我会将其应用于其他必要的课程,但我不知道从哪里开始.

I'm not sure how to approach this as the kivy part is only a fraction of the program. In the end I will need several additional classes, but I don't understand how or where to link these. Once I get the concept I will apply it to the other necessary classes, but I don't know where to start.

推荐答案

您可以使用 ScreenManager 来共享数据.
ScreenManager 将始终是所有屏幕的父级.因此,您可以通过以下三种方式访问​​管理器.

You could use the ScreenManager to share data.
The ScreenManager will allways be parent of all the screens. So here are three ways you can access the manager.

root.manager:
Screen 都有一个名为 manager 的属性,也就是这个 Screen 所在的 ScreenManager.所以您可以从任何这样的屏幕访问它.

root.manager:
The Screen's all have an attribute called manager, which is the ScreenManager which this Screen is in. So you can access it from any screen like this.

root.parent:
如果 Widget 位于另一个小部件中,它们都将具有它的 parent.在这种情况下,Screen 的父级是 ScreenManager.因此,您可以从任何这样的屏幕访问它.

root.parent:
The Widget's if they are in another widget will all have it's parent. In this case, the Screen's parent is the ScreenManager. So you can access it from any screen like this.

app.root:
每个应用程序都有一个 root.在这种情况下,应用程序的根是 ScreenManager.所以你可以像这样从任何地方访问它.

app.root:
Every app has a root. In this case the root of the app, is the ScreenManager. So you can access it from anywhere like this.

试试这个例子,用三个按钮演示:

Try this example, with three buttons demonstrating this:

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


class MyScreenManager(ScreenManager):
    shared_data = StringProperty("")


class Screen1(Screen):
    pass

class Screen2(Screen):
    pass


root = Builder.load_string('''

<Screen1>:
    name: "screen1"
    BoxLayout:
        orientation: "vertical"
        TextInput:
            on_text:
                root.manager.shared_data = self.text
        Label:
            text:
                root.manager.shared_data
        Button:
            text: "Go to screen2"
            on_release: root.manager.current = "screen2"

        Button:
            text: "root.manager.shared_data"
            on_release:
                print(root.manager.shared_data)
        Button:
            text: "root.parent.shared_data"
            on_release:
                print(root.parent.shared_data)
        Button:
            text: "app.root.shared_data"
            on_release:
                print(app.root.shared_data)



<Screen2>:
    name: "screen2"
    BoxLayout:
        orientation: "vertical"
        TextInput:
            on_text:
                root.manager.shared_data = self.text
        Label:
            text:
                root.manager.shared_data
        Button:
            text: "Go to screen1"
            on_release: root.manager.current = "screen1"


MyScreenManager:
    Screen1:
    Screen2:

''')



class MyApp(App):
    def build(self):
        return root

这篇关于kivy 使用附加类来存储来自多个屏幕的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:kivy 使用附加类来存储来自多个屏幕的数据

基础教程推荐