【问题标题】:Using jsonstore in Kivy在 Kivy 中使用 jsonstore
【发布时间】:2019-06-04 18:25:15
【问题描述】:

我创建了一个基于this question 的 GUI,同时尝试自学如何使用 jsonstore。我没有添加评论的声誉点,所以我在这里问我的问题。我想我已经有了基本的想法,但由于某种原因,我无法将数据保存到 json 文件中。我收到以下错误:

AttributeError: 'NoneType' object has no attribute 'text'

我已经尝试按照文档进行操作,但我看不到任何地方可以解释我做错了什么。

ma​​in.py

from kivy.storage.jsonstore import JsonStore
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty


Window.clearcolor = (0.02745098, 0.074509804, 0.121568627, 1)
Window.size = (2000, 900)

class TitleScreen(Screen):
    pass

class MainScreen(Screen):
    pass

class CreateProfile(Screen):
    First = ObjectProperty()
    Middle = ObjectProperty()
    Last = ObjectProperty()

    def __init__(self, **kwargs):
        super(CreateProfile, self).__init__(**kwargs)
        self.store = JsonStore("bco.json")
        self.load()

    def save(self):
        self.store.put('profile', first = self.label.text)
        self.store.put('profile', middle = self.label.text)
        self.store.put('profile', last = self.label.text)

    def load(self):
        try:
            self.Last.text = self.store.get('profile')['score']
        except KeyError:
            pass


class CreatePacket(Screen):
    pass

class ScreenManagement(ScreenManager):
    pass

presentation = Builder.load_file("customwidget.kv")

class CustomWidgetApp(App):
    def build(self):
        return presentation

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

customwidget.kv

#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import hex kivy.utils.get_color_from_hex
#: import FocusBehaviors kivy.uix.behaviors.focus

ScreenManagement:
    transition: FadeTransition()
    TitleScreen:
    MainScreen:
    CreateProfile:
    CreatePacket:

<MainLabel@Label>:
    font_size:50
    bold: True
    size_hint_x: 1
    size_hint_y: 1.85
    color: 0.396078431, 0.803921569, 0.807843137, 1
    font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'

<SubLabel@Label>:
    font_size: 35
    bold: True
    halign: "center"
    size_hint_x: 1
    size_hint_y: 1.5
    color: 0.396078431, 0.803921569, 0.807843137, 1
    font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'

<OtherLabel@Label>:
    font_size: 12
    bold: True
    color: 0.396078431, 0.803921569, 0.807843137, 1
    font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
    text_size: self.size

<Button@Button>:
    font_size: 20
    bold: True
    color: 0.396078431, 0.803921569, 0.807843137, 1
    font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
    background_color: 0.02745098, 0.074509804, 0.121568627, .01
    canvas.before:
        Color:
            rgba: 0.396078431, 0.803921569, 0.807843137, 1
        Line:
            width: 2
            rectangle: self.x, self.y, self.width, self.height
    on_press: self.background_color = (0.396078431, 0.803921569, 0.807843137, 1)
    on_release: self.background_color = (0.02745098, 0.074509804, 0.121568627, .01)

# TODO: Create a focus behavior to "Tab" between widgets
<TextInput@TextInput>:
    font_size: 12
    color: 0.396078431, 0.803921569, 0.807843137, 1
    font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
    padding_x: 10
    padding_y: 10
    focus_next: None
    focus_previous: None
    unfocus_on_touch: True
    background_color: 0.02745098, 0.074509804, 0.121568627, .01
    canvas.before:
        Color:
            rgba: 0.396078431, 0.803921569, 0.807843137, 1
        Line:
            width: 1
            rectangle: self.x, self.y, self.width, self.height

<TitleScreen>:
    id: "title"
    FloatLayout:
        MainLabel:
            text: "Easy Button"
            size_hint_x: 1
            size_hint_y: 1.25

        SubLabel:
            text: 'Test'
            size_hint_x: 1
            size_hint_y: 1
        Button:
            text: "Click Here To Continue"
            on_release: app.root.current = "main"
            size_hint: (.75, .15)
            pos_hint: {'x': .12, 'y': .2}

<MainScreen>:
    name: "main"
    MainLabel:
        text: "Home Page"
    BoxLayout:
        Button:
            on_release: app.root.current = "create_profile"
            text: "Create Profile"
            size_hint: (.5, .15)
        Button:
            on_release: app.root.current = "create_packet"
            text: "Create Packet"
            size_hint: (.5, .15)

