Search code examples
pythonkivykivy-language

Problem to show image according to id in .kv Kivy


I have the following script in python kivy that counts how many records there are in a table in the database and according to the total it shows an image n[] times. If the total record is 4 and I do a print[numero] it prints 0,1,2,3, it's ok. But when I want to show an image "weight.png" 4 times it doesn't show it and gives me an error: AttributeError: 'super' object has no attribute '__getattr__'

Here code:

rollo.py

from email.mime import image
from itertools import count
from logging import root
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.config import Config
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
import time
import serial
import psycopg2
from datetime import datetime, timezone
from kivy.uix.image import Image
from kivy.properties import StringProperty
from inicio import Inicio


class Rollo(Screen):
    def __init__(self, **kwargs):
        super(Rollo, self).__init__(**kwargs)
        print('inicie')
        #connect DB
        con = psycopg2.connect(
            host = "localhost",
            database = "appsenior",
            user = "postgres",
            password = "qq")             
        cur = con.cursor()
            #contar cantidad de rollos pesados
        consulta = "SELECT count(*) pesos FROM peso_materia WHERE id_parada=100"
        cur.execute(consulta)
        rows = cur.fetchone()
        numero = 0
        #example rows[0] = 4  loop con 4
        while numero < rows[0]:
            #It should show me the image peso.png in the corresponding image id
            self.ids.carga[numero] =  StringProperty('peso.png')
            numero = numero + 1
            

kivy.require('2.0.0')
Config.set('graphics', 'resizable', True)
Builder.load_file('rollo.kv')

class Root(GridLayout):
    pass

class Main(App):
    def build(self):
        return Root()
    
if __name__ == '__main__':
    Main().run()

rollo.kv

<Rollo@Screen>
    name:'rollo'
    canvas:
        Color:
            rgba: .9,.9,.9,1
        Rectangle: 
            size: self.size    
    BoxLayout:
        orientation: 'vertical' #Arrange four child objects vertically
        BoxLayout:      
            size_hint_y: 0.2 #Vertical width 10%Occupy
            Button: #Button to change the theme
                size_hint_x: 0.3 #Width 30%Occupy
                text: 'Peso de Rollos'
                background_color: 0.9,0.1,0.9, 1
            Button: #Show theme
                size_hint_x: 0.3 #Width 70%Occupy
                text: 'Peso de Bultos'
                background_color: 0.1,0.1,0.1, 1
            Button: #Show theme
                size_hint_x: 0.3 #Width 70%Occupy
                text: 'Peso de Canutos'
                background_color: 0.1,0.1,0.1, 1                

        BoxLayout: #labels
            size_hint_y: 0.1
            canvas.before:
                Color:
                    rgba: 4, .4, 0, 1
                Rectangle:
                    pos: self.pos
                    size: self.size
                    
            Label:
                text: '#1'
            Label:
                text: '#2'
            Label:
                text: '#3'
            Label:
                text: '#4'
            Label:
                text: '#5'
            Label:
                text: '#6'
            Label:
                text: '#7'
            Label:
                text: '#8'
            Label:
                text: '#9'
            Label:
                text: '#10'
            Label:
                text: '#11'
            Label:
                text: '#12'            

        BoxLayout:
            size_hint_y: 0.2
            id:boxcargan                                          

            Image:
                id: carga0

            Image:
                id: carga1
                source: ''
 
            Image:
                id: carga2
                source: ''
            
            Image:
                id: carga3            
                source: ''

            Image:
                id: carga4            
                source: ''
 
            Image:
                id: carga5            
                source: ''

            Image:
                id: carga6            
                source: ''

            Image:
                id: carga7            
                source: ''
 
            Image:
                id: carga8            
                source: ''

            Image:
                id: carga9            
                source: ''

            Image:
                id: carga10            
                source: ''
 
            Image:
                id: carga11            
                source: ''                                        
 
        BoxLayout:
            Label:
                id: lblcorrecto
                text:''
                size_hint_y: 0.7
                color: 237 , 112 , 64 , 1
                font_size: 20

        BoxLayout:
            Label: #Canvas part (provisional)
                text: 'POR FAVOR, COLOQUE EL ROLLO A  PESAR'
                size_hint_y: 0.9
                color: 1 , 0 , 0 , 1
                size_hint_x: 0.9

    BoxLayout:
        size_hint_y: 0.1 #Vertical width 10%Occupy
        Button: #Undo button
            text: 'PESAR'
            on_press: root.extraer_peso()
        Button: #All erase button
            text: 'FINALIZAR'

Solution

  • You can't access ids that way, and you should change the source property of the Image instead of using a StringProperty. Try changing:

    self.ids.carga[numero] =  StringProperty('peso.png')
    

    to:

    self.ids["carga" + str(numero)].source = 'peso.png'
    

    But the ids will not be available in the __init__() method (they will not have been set yet). So you just need to delay using them slightly, which you can do with Clock.schedule_once(). Here is a modified version of your Rollo class that does it:

    class Rollo(Screen):
        def __init__(self, **kwargs):
            super(Rollo, self).__init__(**kwargs)
            print('inicie')
            Clock.schedule_once(self.setup)
    
        def setup(self, dt):
            # connect DB
            con = psycopg2.connect(
                host="localhost",
                database="appsenior",
                user="postgres",
                password="qq")
            cur = con.cursor()
            # contar cantidad de rollos pesados
            consulta = "SELECT count(*) pesos FROM peso_materia WHERE id_parada=100"
            cur.execute(consulta)
            rows = cur.fetchone()
            numero = 0
            # example rows[0] = 4  loop con 4
            while numero < rows[0]:
                # It should show me the image peso.png in the corresponding image id
                self.ids['carga' + str(numero)].source = 'peso.png'
                numero = numero + 1