Python / kivy-TypeError:“ kivy.properties.ObjectProperty”对象不可迭代

时间:2019-06-20 17:44:16

标签: python kivy kivy-language

所以我一直在为我的项目制作一个骰子滚轴:地牢大师的助手帮助我DM,但现在让我们谈谈我的问题。

当我按下按钮RollDice时,它应该接受两个文本输入(骰子的类型和数量)并掷骰子,然后现在在控制台中打印骰子的数量和类型以及结果。但是,这会使程序崩溃。

这是相关的python代码(如果需要,可以显示更多):

class DiceRoller(Screen):

    def rolldice(self):
        self.diceNumber = ObjectProperty()
        self.diceType = ObjectProperty()


        print(F"{self.diceNumber}D{self.diceType}")


        for x in self.diceNumber:
            x = x + 1

            ActualDie = random.randint(1, self.diceType)
            Total = Total + ActualDie

            print(Total)

这是调用上面函数的按钮:

Button:
    id: RollDice
    text: "Roll dice"
    pos_hint: {"top":0.3,"x":0}
    size_hint: 0.4, 0.2
    background_color: 0,0,0,0.1
    color: 0,0,0,1
        on_release:
            root.rolldice()

正如我所说并表明应该发生的那样,它应该打印例如6D6,然后再打印这些骰子卷的总数。但是,这是发生了什么(错误代码):

enter image description here

该值由同一屏幕上的两个文本输入框设置:kv文件中的链接。

Screen - ObjectProperty links to TextInput

2 个答案:

答案 0 :(得分:0)

您使用的属性错误,必须在类级别声明它们:

class DiceRoller(Screen):
    diceNumber = ObjectProperty()
    diceType = ObjectProperty()

    def rolldice(self):
        print(F"{self.diceNumber}D{self.diceType}")
        # etc.

您还需要以实际方式访问它们之前,将它们设置为实际值,但我认为您未显示的代码已涵盖了它们。

答案 1 :(得分:0)

问题-ObjectProperty @方法级别

参考您提供的原始代码,即在方法级别声明的ObjectProperty

根本原因

原因是,当您将TextInput小部件链接到kv文件中的属性时,Kivy将在关联的类/小部件中查找那些属性。如果班级/小部件没有给定名称的属性,则会自动创建一个ObjectProperty并将其添加到班级/小部件。

当应用重新初始化方法ObjectPropertyrolldice()类型的两个自动创建的类属性,并分配了默认值None时,链接断开。

解决方案

  • 引用text对象的TextInput属性,并将字符串转换为整数int(self.diceNumber.text)int(self.diceType.text)
  • range()函数添加到for循环中
  • 在课程级别声明ObjectProperty(这是可选的)

摘要-示例

class DiceRoller(Screen):
    diceNumber = ObjectProperty(None)
    diceType = ObjectProperty(None)

    def rolldice(self):
        Total = 0    # initialize Total
        print(F"{self.diceNumber.text}, D{self.diceType.text}")

        for x in range(int(self.diceNumber.text)):

            ActualDie = random.randint(1, int(self.diceType.text))
            Total += ActualDie

        print(Total)

示例

以下示例说明Kivy自动创建了diceNumber类型的两个类属性diceTypeObjectProperty

main.py

import random
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

Builder.load_string("""
<CustomLabel@Label>:    # dynamic class
    color: 0, 0, 0,1    # black color text
    text_size: self.size
    halign: 'left'
    valign: 'middle'

<DiceRoller>:
    diceNumber: diceNumber
    diceType: diceType

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

    BoxLayout:
        orientation: 'vertical'

        GridLayout:
            cols: 2
            row_force_default: True
            row_default_height: 40

            CustomLabel:
                text: 'How many sides do you want your dice to have (6 for D6, 20 for D20, etc)?'
            TextInput:
                id: diceNumber
                size_hint_x: None
                width: 100

            CustomLabel:
                text: 'How many dice do you want to roll?'
            TextInput:
                id: diceType
                size_hint_x: None
                width: 100

        Button:
            id: RollDice
            text: "Roll dice"
            pos_hint: {"top":0.3,"x":0}
            size_hint: 0.4, 0.2
            background_color: 0,0,0,0.1
            color: 0,0,0,1
            on_release:
                root.rolldice()
""")


class DiceRoller(Screen):

    def rolldice(self):
        Total = 0
        print(F"{self.diceNumber.text}, D{self.diceType.text}")

        for x in range(int(self.diceNumber.text)):
            # x = x + 1

            ActualDie = random.randint(1, int(self.diceType.text))
            Total += ActualDie

        print(Total)


class TestApp(App):

    def build(self):
        return DiceRoller()


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