<CreateProfile>:
    name: "create_profile"

    AnchorLayout:
        anchor_x: 'center'
        anchor_y: 'top'
        MainLabel:
            text: "Create Profile"
            size_hint: (1, .15)

    BoxLayout:
        size_hint: (.95, .2)
        pos_hint: {'x': 0, 'y': .85}
        spacing: 10
        padding: 10
        halign: "left"

        OtherLabel:
            text: "First"

        OtherLabel:
            text: "Middle"

        OtherLabel:
            text: "Last"

    BoxLayout:
        size_hint: (.95, .07)
        pos_hint: {'x': 0, 'y': .8}
        spacing: 20
        padding: 10
        halign: "right"
        text_size: self.size

        TextInput:
            id: 'First'


        TextInput:
            id: "Middle"


        TextInput:
            id: 'Last'    

    BoxLayout:

        Button:
            on_release: app.root.current = "main"
            text: "back Home"
            size_hint: (.5, .15)
        Button:
            on_release: root.save()
            text: "Save Profile"
            size_hint: (.5, .15)

<CreatePacket>:
    name: "create_packet"
    MainLabel:
        text: "Select Packet"
    FloatLayout:
        Button:
            on_release: app.root.current = "main"
            text: "back Home"
            size_hint: (1, .15)

