在尝试创建小部件来模仿多项选择测验的功能时,遇到了一个我找不到任何解决方案的错误。我读了this post,但没有发现适合我具体情况的任何内容。
我正在尝试从.JSON文件加载一组设置,并将它们用作我的KV对象的主要属性。例如,从文件中加载“ canvas_color”设置,并将该值分配给我的小部件的画布颜色。
当我尝试执行此操作时,出现错误:
AttributeError: 'MultipleChoiceT' object has no attribute 'settings'
我的.py文件包含“缺少”属性:
import kivy
import json
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.app import App
kivy.require("1.11.1")
Builder.load_file("MultipleChoice_text.kv")
class MultipleChoiceT(BoxLayout):
# collects info from json file and assigns it to settings var
with open('widget_settings.json', 'r') as file:
settings = json.load(file)["MultipleChoice_settings"][0]
print(settings)
test = 'hello'
def __init__(self, **kwargs):
super(MultipleChoiceT, self).__init__(**kwargs)
self.app = App.get_running_app()
print(self.app)
self.w_width = 0.5
self.w_height = 1
self.data = {'pressed_btn': 0, 'btn_text': None}
# the function called for when the toggle button is on_state
def pressed(self, instance):
self.data['pressed_btn'] = self.get_id(instance)
self.data['btn_text'] = instance.text
print(self.data)
# changes the bottom label when submit button is pressed
def submit(self):
self.bottom_label.text = f"ID: {self.data['pressed_btn']} TEXT: {self.data['btn_text']}"
# returns the id of the given instance
@staticmethod
def get_id(instance):
for id, widget in instance.parent.ids.items():
if widget.__self__ == instance:
return id
# null method for now, not implemented
def change_question(self, new_text):
self.question_label.text = str(new_text)
# prints text when the next question button is pressed
def next_question(self):
print('next question pressed')
# returns the dimensions for the toggle buttons based on their text length and font size defined in settings json
def get_dimension(self, instance):
if len(instance.text) < 25:
width = ((len(instance.text) / 2) * instance.font_size) * 1.1
else:
width = (len(instance.text) / 2) * instance.font_size
height = instance.font_size * 1.35
return width * self.settings["btn_scalar"], height * self.settings["btn_scalar"]
class Test(BoxLayout):
pass
class MainApp(App):
def build(self):
return Test()
if __name__ == "__main__":
MainApp().run()
还有我的.kv文件(是的,我知道缩进已关闭,仅在本文中如此):
<MultipleChoiceT@BoxLayout>:
orientation: 'vertical'
padding: 10
id: main_layout
bottom_label: bottom_label
canvas:
Color:
rgba: root.settings["canvas_color"]
Rectangle:
pos: self.x + 5, self.y + 5
size: self.width - 10, self.height - 10
Label:
id: question_label
font_size: root.settings["font_size"]
text: 'Sample question'
text_size: self.size[0] + 5, self.size[1]
valign: 'middle'
height: self.font_size * 1.33
size_hint: 1, None
color: root.settings["label_text_color"]
Label:
size_hint_y: None
height: 10
ToggleButton:
id: btn1
background_color: root.settings["button_bg_color"]
color: root.settings["button_text_color"]
font_size: root.settings["font_size"]
text: 'Option1'
group: 'MultChoice'
on_state: root.pressed(self)
size: root.get_dimension(self)
size_hint: None, None
halign: 'center'
valign: 'center'
Label:
size_hint_y: 0.1
ToggleButton:
id: btn2
background_color: root.settings["button_bg_color"]
color: root.settings["button_text_color"]
font_size: root.settings["font_size"]
text: '4785839409fjvojrvn eijofgj4389'
group: 'MultChoice'
on_state: root.pressed(self)
size: root.get_dimension(self)
size_hint: None, None
halign: 'center'
valign: 'center'
Label:
size_hint_y: 0.1
ToggleButton:
id: btn3
background_color: root.settings["button_bg_color"]
color: root.settings["button_text_color"]
font_size: root.settings["font_size"]
text: 'Option3'
group: 'MultChoice'
on_state: root.pressed(self)
size: root.get_dimension(self)
size_hint: None, None
halign: 'center'
valign: 'center'
Label:
size_hint_y: 0.1
ToggleButton:
id: btn4
background_color: root.settings["button_bg_color"]
font_size: root.settings["font_size"]
color: root.settings["button_text_color"]
text: 'A sample question type'
group: 'MultChoice'
on_state: root.pressed(self)
size: root.get_dimension(self)
size_hint: None, None
halign: 'center'
valign: 'center'
Label:
size_hint: 1, 0.5
GridLayout:
id: bottom_layout
cols: 4
size_hint_y: None
canvas:
Color:
rgba: root.settings["second_canvas_color"]
Rectangle:
pos: self.x, self.y
size: self.width, self.height
Button:
id: submit_btn
text: 'Press to submit'
on_press: root.submit()
font_size: root.settings["font_size"]
background_color: root.settings["second_btn_bg_color"]
color: root.settings["second_btn_txt_color"]
# for text wrapping
size: root.get_dimension(self)
text_size: self.size
halign: 'center'
valign: 'center'
Label:
id: bottom_label
text: 'answer'
font_size: root.settings["font_size"]
color: root.settings["second_lbl_txt_color"]
size_hint_x: main_layout.size_hint_x * 2
# for text wrapping
size: root.get_dimension(self)
text_size: self.size
halign: 'center'
valign: 'center'
Button:
id: next_btn
text: 'Next question'
font_size: root.settings["font_size"]
background_color: root.settings["second_btn_bg_color"]
color: root.settings["second_btn_txt_color"]
on_press: root.next_question()
# for text wrapping
size: self.texture_size
text_size: self.size
halign: 'center'
valign: 'center'
<Test@BoxLayout>:
orientation: 'horizontal'
MultipleChoiceT:
MultipleChoiceT:
无论何时运行MultipleChoice_text.py文件,我都会在MultipleChoice_text.kv的第11行收到一条错误消息,提示MultipleChoiceT对象没有属性“设置”,也许这只是我对属性的了解。但是,当我自己运行文件时,如果没有尝试在一个布局中包含多个MultipleChoiceT小部件,它就可以完美运行。
我当前的想法是settings属性是在实例级别创建的,并且仅在创建实例时创建。并且直到调用root.settings[whatever]
之后才创建实例。我不确定如何解决此问题。
我尝试将settings属性的创建移至不同的类中,以查看是否可以在调用它之前对其进行初始化,但是我对此并不走运。我还尝试将settings属性导入到kv文件中,但也没有执行任何操作。我最接近的尝试是独自运行MultipleChoiceT
小部件,并使它成为应用程序中唯一的东西。当代码如下时,该方法起作用:
class MainApp(App):
def build(self):
return MultipleChoiceT()
MainApp().run()
任何帮助或指点将不胜感激,因为这是为期2周的学校项目:) 如果需要,我可以发布完整的错误消息,但我发现唯一有用的是声明缺少属性的行。
作为旁注,PyQt5是python GUI开发的更好选择吗?我调查了一下,选择不走这条路,因为我没有找到支持可扩展应用程序的方法。而且,论坛帖子稀疏
答案 0 :(得分:0)
<MultipleChoiceT@BoxLayout>:
这是错误的语法,它会创建一个名为MultipleChoiceT
的新窗口小部件类,除了您在Python中定义的类之外,还 。您需要<MultipleChoiceT>
。