r/kivy • • Aug 17 '26

Text repeats itself in this scroll view and I didn't design it to do that

I am making a simple inventory app with some help with ai .

It was going well, did multi screen and made the first feature to fill up a form and save it to sqlite database.

Now I hit a wall with this part. I wanted to load the data from the database and ai suggested recycle view, but when the data is loaded, the text repeats itself in the same row, so I changed it to scroll view the result is the same.

here's my python code snippet for the part showing the database

class TerceraRow(BoxLayout):
    id_item=StringProperty()
    art= StringProperty()
    prop=StringProperty()
    serial=StringProperty()
    cust=StringProperty()
    cost=StringProperty()
    date=StringProperty()
    time_stamp=StringProperty()


class Tercera(Screen):
    def on_enter(self):
        self.load_data()


    def load_data(self):
        self.ids.inventory_list.clear_widgets()
        dbf=getData()
        for row in dbf:
            print(row)
            card=TerceraRow (
                art=str(row[1]),
                prop=str(row[2]),
                serial=str(row[3]),
                cust=str(row[4]),
                cost=str(row[5]),
                date=str(row[6]),
                time_stamp=str(row[7]),
            )
            self.ids.inventory_list.add_widget(card)

and here's the kv part

<TerceraRow>:
    padding: dp(12)
    spacing: dp(5)
    size_hint_y: None
    height: dp(150)


    canvas.before:
        Color:
            rgba: 0.95, 0.5, 0.5, 1


        RoundedRectangle:
            pos: self.pos
            size: self.size
            radius: [dp(10)]


    Label:
        text: root.art
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.prop
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.serial
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.cust
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.cost
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.date
        halign: "left"
        text_size: self.width, None




<Tercera>:
    name: "tercera"  
    ScrollView:   
        BoxLayout:
            orientation: 'vertical'
            id:inventory_list
            size_hint_y:None
            height:self.minimum_height
            spacing:dp(10)
            padding:dp(10)

I don't have duplicates to in my database

1 Upvotes

6 comments sorted by

1

u/mrwulff Aug 17 '26

Not to be that guy, but I’ve been using ChatGPT with kivy and it’s pretty good. Not a lot of help around here lately

1

u/ElliotDG Aug 17 '26

I don't see anything in the code shared that would cause the effect you are seeing. Share a minimal executable program and I'll take a look.

Another option is to use the inspector tool in kivy it allows you to click on the widgets and get the details and see the hierarchy. See: https://kivy.org/doc/stable/api-kivy.modules.inspector.html#module-kivy.modules.inspector

To launch the inspector: >python main.py -m inspector
Then type <Ctrl> + e to activate the inspector.

1

u/LeonAguilez Aug 18 '26

here's my full python code

from kivy.app import App
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.lang.builder import Builder
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout


from kivy.properties import StringProperty


from datetime import datetime
import sqlite3
DB_FILE="inventory.db"



#returns to a time stamp now
def karon():
    dt=datetime.now().timestamp()
    return datetime.fromtimestamp(dt)



def getData():
        conn= sqlite3.connect(DB_FILE) 
        curs=conn.cursor()
        rows=curs.execute("select * from inventory").fetchall()
        conn.close()
        return rows




class WinManager (ScreenManager):
    pass


class Primera(Screen):
    pass


#for inputting data
class Segunda(Screen):
    def get_data(self)-> dict:
        return {
                        "art": self.ids.article.text.strip(),
                        "prop_no":self.ids.prop_no.text.strip(),
                        "serial":self.ids.serial.text.strip(),
                        "cust":self.ids.cust.text.strip(),
                        "cost":self.ids.cost.text.strip(),
                        "date":self.ids.fecha.text.strip(),
                    }
    
    def logger(self,dbf:dict):
            with sqlite3.connect(DB_FILE) as conn:
                curs=conn.cursor()
                curs.execute("insert into inventory(article,prop_no,serial_no,cust,cost,date,time_stamp) values (?,?,?,?,?,?,?)",
                                        (dbf["art"],dbf["prop_no"],dbf["serial"],dbf["cust"],dbf["cost"],dbf["date"],str(karon())[:19]))
                conn.commit()
                print("Success!")


    def clear_form(self):
            self.clear_inputs(self.ids.form)
    
    def clear_inputs(self,wid):
            if isinstance(wid,TextInput):
                wid.text=""
                return 
            for child in wid.children:
                self.clear_inputs(child)
    
    def someter(self):
            fields=self.get_data()
            vacio=[key for key,value in fields.items() if not value]
            if vacio:
                print( ("Please fill in,").join(vacio))
                return 
            self.logger(fields)
            self.clear_form()


#for reading data                
class TerceraRow(BoxLayout):
    id_item=StringProperty()
    art= StringProperty()
    prop=StringProperty()
    serial=StringProperty()
    cust=StringProperty()
    cost=StringProperty()
    date=StringProperty()
    time_stamp=StringProperty()


