pythonkivy

Python/Kivy AttributeError: 'super' object has no attribute '__getattr__'


I am having trouble to reload picture or profile of user. The widget that I want to reload is included in the ScreenOne, I create the function for reloading in this class and try to call it from the function in the class Change.

Here is my main.py:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
import readtable
import Readpictureadress
import sizetable
import Match
import nbofpictures
import random
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.properties import ObjectProperty, NumericProperty, StringProperty
import kivy


size = sizetable.main()
Iduserp = (random.randint(1, size))
imagenb=0
picadress= Readpictureadress.main(Iduserp, 0)

class Manager(ScreenManager):

    screen_one = ObjectProperty(None)
    screen_two = ObjectProperty(None)

class ScreenTwo(Screen):
    print('screentwo')
    pass

class ScreenOne(Screen):
    img = StringProperty()
    global picadress
    global Iduserp


    def __init__(self, **kwargs):
        super(ScreenOne, self).__init__(**kwargs)
        self.img = picadress


    def displayScreenThenLeave(self):
        print('Displayscreen')

        self.changeScreen()

    def changeScreen(self):
        print('changescreen')

        if self.Manager.current == 'screen1':
            self.Manager.current = 'screen2'
        else:
            self.Manager.current = 'screen1'
    pass

    def reloadprofile(self):
        self.img = picadress
        self.ids.a1.reload()


class Change():
    global Iduserp
    global imagenb
    global picadress

    def changeuser(self):

        size = sizetable.main()
        Iduserp = (random.randint(1, size))
        app = App.get_running_app()
        app.screenone.reloadprofile()

    def changepicturenb (self):

        nbofpic = nbofpictures.main(Iduserp)
        if imagenb < nbofpic:
            imagenb += 1
        else:
            imagenb = 0
        app = App.get_running_app()
        app.screenone.reloadprofile()

class ScreensApp(App):
    print('ScreensApp')
    screenone=ScreenOne()
    varChange= Change()
    def build(self):
        m = Manager(transition=NoTransition())
        return m

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

My kivy file:

#:kivy 1.8.0

<ScreenTwo>:

<ScreenOne>:
    stuff_a: a1
    BoxLayout:
        orientation: 'vertical'
        rows: 4
        BoxLayout:
            orientation: 'vertical'
            rows: 1
            size_hint_y: 0.8
            AsyncImage
                id:a1
                source:root.img
                on_touch_down: app.varChange.changepicturenb()

        BoxLayout:
            padding: 10,10,10,0
            spacing: 10
            size_hint: 1,0.3
            orientation: "horizontal"
            Button:
                text: "Clear"
                on_touch_down: app.varChange.changeuser()
            Button:
                text: "Remove"
            Button:
                text: "Group"
            Button:
                text: "Color"
            Button:
                text: "Gestures"


<Manager>:
    id: screen_manager

    screen_one: screen_one
    screen_two: screen_two

    ScreenOne:
        id: screen_one
        name: "screen1"
        manager: screen_manager

    ScreenTwo:
        id: screen_two
        name: "screen2"
        manager: screen_manager

and my error file:

> File "main7.py", line 105, in changeuser
>      app.screenone.reloadprofile()    File "main7.py", line 60, in reloadprofile
>      self.ids.a1.reload()    File "kivy\properties.pyx", line 839, in kivy.properties.ObservableDict.__getattr__ (kivy\properties.c:12654) 
> AttributeError: 'super' object has no attribute '__getattr__'

Solution

  • You have several problems. First, change your ScreensApp

    class ScreensApp(App):
        
        def build(self):
            self.varChange = Change()
            self.m = Manager(transition=NoTransition())
            return self.m
    

    Note that your creation of a ScreenOne is eliminated, because that is created by your <Manager> rule in the kv file. The other statements are moved into the build method and saved as instance variables, since you need them elsewhere. This also allows your reference to app.varChange in your kv file to work.

    Also, you need to modify your Change class:

    class Change():
        global Iduserp
        global imagenb
        global picadress
    
        def changeuser(self):
    
            size = sizetable.main()
            Iduserp = (random.randint(1, size))
            app = App.get_running_app()
            app.m.screen_one.reloadprofile()
    
        def changepicturenb (self):
    
            nbofpic = nbofpictures.main(Iduserp)
            if imagenb < nbofpic:
                imagenb += 1
            else:
                imagenb = 0
            app = App.get_running_app()
            app.m.screen_one.reloadprofile()
    

    The reference to ScreenOne is saved in your <Manager> rule in the kv file as screen_one, so to access it you can go through the app, to the m (Manager) reference that was saved in the build method, and then to the screen_one property that was also defined in the <Manager> rule. I think that might fix your problem, but I can't be positive since I had to make changes to the example to get it to the "problem".