Python,Kivy - 在 Popup 中使用创建的模块时出现问题(无法识别)
Python, Kivy - Problem using created module in Popup (not recognised)
在我的应用程序中,可以收集硬币来解锁新的背景和服装,为此我使用了一个名为 packData 的单独模块。
问题是运行应用程序正常时无法识别packData。如果我 return 只有 Popup,它就可以正常工作。在我开始使用 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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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}}
抱歉,如果代码中的某些部分没有意义。该应用程序仍处于起步阶段,我还尝试进行一些更改以使其正常运行。我试着尽可能地清理它。
希望有人能帮帮我,先谢谢了!
我认为问题出在您的 kv
上。该行:
<PopupBg@Popup>:
定义了一个名为 PopupBg
的自定义 class,但您已经在 main.py
中定义了一个 PopupBg
class。尝试将 kv
中的那一行更改为:
<PopupBg>:
这样您就不会定义新的 class,而是使用已经定义的 class。
在我的应用程序中,可以收集硬币来解锁新的背景和服装,为此我使用了一个名为 packData 的单独模块。
问题是运行应用程序正常时无法识别packData。如果我 return 只有 Popup,它就可以正常工作。在我开始使用 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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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/Whosebug/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}}
抱歉,如果代码中的某些部分没有意义。该应用程序仍处于起步阶段,我还尝试进行一些更改以使其正常运行。我试着尽可能地清理它。
希望有人能帮帮我,先谢谢了!
我认为问题出在您的 kv
上。该行:
<PopupBg@Popup>:
定义了一个名为 PopupBg
的自定义 class,但您已经在 main.py
中定义了一个 PopupBg
class。尝试将 kv
中的那一行更改为:
<PopupBg>:
这样您就不会定义新的 class,而是使用已经定义的 class。