【问题标题】:Kivy accessing class attributes from screen managerKivy 从屏幕管理器访问类属性
【发布时间】:2020-07-15 02:28:08
【问题描述】:

我正在使用python和kivy制作一个简单的应用程序,但是当我为我的应用程序创建多个屏幕时,我无法访问某些类的类属性。

我在使用屏幕管理器访问方法时遇到问题。

ma​​in.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget


class MyGame(Widget):
    def __init__(self, **kwargs):
        super(MyGame, self).__init__(**kwargs)

    def print_a_word(self):
        print('a word')

class OptionWindow(Screen):
    pass


class SecondWindow(Screen):
    pass


class WindowManager(ScreenManager):
    pass

kv = Builder.load_file('screen_manager.kv')

class MyMainApp(App):
    def build(self):
        return kv

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

kivy 文件 (screen_manager.kv)

#:kivy 2.0.0
# File name: screen_manager.kv
#: import MyGame Widget

WindowManager:

    OptionWindow:
    SecondWindow:

<OptionWindow>:
    name: "main"

    GridLayout:
        cols:1
        canvas.before:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                pos: 0, 0
                size: root.width, root.height
        GridLayout:
            rows: 5
            padding: 50, 50
            spacing: 20, 20
            OptionBtn:
                text: 'Americas'
                on_release:
                    app.root.current = "second"
                    root.manager.transition.direction = "left"



<SecondWindow>:
    name: "second"
    MyGame
    Button:
        on_press: root.MyGame.print_a_word()


<OptionBtn@Button>
    background_normal: 'Images/Other/white.png'
    color: 0, 0, 0, 1
    font_size: 20
    canvas.after:
        Color:
            rgba: 0, 0, 0, 1
        Line:
            rectangle: self.x, self.y, self.size[0], self.size[1]

在我按下第二个窗口的按钮之前,一切正常。我无法从 MyGame(Widget) 访问该方法。我得到'SecondWindow' object has no attribute 'MyGame'

这是一个更大问题的一部分,因为我制作这个文件是为了解决我原来的问题,即... 我有一个大程序,其中有两个文件 main.py 和 my.kv,我想添加屏幕。在这个 main.py 中,所有内容都定义了一个继承自 Widget 的类,并且 build 方法返回该类的一个实例。这就是我从上面制作文件的原因......这是为了了解我如何从 Widget 类中访问。谢谢

【问题讨论】:

  • 请专注于您的问题。无需宣传您正在学习。这是理解和鼓励的。

标签: python kivy kivy-language


【解决方案1】:

我在这里修复了您的示例代码,现在可以访问和执行 MyGame() 对象中的 print_my_word() 方法,这应该足以让您挡道。

只有 kv 文件需要更改:

在“MyGame”对象中使用包含而不是导入:
#: 包括 MyGame

对象中实例化它。

为其添加了一个 id,以便能够访问它。

WindowManager:

    OptionWindow:
    SecondWindow:

<OptionWindow>:
    name: "main"

    GridLayout:
        cols:1
        canvas.before:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                pos: 0, 0
                size: root.width, root.height
        GridLayout:
            rows: 5
            padding: 50, 50
            spacing: 20, 20
            OptionBtn:
                text: 'Americas'
                on_release:
                    app.root.current = "second"
                    root.manager.transition.direction = "left"



<SecondWindow>:
    name: "second"
    MyGame:
        id: my_game
    Button:
        on_press: my_game.print_a_word()


<OptionBtn@Button>
    background_normal: 'Images/Other/white.png'
    color: 0, 0, 0, 1
    font_size: 20
    canvas.after:
        Color:
            rgba: 0, 0, 0, 1
        Line:
            rectangle: self.x, self.y, self.size[0], self.size[1]

好的,下面的下一部分是更新,以在第二条评论中回答您的问题。

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget


class MyGame(Widget):
    def __init__(self, **kwargs):
        super(MyGame, self).__init__(**kwargs)

    def print_a_word(self):
        print('My Game: print method')

class OptionWindow(Screen):
    pass


class SecondWindow(Screen):
    pass


class WindowManager(ScreenManager):
    pass

kv = Builder.load_file('screen_manager.kv')

class MyMainApp(App):
    def build(self):
        self.my_game = MyGame()  # <-- instantiated MyGame in the Main class to access it from any where
        return kv

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

screen_manager.kv

WindowManager:
    OptionWindow:
    SecondWindow:



<OptionWindow>:
    name: "main"

    GridLayout:
        cols:1
        canvas.before:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                pos: 0, 0
                size: root.width, root.height
        GridLayout:
            rows: 5
            padding: 50, 50
            spacing: 20, 20
            OptionBtn:
                text: 'Americas'
                on_release:
                    app.root.current = "second"
                    root.manager.transition.direction = "left"
            # ADDED EXTRA BUTTON TO SAMPLE ACCESSING MyGame OBJECT, FROM THIS CLASS
            Button:
                text: 'Access My Game Method'
                on_release:
                    app.my_game.print_a_word()   # <-- app can access main class attributes and methods



<SecondWindow>:
    name: "second"
    # USE A BOXLAYOUT TO LAYOUT THE BUTTONS
    BoxLayout:
        orientation: 'vertical'
        spacing: 2
        padding: 2
        # ADDED BUTTON TO SAMPLE ACCESSING MyGame OBJECT
        Button:
            text: 'Access method from MyGame'
            on_press: app.my_game.print_a_word()     # <-- app can access main class attributes and methods
        Button:
            text: 'Return to Main'
            on_press: app.root.current = "main"



<OptionBtn@Button>
    background_normal: 'Images/Other/white.png'
    color: 0, 0, 0, 1
    font_size: 20
    canvas.after:
        Color:
            rgba: 0, 0, 0, 1
        Line:
            rectangle: self.x, self.y, self.size[0], self.size[1]

【讨论】:

  • 无论如何,你知道我如何从另一个类访问 my_game.print_a_word() ,比如 吗?我已经尝试了各种各样的东西,例如 app.root.second.my_game.print_a_word(),但都是徒劳的。谢谢你,我开始明白了
  • 我更新了回复以回答您之前的评论,希望对您有所帮助。
猜你喜欢
  • 2015-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
相关资源
最近更新 更多