【问题讨论】:

    标签: python python-3.x kivy jsonstore


    【解决方案1】:

    我找到了一种解决方法,它仍然允许我使用 TinyDB 将信息附加到 JSON 中。这是更新的代码:

    from kivy.app import App
    from kivy.storage.jsonstore import JsonStore
    from kivy.lang import Builder
    from kivy.uix.screenmanager import Screen, ScreenManager
    from kivy.core.window import Window
    from tinydb import TinyDB, Query
    from kivy.uix.listview import ListItemButton
    
    
    Window.clearcolor = (0.02745098, 0.074509804, 0.121568627, 1)
    Window.size = (2000, 900)
    
    db = TinyDB('bcodb.json')
    
    class ProfileListButton(ListItemButton):
        pass
    
    class TitleScreen(Screen):
        pass
    
    class MainScreen(Screen):
        pass
    
    class CreateProfile(Screen):
        def __init__(self, **kwargs):
            super(CreateProfile, self).__init__(**kwargs)
            self.store = JsonStore("bcodb.json")
    
        def save(self):
            db.insert({'first': self.first.text, 'middle': self.middle.text, 'last': self.last.text})
    
        def update(self):
            db.update({'first': self.first.text, 'middle': self.middle.text, 'last': self.last.text})
    
    class CreatePacket(Screen):
        pass
    
    class ScreenManagement(ScreenManager):
        pass
    
    
    presentation = Builder.load_file("customwidget2.kv")
    
    class CustomWidgetApp(App):
        def build(self):
            return presentation
    
    if __name__ == "__main__":
        CustomWidgetApp().run()
    

    使用我正在尝试开发的简单的类似数据库的程序很容易弄清楚。 .kv 文件也是一样的。

    【讨论】:

      【解决方案2】:

      您的代码有几个问题,但主要问题是您不了解如何将任何 .kv 小部件公开给 .py,最简单的方法之一是尝试使用 ObjectProperty 但该属性未链接对于小部件,为了简单起见,我更喜欢在 .kv 中进行创建。

      另一方面,我建议您避免滥用 try-except,因为它隐藏了错误,最好的办法是验证。

      另一个错误是您正在覆盖 .json 中配置文件的值,想法是将所有内容保存在一个中。

      综合以上,解决办法是:

      *.py

      from kivy.app import App
      from kivy.storage.jsonstore import JsonStore
      from kivy.lang import Builder
      from kivy.uix.screenmanager import Screen, ScreenManager
      from kivy.core.window import Window
      from kivy.clock import Clock
      
      
      Window.clearcolor = (0.02745098, 0.074509804, 0.121568627, 1)
      Window.size = (2000, 900)
      
      class TitleScreen(Screen):
          pass
      
      class MainScreen(Screen):
          pass
      
      class CreateProfile(Screen):
          def __init__(self, **kwargs):
              super(CreateProfile, self).__init__(**kwargs)
              self.store = JsonStore("bco.json")
              Clock.schedule_once(lambda *args: self.load())
      
          def save(self):
              self.store.put('profile', 
                  first = self.first.text,
                  middle = self.middle.text,
                  last = self.last.text)
      
          def load(self):
              if self.store.exists('profile'):
                  profile = self.store.get('profile')
                  v = [("first", self.first), ("middle", self.middle), ("last", self.last)]
                  for key, ti in v:
                      val = profile.get(key)
                      if val:
                          ti.text = val
      
      class CreatePacket(Screen):
          pass
      
      class ScreenManagement(ScreenManager):
          pass
      
      presentation = Builder.load_file("customwidget.kv")
      
      class CustomWidgetApp(App):
          def build(self):
              return presentation
      
      if __name__ == "__main__":
          CustomWidgetApp().run()
      

      *.kv

      #: import FadeTransition kivy.uix.screenmanager.FadeTransition
      #: import hex kivy.utils.get_color_from_hex
      #: import FocusBehaviors kivy.uix.behaviors.focus
      
      ScreenManagement:
          transition: FadeTransition()
          TitleScreen:
          MainScreen:
          CreateProfile:
          CreatePacket:
      
      <MainLabel@Label>:
          font_size:50
          bold: True
          size_hint_x: 1
          size_hint_y: 1.85
          color: 0.396078431, 0.803921569, 0.807843137, 1
          font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
      
      <SubLabel@Label>:
          font_size: 35
          bold: True
          halign: "center"
          size_hint_x: 1
          size_hint_y: 1.5
          color: 0.396078431, 0.803921569, 0.807843137, 1
          font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
      
      <OtherLabel@Label>:
          font_size: 12
          bold: True
          color: 0.396078431, 0.803921569, 0.807843137, 1
          font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
          text_size: self.size
      
      <Button@Button>:
          font_size: 20
          bold: True
          color: 0.396078431, 0.803921569, 0.807843137, 1
          font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
          background_color: 0.02745098, 0.074509804, 0.121568627, .01
          canvas.before:
              Color:
                  rgba: 0.396078431, 0.803921569, 0.807843137, 1
              Line:
                  width: 2
                  rectangle: self.x, self.y, self.width, self.height
          on_press: self.background_color = (0.396078431, 0.803921569, 0.807843137, 1)
          on_release: self.background_color = (0.02745098, 0.074509804, 0.121568627, .01)
      
      # TODO: Create a focus behavior to "Tab" between widgets
      <TextInput@TextInput>:
          font_size: 12
          color: 0.396078431, 0.803921569, 0.807843137, 1
          font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
          padding_x: 10
          padding_y: 10
          focus_next: None
          focus_previous: None
          unfocus_on_touch: True
          background_color: 0.02745098, 0.074509804, 0.121568627, .01
          canvas.before:
              Color:
                  rgba: 0.396078431, 0.803921569, 0.807843137, 1
              Line:
                  width: 1
                  rectangle: self.x, self.y, self.width, self.height
      
      <TitleScreen>:
          id: "title"
          FloatLayout:
              MainLabel:
                  text: "Easy Button"
                  size_hint_x: 1
                  size_hint_y: 1.25
      
              SubLabel:
                  text: 'Test'
                  size_hint_x: 1
                  size_hint_y: 1
              Button:
                  text: "Click Here To Continue"
                  on_release: app.root.current = "main"
                  size_hint: (.75, .15)
                  pos_hint: {'x': .12, 'y': .2}
      
      <MainScreen>:
          name: "main"
          MainLabel:
              text: "Home Page"
          BoxLayout:
              Button:
                  on_release: app.root.current = "create_profile"
                  text: "Create Profile"
                  size_hint: (.5, .15)
              Button:
                  on_release: app.root.current = "create_packet"
                  text: "Create Packet"
                  size_hint: (.5, .15)
      
      <CreateProfile>:
          name: "create_profile"
      
          first: first
          middle: middle
          last: last
      
          AnchorLayout:
              anchor_x: 'center'
              anchor_y: 'top'
              MainLabel:
                  text: "Create Profile"
                  size_hint: (1, .15)
      
          BoxLayout:
              size_hint: (.95, .2)
              pos_hint: {'x': 0, 'y': .85}
              spacing: 10
              padding: 10
              halign: "left"
      
              OtherLabel:
                  text: "First"
      
              OtherLabel:
                  text: "Middle"
      
              OtherLabel:
                  text: "Last"
          BoxLayout:
              size_hint: (.95, .07)
              pos_hint: {'x': 0, 'y': .8}
              spacing: 20
              padding: 10
              halign: "right"
              text_size: self.size
              TextInput:
                  id: first
              TextInput:
                  id: middle
              TextInput:
                  id: last    
      
          BoxLayout:
              Button:
                  on_release: app.root.current = "main"
                  text: "back Home"
                  size_hint: (.5, .15)
              Button:
                  on_release: root.save()
                  text: "Save Profile"
                  size_hint: (.5, .15)
      
      <CreatePacket>:
          name: "create_packet"
          MainLabel:
              text: "Select Packet"
          FloatLayout:
              Button:
                  on_release: app.root.current = "main"
                  text: "back Home"
                  size_hint: (1, .15)
      

      【讨论】:

      • 效果很好!谢谢!你能帮我弄清楚如何附加到 JSON 文件而不是写入吗?
      • @JarrenPoulsen append 的概念是获取已有的数据,添加新数据并再次保存,因此使用 get 和 put 可以得到该行为:d = self.store.get('profile') if not d: d = dict() d["first"] = "some value" self.store.put('profile', **d)
      • 请原谅我的无知......所以你给我附加到 json 文件的解决方案对我不起作用。我花了过去几个小时寻找解决方案,但您的方式似乎很独特。这可能是因为我不明白要为“某些价值”投入什么。我已经尝试对其进行硬编码(写入json,但没有附加)。我试过'self.first.text'没有改变。
      猜你喜欢
      • 2017-12-29
      • 2019-09-11
      • 2020-05-12
      • 2013-01-13
      • 2015-06-18
      • 2016-05-24
      • 2013-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多