Python、Kivy - 在 Popup 中使用创建的模块时出现问题(无法识别)

发布于 2025-01-12 17:41:46 字数 21921 浏览 0 评论 0原文

在我的应用程序中,可以收集硬币来解锁新的背景和服装,为此我使用了一个名为 packData 的单独模块。

问题是正常运行应用程序时无法识别 packData。如果我只返回弹出窗口,它就会按预期工作。在我开始使用 ScreenManager 后,这种情况开始发生,但我不认为这是问题所在,因为我尝试在没有它的情况下运行应用程序,但它仍然无法工作。

我不确定这是否是由于我对 Python/Kivy 理解不够好、我多次调用部分代码、一个不经意的错误或其他原因造成的。

回溯:

 Traceback (most recent call last):
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 242, in create_handler
     return eval(value, idmap), bound_list
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68, in <module>
     source: root.packData.backgrounds[1]
   File "kivy/weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'PopupBg' object has no attribute 'packData'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 924, in _build_canvas
     value, _ = create_handler(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 245, in create_handler
     raise BuilderException(rule.ctx, rule.line,
 kivy.lang.builder.BuilderException: Parser: File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68:
 ...
      66:                        size: self.width, self.height
      67:                        pos: self.pos
 >>   68:                        source: root.packData.backgrounds[1]
      69:
      70:            Button:
 ...
 AttributeError: 'PopupBg' object has no attribute 'packData'
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 242, in create_handler
     return eval(value, idmap), bound_list
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68, in <module>
     source: root.packData.backgrounds[1]
   File "kivy/weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__


 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/main.py", line 235, in <module>
     TestApp().run()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/app.py", line 955, in run
     runTouchApp()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 570, in runTouchApp
     EventLoop.mainloop()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 335, in mainloop
     self.idle()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 379, in idle
     self.dispatch_input()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 330, in dispatch_input
     post_dispatch_input(*pop(0))
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 299, in post_dispatch_input
     wid.dispatch('on_touch_up', me)
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/behaviors/button.py", line 179, in on_touch_up
     self.dispatch('on_release')
   File "kivy/_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch
   File "kivy/_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1191, in kivy._event.EventObservers._dispatch
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 57, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 191, in <module>
     on_release: Factory.PopupBg().open()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/modalview.py", line 195, in __init__
     super(ModalView, self).__init__(**kwargs)
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/anchorlayout.py", line 68, in __init__
     super(AnchorLayout, self).__init__(**kwargs)
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/layout.py", line 76, in __init__
     super(Layout, self).__init__(**kwargs)
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/widget.py", line 359, in __init__
     self.apply_class_lang_rules(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/widget.py", line 463, in apply_class_lang_rules
     Builder.apply(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 542, in apply
     self._apply_rule(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 664, in _apply_rule
     self._apply_rule(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 664, in _apply_rule
     self._apply_rule(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 664, in _apply_rule
     self._apply_rule(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 597, in _apply_rule
     self._build_canvas(widget.canvas.before, widget,
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 930, in _build_canvas
     raise BuilderException(
 kivy.lang.builder.BuilderException: Parser: File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68:
 ...
      66:                        size: self.width, self.height
      67:                        pos: self.pos
 >>   68:                        source: root.packData.backgrounds[1]
      69:
      70:            Button:
 ...
 BuilderException: Parser: File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68:
 ...
      66:                        size: self.width, self.height
      67:                        pos: self.pos
 >>   68:                        source: root.packData.backgrounds[1]
      69:
      70:            Button:
 ...
 AttributeError: 'PopupBg' object has no attribute 'packData'
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 242, in create_handler
     return eval(value, idmap), bound_list
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68, in <module>
     source: root.packData.backgrounds[1]
   File "kivy/weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__

   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 924, in _build_canvas
     value, _ = create_handler(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 245, in create_handler
     raise BuilderException(rule.ctx, rule.line,


Process finished with exit code 1

代码:

main.py

# Using kivy 2.0.0 and python3.8

import kivy

from kivy.config import Config  # For setting height (19.5:9)
from kivy.factory import Factory
from kivy.graphics import Rectangle, RoundedRectangle, Color, InstructionGroup
from kivy.uix.gridlayout import GridLayout

from kivy.app import App
from kivy.lang import Builder

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup

from kivy.properties import ObjectProperty
from kivy.clock import Clock
from kivy.storage.jsonstore import JsonStore

import packData


kivy.require('2.0.0')  # Version of Kivy
Config.set('graphics', 'width', '360')  # (New Android smartphones e.g. OnePlus 7 series)
Config.set('graphics', 'height', '640')  # (iPhone X, 11 and 12 series, upsampled)
store = JsonStore('resources/user_data.json')  # For saving high score
root_widget = Builder.load_file('layout.kv')

class PopupBg(Popup):
   bg = store.get('custom')['current_bg']
   packData = packData
   bg_unlocked = store.get('backgrounds')['unlocked']
   bg_price = store.get('backgrounds')['price']

   selected = 0  # View currently selected background
   selection_rects = []

   current_bg = 1
   bg_index = 'bg' + str(current_bg)

   bg_btn1 = ObjectProperty(None)

   bg_btn2 = ObjectProperty(None)
   buy_btn2 = ObjectProperty(None)

   bg_btn3 = ObjectProperty(None)
   buy_btn3 = ObjectProperty(None)

   bg_btn = [None, bg_btn1, bg_btn2, bg_btn3]

   price = ObjectProperty(0)
   price_str = str(bg_price) + 'KC'

   wallet = store.get("wallet")["coins"]
   print(wallet)

   # Function to ensure buttons are disabled/enabled where need to
   def update(self, dt):

       if store['backgrounds']['unlocked']['bg2']:
           self.buy_btn2.disabled = True
           self.bg_btn2.disabled = False
           self.buy_btn2.text = 'Bought'
           print('bg2')

       if store['backgrounds']['unlocked']['bg3']:
           self.buy_btn3.disabled = True
           self.bg_btn2.disabled = False
           self.buy_btn3.text = 'Bought'
           print('bg3')

       if store.get('custom')['current_bg'] == 'resources/backgrounds/wallpaper.png':

           if self.selected == 0:

               self.selected = 1

               if len(self.selection_rects) != 0:
                   item = self.selection_rects.pop(-1)
                   try:
                       self.bg_btn1.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn2.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn3.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')

               self.obj = InstructionGroup()
               self.obj.add(Color(0, .7, .7, .7))
               self.obj.add(RoundedRectangle(size=self.bg_btn1.size, pos=self.bg_btn1.pos))
               self.selection_rects.append(self.obj)
               self.bg_btn1.canvas.before.add(self.obj)

       if store.get('custom')['current_bg'] == 'resources/backgrounds/wallpaper2.png':

           if self.selected == 0:

               self.selected = 1

               if len(self.selection_rects) != 0:
                   item = self.selection_rects.pop(-1)
                   try:
                       self.bg_btn1.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn2.canvas.before.remove(item)
                       self.bg_btn2.text = ''
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn3.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')

               self.obj = InstructionGroup()
               self.obj.add(Color(0, .7, .7, .7))
               self.obj.add(RoundedRectangle(size=self.bg_btn2.size, pos=self.bg_btn2.pos))
               self.selection_rects.append(self.obj)
               self.bg_btn2.canvas.before.add(self.obj)

       if store.get('custom')['current_bg'] == 'resources/backgrounds/wallpaper3.png':

           if self.selected == 0:

               self.selected = 1

               if len(self.selection_rects) != 0:
                   item = self.selection_rects.pop(-1)
                   try:
                       self.bg_btn1.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn2.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn3.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')

               self.obj = InstructionGroup()
               self.obj.add(Color(0, .7, .7, .7))
               self.obj.add(RoundedRectangle(size=self.bg_btn3.size, pos=self.bg_btn3.pos))
               self.selection_rects.append(self.obj)
               self.bg_btn3.canvas.before.add(self.obj)

   def checkout(self):

       if self.price <= self.wallet:

           print("Kaching!")
           self.wallet = self.wallet - self.bg_price
           print('current wallet: ', self.wallet)
           store.put("wallet", coins=self.wallet)

           store['backgrounds']['unlocked'][self.bg_index] = True

           self.title = ('KaruCoins: ' + str(round(self.wallet)))

       else:
           print("Not enough coins")

   def background_change(self):

       self.bg_index = 'bg' + str(self.current_bg)

       if self.bg_unlocked[self.bg_index]:

           store.put("custom", current_bg=self.packData.backgrounds[self.current_bg])

           print("click")
           Clock.schedule_once(self.update, -1)

       elif not self.bg_unlocked[self.bg_index]:

           print("Not bought")
           self.checkout()


class KaruHouse(Screen, BoxLayout):
   pass


class WindowManager(ScreenManager):
   pass


class TestApp(App):
   WindowManager = WindowManager()

   def build(self):
       self.icon = 'resources/icons/karuicon.png'
       return self.WindowManager
       # return PopupBg()


TestApp().run()

layout.kv

#: kivy 2.1.0
#: import WipeTransition kivy.uix.screenmanager.WipeTransition
#:import hex kivy.utils.get_color_from_hex
#: import JsonStore kivy.storage.jsonstore
#:import Factory kivy.factory.Factory
#: import Clock kivy.clock.Clock

<WindowManager>:
    transition: WipeTransition()
    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            pos: self.pos
            size: self.size
    KaruHouse:
        id: kh

<PopupBg@Popup>:
    size_hint_y: .65
    size_hint_x: .8

    #kh: app.root.ids.kh
    title: ('KaruCoins: ' + str(round(self.wallet)))
    bg_btn1: bg_btn1


    bg_btn2: bg_btn2
    buy_btn2: buy_btn2

    bg_btn3: bg_btn3
    buy_btn3: buy_btn3

    on_open: Clock.schedule_once(self.update, -1); Clock.schedule_interval(self.update, .1)
    on_dismiss: Clock.unschedule(self.update)

    ScrollView:

        do_scroll_x: True
        do_scroll_y: False
        pos: root.width, root.height
        GridLayout:
            cols: 3
            rows: 2
            padding: 135, 75, 135 ,75
            spacing: 165, 25
            size_hint_y: None
            height: self.minimum_height
            size_hint_x: None
            width: self.minimum_width
            Button:
                id: bg_btn1
                on_press: root.current_bg = 1
                on_release: root.background_change(); root.selected = 0
                font_size: 32
                size: 360/1.5, 640/1.5
                size_hint: None, None
                pos: root.width/4, root.height/6
                background_color: 0, 0, 0, 0
                canvas.before:
                    Color:
                        rgba: (1,1,1,1)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos
                        source: root.packData.backgrounds[1]

            Button:
                id: bg_btn2
                disabled: True if not root.bg_unlocked['bg2'] else False
                color: 1, 1, 1, 1
                on_press: root.current_bg = 2
                on_release: root.background_change(); root.selected = 0
                font_size: 30
                size: 360/1.5, 640/1.5
                size_hint: None, None
                pos: root.width/4, root.height/6
                background_color: 0, 0, 0, 0
                canvas.before:
                    Color:
                        rgba: (1,1,1,1)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos
                        source: root.packData.backgrounds[2]
                canvas.after:
                    Color:
                        rgba: (1,1,1,0) if bg_btn2.disabled==False else (115/255,115/255,115/255, .9)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos

            Button:
                id: bg_btn3
                disabled: True if not root.bg_unlocked['bg3'] else False
                color: 1, 1, 1, 1
                on_press: root.current_bg = 3
                on_release: root.background_change(); root.selected = 0
                font_size: 30
                size: 360/1.5, 640/1.5
                size_hint: None, None
                pos: root.width/4, root.height/6
                background_color: 0, 0, 0, 0
                canvas.before:
                    Color:
                        rgba: (1,1,1,1)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos
                        source: root.packData.backgrounds[3]
                canvas.after:
                    Color:
                        rgba: (1,1,1,0) if bg_btn3.disabled==False else (115/255,115/255,115/255, .9)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos

            Button:
                id: buy_btn1
                disabled: True
                text: root.price_str if not root.bg_unlocked['bg1'] else 'Bought'
                bold: True
                background_color: 0, 0, 0, 0
                pos: self.pos
                size_hint: None, None
                size: 360/1.5, 640/8
                canvas.before:
                    Color:
                        rgba: 0,.7,.7,1
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size

            Button:
                id: buy_btn2
                disabled: False if not root.bg_unlocked['bg2'] else True
                text: root.price_str if not root.bg_unlocked['bg2'] else 'Bought'
                bold: True
                on_press: root.current_bg = 2;
                on_release: root.background_change()
                background_color: 0, 0, 0, 0
                pos: self.pos
                size_hint: None, None
                size: 360/1.5, 640/8
                canvas.before:
                    Color:
                        rgba: (0,.7,.7,1) if self.state=='normal' else (0,.7,.7,.7)
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size

            Button:
                id: buy_btn3
                disabled: False if not root.bg_unlocked['bg3'] else True
                text: root.price_str if not root.bg_unlocked['bg3'] else 'Bought'
                bold: True
                on_press: root.current_bg = 3;
                on_release: root.background_change()
                background_color: 0, 0, 0, 0
                pos: self.pos
                size_hint: None, None
                size: 360/1.5, 640/8
                canvas.before:
                    Color:
                        rgba: (0,.7,.7,1) if self.state=='normal' else (0,.7,.7,.7)
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size

<KaruHouse>:
    name: "third"
    orientation: 'vertical'
    size: root.width, root.height
    secondary_color: .4,.4,.4,.8
    secondary_color2: 0,.7,.7,.8

    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            pos: self.pos
            size: self.size


    Button:
        text: 'Backgrounds'
        size: root.width/2, root.height/12
        size_hint: None, None
        on_release: Factory.PopupBg().open()
        pos: root.width/4, root.height/1.5
        background_color: 0, 0, 0, 0
        canvas.before:
            Color:
                rgba: root.secondary_color if self.state=='normal' else root.secondary_color2
            RoundedRectangle:
                size: self.size
                pos: self.pos

    Button:
        text: "Menu"
        font_size: 32
        on_release: print('click')
        size: root.width/2, root.height/12
        size_hint: None, None
        pos: root.width/4, root.height/3.3
        background_color: 0, 0, 0, 0
        canvas.before:
            Color:
                rgba: root.secondary_color if self.state=='normal' else root.secondary_color2
            RoundedRectangle:
                size: self.size
                pos: self.pos


packData.py


# backgrounds
backgrounds = {1: 'resources/backgrounds/wallpaper.png', 2: 'resources/backgrounds/wallpaper2.png', 3: 'resources/backgrounds/wallpaper3.png'}

user_data.json

{"data": {"highscore": 238}, "wallet": {"coins": 703}, "custom": {"current_bg": "resources/backgrounds/wallpaper2.png"}, "backgrounds": {"unlocked": {"bg1": true, "bg2": false, "bg3": false}, "price": 250}, "outfits": {"unlocked": 0}}

抱歉,如果代码中有些部分没有意义。该应用程序仍处于开始阶段,我还尝试更改一些内容以使其正常工作。我尝试尽可能地清理它。

希望有人能帮助我,先谢谢你了!

In my app, coins can be collected to unlock new backgrounds and outfits, for which I use a separate module called packData.

The problem is that packData is not recognised when running the app normally. If I return only the Popup it works as it should. This started happening after I started using ScreenManager, but I don't think that's the problem because I tried running the app without it and it still didn't work.

I'm not sure if this is caused by me not understanding Python/Kivy well enough, me calling a part of the code too many times, a thoughtless mistake, or something else.

Traceback:

 Traceback (most recent call last):
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 242, in create_handler
     return eval(value, idmap), bound_list
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68, in <module>
     source: root.packData.backgrounds[1]
   File "kivy/weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'PopupBg' object has no attribute 'packData'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 924, in _build_canvas
     value, _ = create_handler(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 245, in create_handler
     raise BuilderException(rule.ctx, rule.line,
 kivy.lang.builder.BuilderException: Parser: File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68:
 ...
      66:                        size: self.width, self.height
      67:                        pos: self.pos
 >>   68:                        source: root.packData.backgrounds[1]
      69:
      70:            Button:
 ...
 AttributeError: 'PopupBg' object has no attribute 'packData'
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 242, in create_handler
     return eval(value, idmap), bound_list
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68, in <module>
     source: root.packData.backgrounds[1]
   File "kivy/weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__


 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/main.py", line 235, in <module>
     TestApp().run()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/app.py", line 955, in run
     runTouchApp()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 570, in runTouchApp
     EventLoop.mainloop()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 335, in mainloop
     self.idle()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 379, in idle
     self.dispatch_input()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 330, in dispatch_input
     post_dispatch_input(*pop(0))
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/base.py", line 299, in post_dispatch_input
     wid.dispatch('on_touch_up', me)
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/behaviors/button.py", line 179, in on_touch_up
     self.dispatch('on_release')
   File "kivy/_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch
   File "kivy/_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1191, in kivy._event.EventObservers._dispatch
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 57, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 191, in <module>
     on_release: Factory.PopupBg().open()
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/modalview.py", line 195, in __init__
     super(ModalView, self).__init__(**kwargs)
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/anchorlayout.py", line 68, in __init__
     super(AnchorLayout, self).__init__(**kwargs)
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/layout.py", line 76, in __init__
     super(Layout, self).__init__(**kwargs)
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/widget.py", line 359, in __init__
     self.apply_class_lang_rules(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/uix/widget.py", line 463, in apply_class_lang_rules
     Builder.apply(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 542, in apply
     self._apply_rule(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 664, in _apply_rule
     self._apply_rule(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 664, in _apply_rule
     self._apply_rule(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 664, in _apply_rule
     self._apply_rule(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 597, in _apply_rule
     self._build_canvas(widget.canvas.before, widget,
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 930, in _build_canvas
     raise BuilderException(
 kivy.lang.builder.BuilderException: Parser: File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68:
 ...
      66:                        size: self.width, self.height
      67:                        pos: self.pos
 >>   68:                        source: root.packData.backgrounds[1]
      69:
      70:            Button:
 ...
 BuilderException: Parser: File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68:
 ...
      66:                        size: self.width, self.height
      67:                        pos: self.pos
 >>   68:                        source: root.packData.backgrounds[1]
      69:
      70:            Button:
 ...
 AttributeError: 'PopupBg' object has no attribute 'packData'
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 242, in create_handler
     return eval(value, idmap), bound_list
   File "/Users/User/Documents/Python/StackOverflow/PopupBgProblem/layout.kv", line 68, in <module>
     source: root.packData.backgrounds[1]
   File "kivy/weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__

   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 924, in _build_canvas
     value, _ = create_handler(
   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/kivy/lang/builder.py", line 245, in create_handler
     raise BuilderException(rule.ctx, rule.line,


Process finished with exit code 1

Code:

main.py

# Using kivy 2.0.0 and python3.8

import kivy

from kivy.config import Config  # For setting height (19.5:9)
from kivy.factory import Factory
from kivy.graphics import Rectangle, RoundedRectangle, Color, InstructionGroup
from kivy.uix.gridlayout import GridLayout

from kivy.app import App
from kivy.lang import Builder

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup

from kivy.properties import ObjectProperty
from kivy.clock import Clock
from kivy.storage.jsonstore import JsonStore

import packData


kivy.require('2.0.0')  # Version of Kivy
Config.set('graphics', 'width', '360')  # (New Android smartphones e.g. OnePlus 7 series)
Config.set('graphics', 'height', '640')  # (iPhone X, 11 and 12 series, upsampled)
store = JsonStore('resources/user_data.json')  # For saving high score
root_widget = Builder.load_file('layout.kv')

class PopupBg(Popup):
   bg = store.get('custom')['current_bg']
   packData = packData
   bg_unlocked = store.get('backgrounds')['unlocked']
   bg_price = store.get('backgrounds')['price']

   selected = 0  # View currently selected background
   selection_rects = []

   current_bg = 1
   bg_index = 'bg' + str(current_bg)

   bg_btn1 = ObjectProperty(None)

   bg_btn2 = ObjectProperty(None)
   buy_btn2 = ObjectProperty(None)

   bg_btn3 = ObjectProperty(None)
   buy_btn3 = ObjectProperty(None)

   bg_btn = [None, bg_btn1, bg_btn2, bg_btn3]

   price = ObjectProperty(0)
   price_str = str(bg_price) + 'KC'

   wallet = store.get("wallet")["coins"]
   print(wallet)

   # Function to ensure buttons are disabled/enabled where need to
   def update(self, dt):

       if store['backgrounds']['unlocked']['bg2']:
           self.buy_btn2.disabled = True
           self.bg_btn2.disabled = False
           self.buy_btn2.text = 'Bought'
           print('bg2')

       if store['backgrounds']['unlocked']['bg3']:
           self.buy_btn3.disabled = True
           self.bg_btn2.disabled = False
           self.buy_btn3.text = 'Bought'
           print('bg3')

       if store.get('custom')['current_bg'] == 'resources/backgrounds/wallpaper.png':

           if self.selected == 0:

               self.selected = 1

               if len(self.selection_rects) != 0:
                   item = self.selection_rects.pop(-1)
                   try:
                       self.bg_btn1.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn2.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn3.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')

               self.obj = InstructionGroup()
               self.obj.add(Color(0, .7, .7, .7))
               self.obj.add(RoundedRectangle(size=self.bg_btn1.size, pos=self.bg_btn1.pos))
               self.selection_rects.append(self.obj)
               self.bg_btn1.canvas.before.add(self.obj)

       if store.get('custom')['current_bg'] == 'resources/backgrounds/wallpaper2.png':

           if self.selected == 0:

               self.selected = 1

               if len(self.selection_rects) != 0:
                   item = self.selection_rects.pop(-1)
                   try:
                       self.bg_btn1.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn2.canvas.before.remove(item)
                       self.bg_btn2.text = ''
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn3.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')

               self.obj = InstructionGroup()
               self.obj.add(Color(0, .7, .7, .7))
               self.obj.add(RoundedRectangle(size=self.bg_btn2.size, pos=self.bg_btn2.pos))
               self.selection_rects.append(self.obj)
               self.bg_btn2.canvas.before.add(self.obj)

       if store.get('custom')['current_bg'] == 'resources/backgrounds/wallpaper3.png':

           if self.selected == 0:

               self.selected = 1

               if len(self.selection_rects) != 0:
                   item = self.selection_rects.pop(-1)
                   try:
                       self.bg_btn1.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn2.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')
                   try:
                       self.bg_btn3.canvas.before.remove(item)
                   except ValueError:
                       print('nothing to remove')

               self.obj = InstructionGroup()
               self.obj.add(Color(0, .7, .7, .7))
               self.obj.add(RoundedRectangle(size=self.bg_btn3.size, pos=self.bg_btn3.pos))
               self.selection_rects.append(self.obj)
               self.bg_btn3.canvas.before.add(self.obj)

   def checkout(self):

       if self.price <= self.wallet:

           print("Kaching!")
           self.wallet = self.wallet - self.bg_price
           print('current wallet: ', self.wallet)
           store.put("wallet", coins=self.wallet)

           store['backgrounds']['unlocked'][self.bg_index] = True

           self.title = ('KaruCoins: ' + str(round(self.wallet)))

       else:
           print("Not enough coins")

   def background_change(self):

       self.bg_index = 'bg' + str(self.current_bg)

       if self.bg_unlocked[self.bg_index]:

           store.put("custom", current_bg=self.packData.backgrounds[self.current_bg])

           print("click")
           Clock.schedule_once(self.update, -1)

       elif not self.bg_unlocked[self.bg_index]:

           print("Not bought")
           self.checkout()


class KaruHouse(Screen, BoxLayout):
   pass


class WindowManager(ScreenManager):
   pass


class TestApp(App):
   WindowManager = WindowManager()

   def build(self):
       self.icon = 'resources/icons/karuicon.png'
       return self.WindowManager
       # return PopupBg()


TestApp().run()

layout.kv

#: kivy 2.1.0
#: import WipeTransition kivy.uix.screenmanager.WipeTransition
#:import hex kivy.utils.get_color_from_hex
#: import JsonStore kivy.storage.jsonstore
#:import Factory kivy.factory.Factory
#: import Clock kivy.clock.Clock

<WindowManager>:
    transition: WipeTransition()
    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            pos: self.pos
            size: self.size
    KaruHouse:
        id: kh

<PopupBg@Popup>:
    size_hint_y: .65
    size_hint_x: .8

    #kh: app.root.ids.kh
    title: ('KaruCoins: ' + str(round(self.wallet)))
    bg_btn1: bg_btn1


    bg_btn2: bg_btn2
    buy_btn2: buy_btn2

    bg_btn3: bg_btn3
    buy_btn3: buy_btn3

    on_open: Clock.schedule_once(self.update, -1); Clock.schedule_interval(self.update, .1)
    on_dismiss: Clock.unschedule(self.update)

    ScrollView:

        do_scroll_x: True
        do_scroll_y: False
        pos: root.width, root.height
        GridLayout:
            cols: 3
            rows: 2
            padding: 135, 75, 135 ,75
            spacing: 165, 25
            size_hint_y: None
            height: self.minimum_height
            size_hint_x: None
            width: self.minimum_width
            Button:
                id: bg_btn1
                on_press: root.current_bg = 1
                on_release: root.background_change(); root.selected = 0
                font_size: 32
                size: 360/1.5, 640/1.5
                size_hint: None, None
                pos: root.width/4, root.height/6
                background_color: 0, 0, 0, 0
                canvas.before:
                    Color:
                        rgba: (1,1,1,1)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos
                        source: root.packData.backgrounds[1]

            Button:
                id: bg_btn2
                disabled: True if not root.bg_unlocked['bg2'] else False
                color: 1, 1, 1, 1
                on_press: root.current_bg = 2
                on_release: root.background_change(); root.selected = 0
                font_size: 30
                size: 360/1.5, 640/1.5
                size_hint: None, None
                pos: root.width/4, root.height/6
                background_color: 0, 0, 0, 0
                canvas.before:
                    Color:
                        rgba: (1,1,1,1)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos
                        source: root.packData.backgrounds[2]
                canvas.after:
                    Color:
                        rgba: (1,1,1,0) if bg_btn2.disabled==False else (115/255,115/255,115/255, .9)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos

            Button:
                id: bg_btn3
                disabled: True if not root.bg_unlocked['bg3'] else False
                color: 1, 1, 1, 1
                on_press: root.current_bg = 3
                on_release: root.background_change(); root.selected = 0
                font_size: 30
                size: 360/1.5, 640/1.5
                size_hint: None, None
                pos: root.width/4, root.height/6
                background_color: 0, 0, 0, 0
                canvas.before:
                    Color:
                        rgba: (1,1,1,1)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos
                        source: root.packData.backgrounds[3]
                canvas.after:
                    Color:
                        rgba: (1,1,1,0) if bg_btn3.disabled==False else (115/255,115/255,115/255, .9)
                    RoundedRectangle:
                        size: self.width, self.height
                        pos: self.pos

            Button:
                id: buy_btn1
                disabled: True
                text: root.price_str if not root.bg_unlocked['bg1'] else 'Bought'
                bold: True
                background_color: 0, 0, 0, 0
                pos: self.pos
                size_hint: None, None
                size: 360/1.5, 640/8
                canvas.before:
                    Color:
                        rgba: 0,.7,.7,1
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size

            Button:
                id: buy_btn2
                disabled: False if not root.bg_unlocked['bg2'] else True
                text: root.price_str if not root.bg_unlocked['bg2'] else 'Bought'
                bold: True
                on_press: root.current_bg = 2;
                on_release: root.background_change()
                background_color: 0, 0, 0, 0
                pos: self.pos
                size_hint: None, None
                size: 360/1.5, 640/8
                canvas.before:
                    Color:
                        rgba: (0,.7,.7,1) if self.state=='normal' else (0,.7,.7,.7)
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size

            Button:
                id: buy_btn3
                disabled: False if not root.bg_unlocked['bg3'] else True
                text: root.price_str if not root.bg_unlocked['bg3'] else 'Bought'
                bold: True
                on_press: root.current_bg = 3;
                on_release: root.background_change()
                background_color: 0, 0, 0, 0
                pos: self.pos
                size_hint: None, None
                size: 360/1.5, 640/8
                canvas.before:
                    Color:
                        rgba: (0,.7,.7,1) if self.state=='normal' else (0,.7,.7,.7)
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size

<KaruHouse>:
    name: "third"
    orientation: 'vertical'
    size: root.width, root.height
    secondary_color: .4,.4,.4,.8
    secondary_color2: 0,.7,.7,.8

    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            pos: self.pos
            size: self.size


    Button:
        text: 'Backgrounds'
        size: root.width/2, root.height/12
        size_hint: None, None
        on_release: Factory.PopupBg().open()
        pos: root.width/4, root.height/1.5
        background_color: 0, 0, 0, 0
        canvas.before:
            Color:
                rgba: root.secondary_color if self.state=='normal' else root.secondary_color2
            RoundedRectangle:
                size: self.size
                pos: self.pos

    Button:
        text: "Menu"
        font_size: 32
        on_release: print('click')
        size: root.width/2, root.height/12
        size_hint: None, None
        pos: root.width/4, root.height/3.3
        background_color: 0, 0, 0, 0
        canvas.before:
            Color:
                rgba: root.secondary_color if self.state=='normal' else root.secondary_color2
            RoundedRectangle:
                size: self.size
                pos: self.pos


packData.py


# backgrounds
backgrounds = {1: 'resources/backgrounds/wallpaper.png', 2: 'resources/backgrounds/wallpaper2.png', 3: 'resources/backgrounds/wallpaper3.png'}

user_data.json

{"data": {"highscore": 238}, "wallet": {"coins": 703}, "custom": {"current_bg": "resources/backgrounds/wallpaper2.png"}, "backgrounds": {"unlocked": {"bg1": true, "bg2": false, "bg3": false}, "price": 250}, "outfits": {"unlocked": 0}}

Sorry if there are parts in the code that don't make sense. The app is still in the beginning phase and I've also tried to change up a few things to make it work. I tried to clean it up as much as possible.

Hopefully someone can help me out, thank you in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

叫思念不要吵 2025-01-19 17:41:46

我认为问题出在你的kv上。该行:

<PopupBg@Popup>:

定义了一个名为 PopupBg 的自定义类,但您已经在 main.py 中定义了一个 PopupBg 类。尝试将 kv 中的该行更改为:

<PopupBg>:

这样您就不会定义新类,而是使用已定义的类。

I think the problem is in your kv. The line:

<PopupBg@Popup>:

defines a custom class named PopupBg, but you have already defined a PopupBg class in your main.py. Try just changing that line in your kv to:

<PopupBg>:

so that you are not defining a new class, but using the already defined class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文