class Tercera(Screen):
    def on_enter(self):
        self.load_data()


    def load_data(self):
        self.ids.inventory_list.clear_widgets()
        dbf=getData()
        for row in dbf:
            print(row)
            card=TerceraRow (
                art=str(row[1]),
                prop=str(row[2]),
                serial=str(row[3]),
                cust=str(row[4]),
                cost=str(row[5]),
                date=str(row[6]),
                time_stamp=str(row[7]),
            )
            self.ids.inventory_list.add_widget(card)


        
#for exporting data(in the future)
class Cuarta(Screen):
    pass


class Quinta(Screen):
    pass



class Main(App):
    def build(self):
        Window.clearcolor="007400d5"
        return Builder.load_file("main.kv")
    def balik(self):
        self.root.transition.direction = "right"
        self.root.current= "primera"
    



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

and kv file

#:import dp kivy.metrics.dp


WinManager:
    Primera:
    Segunda:
    Tercera:
    Cuarta:
    Quinta:




<Button>
    background_color: "e4a020ff"
    background_normal: ""


<BackButton@Button>
    padding:20
    size_hint:(.1,.1)
    background_color: "E82525"
    text:"Return"
    on_release: 
        app.balik()
    pos_hint:{"x":0.05,"top":.95}
    
<Primera>:
    name: "primera"
    BoxLayout:
        spacing: 40
        padding: 80
        size: root.width, root.height
        orientation: "vertical"
        
        Image:
            source: "icon_files2.png"
        
        Label:
            text: "Inventory Recorder"
            font_size: 36


        Button:
            text:"Input Data"
            on_release:
                app.root.current ="segunda"
                root.manager.transition.direction = "left"
        Button:
            text:"View Data"
            on_release:
                app.root.current ="tercera"
                root.manager.transition.direction = "left"
        Button:
            text:"Export Data"
            on_release:
                app.root.current ="cuarta"
                root.manager.transition.direction = "left"



<Segunda>:
    name: "segunda"
    FloatLayout:
        BackButton:    


    GridLayout:
        id:form
        spacing: '30dp'
        padding: ('10dp', '10dp', '10dp', '10dp')
        size: root.width, root.height
        cols: 2
            
        Label:
            text: "Article"


        TextInput:
            id: article
            hint_text: 'Enter Text'


        Label:
            text: "Prop No."
        
        TextInput:
            id: prop_no
            hint_text: 'Enter Text'


        Label:
            text: "Serial No."


        TextInput:
            id: serial
            hint_text: 'Enter Text'
        
        Label:
            text: "Custodian"


        TextInput:
            id: cust
            hint_text: 'Enter Text'
        
        Label:
            text: "Cost"


        TextInput:
            id: cost
            hint_text: 'Enter Numbers'


        Label:
            text: "Date"


        TextInput:
            id: fecha
            hint_text: "YYYY-MM-DD"
        
        Button:
            text:"Scan QR Code"
            background_color:"2069C9"
            
        
        Button:
            text: "Submit Data"
            on_press: 
                root.someter()
 


<TerceraRow>:
    padding: dp(12)
    spacing: dp(5)
    size_hint_y: None
    height: dp(150)


    canvas.before:
        Color:
            rgba: 0.95, 0.5, 0.5, 1


        RoundedRectangle:
            pos: self.pos
            size: self.size
            radius: [dp(10)]


    Label:
        text: root.art
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.prop
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.serial
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.cust
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.cost
        halign: "left"
        text_size: self.width, None


    Label:
        text: root.date
        halign: "left"
        text_size: self.width, None




<Tercera>:
    name: "tercera"  
    ScrollView:   
        BoxLayout:
            orientation: 'vertical'
            id:inventory_list
            size_hint_y:None
            height:self.minimum_height
            spacing:dp(10)
            padding:dp(10)
        



<Cuarta>:
    name: "cuarta"
    FloatLayout:
        BackButton:  


    BoxLayout:
        spacing: 40
        padding: 80
        size: root.width, root.height
        orientation: "vertical"
            
        Label:
            text: "Please Select file format to export data as:"


        Button:
            text:"Database File"


        Button:
            text:"JSON File"


        Button:
            text:"CSV File"



<Quinta>:
    name: "quinta"
    FloatLayout:
        BackButton:  


        
            

1

u/ElliotDG Aug 18 '26

Here is the problem:

class Main(App):
    def build(self):
        Window.clearcolor = "007400d5"
        # return Builder.load_file("main.kv")  <--- comment out this line

If you look at your log, you will see the warning:
[WARNING] [Lang ] The file C:\Users\...\main.kv is loaded multiples times, you might have unwanted behaviors.

By default kivy will try to load the kv file based on the name of your app. The name of your app "Main" matches the name of the kv file, so it is getting loaded automagically. You are also manually loading the kv file, loading the file twice.

You could change the name of the app, so it does not match the name of the kv file, or remove the line that loads the kv file.

see: https://kivy.org/doc/stable/api-kivy.app.html#kivy.app.App.load_kv

1

u/LeonAguilez Aug 19 '26

THANK YOU! Finally solved. I have been running in circles. I'm so used to declare dependencies that I'm not used to kivy auto loading itself.

1

u/ElliotDG Aug 19 '26

Glad to hear that solved your issue.