Python Forum
kivy binding issue
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
kivy binding issue
#1
Can you pass arguments in the kivy bind operation? See below where i am experimenting with calling a function to build a input screen and add it to a tabbed header. Also on the bind operation I try to pass the text input widget so i can also clear it's text in the on_pressed event. The issue is the on_pressed event is called as the code is executed adding empty data to my table without the btnAccept being pressed.
Also, if i did not post code correctly let me know-thanks

con=sqlite3.connect('bovine.db');
c=con.cursor();
#c.execute(""" CREATE TABLE cattleData
#           (tagNo integer,
#            Loc text,
#            sex text,
#            type text)
#           """)
#c.execute(""" CREATE TABLE locations
#           (Hermas text,
#            Tobaco Barn text,
#            Chambers text,
#            New Barn)
#           """)

locList=["Hermas","Tobbaco Barn","New Barn","Chambers"]
opList=["Location","Add","Edit"]

class myTabbedPanel(TabbedPanel):
    def __init__(self):
        super(myTabbedPanel, self).__init__()
        self.do_default_tab=False
        for i in opList:
            myTPHM=TabbedPanelHeader()
            myTPHM.text=str(i)
            self.add_widget(myTPHM)
            if str(i)=='Location':
                myTPLoc=TabbedPanel()
                myTPLoc.do_default_tab=False
                myTPHM.content=myTPLoc
                for j in locList:
                     myTPHL=TabbedPanelHeader()
                     myTPHL.text=str(j)
                     myTPLoc.add_widget(myTPHL)
                     
            if str(i)=='Add':
                myTPHM.content=myTabbedPanel.enterScreen()
                
    def enterScreen():    
        stkEnter=StackLayout(orientation='lr-tb',spacing=4)
        lbl1=Label(text='Tag No',size_hint=(.1,.04))
        lbl2=Label(text='Location',size_hint=(.1,.04))
        lbl3=Label(text='Sex',size_hint=(.1,.04))
        lbl4=Label(text='type',size_hint=(.1,.04))
        txtTag=TextInput(text='',size_hint=(.1,.06))
        txtLoc=TextInput(text='',size_hint=(.1,.06))
        txtSex=TextInput(text='',size_hint=(.1,.06))
        txtType=TextInput(text='',size_hint=(.1,.06))
        btnAccept=Button(text='add',size_hint=(.1,.04))
        stkEnter.add_widget(lbl1)
        stkEnter.add_widget(txtTag)
        stkEnter.add_widget(lbl2)
        stkEnter.add_widget(txtLoc)
        stkEnter.add_widget(lbl3)
        stkEnter.add_widget(txtSex)
        stkEnter.add_widget(lbl4)
        stkEnter.add_widget(txtType)
        stkEnter.add_widget(btnAccept)

        btnAccept.bind(on_press=pressed(txtTag,txtLoc,txtSex,txtType)) # **** Here ****
        
        return stkEnter

def pressed(txtTag,txtLoc,txtSex,txtType):
    c.execute("INSERT INTO cattleData VALUES(?,?,?,?)",(txtTag.text,txtLoc.text,txtSex.text,txtType.text))
    con.commit()
    txtTag.text=''
    txtLoc.text=''
    txtSex.text=''
    txtType.text=''
Yoriz write Nov-05-2021, 03:50 PM:
Please post all code, output and errors (in their entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Reply
#2
Keep a reference to the TextInput's as attributes on the MyTabbedPanel class,
Bind the button event to a method on the MyTabbedPanel class,
Have that method call the pressed function and pass in the TextInput values.
Do the clearing of the TextInput's in the button event method after calling the pressed function rather than in the function.
Reply
#3
Attempted to make changes as recommended. Additional feedback where i went wrong is appreciated. new error-Line 73 seems to say i am not adding a widget but in the debug console it indicates myTabbedPanel.lbl1 is a button widget-?
Also check my feeble attempt to make the changes previously recommended.
Thanks

Error:
Exception has occurred: TypeError (note: full exception trace is shown but execution is paused at: build) add_widget() missing 1 required positional argument: 'widget' File "/home/mark/Python Environments/FirstEnvProject/ClassTest5.py", line 73, in enterScreen myTabbedPanel.stkEnter.add_widget(myTabbedPanel.lbl1) File "/home/mark/Python Environments/FirstEnvProject/ClassTest5.py", line 60, in __init__ myTPHM.content=myTabbedPanel.enterScreen() File "/home/mark/Python Environments/FirstEnvProject/ClassTest5.py", line 122, in build (Current frame) return myTabbedPanel() File "/home/mark/Python Environments/FirstEnvProject/ClassTest5.py", line 126, in <module> CreateApp().run()
import kivy
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanelHeader
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
import sqlite3  



con=sqlite3.connect('bovine.db');
c=con.cursor();
#c.execute(""" CREATE TABLE cattleData
#           (tagNo integer,
#            Loc text,
#            sex text,
#            type text)
#           """)
#c.execute(""" CREATE TABLE locations
#           (Hermas text,
#            Tobaco Barn text,
#            Chambers text,
#            New Barn)
#           """)

locList=["Hermas","Tobbaco Barn","New Barn","Chambers"]
opList=["Location","Add","Edit"]

class myTabbedPanel(TabbedPanel):
    stkEnter=StackLayout
    lbl1=Label
    lbl2=Label
    lbl3=Label
    lbl4=Label
    txtTag=TextInput
    txtLoc=TextInput
    txtSex=TextInput
    txtType=TextInput
    btnAccept=Button
    
    def __init__(self):
        super(myTabbedPanel, self).__init__()
        self.do_default_tab=False
        for i in opList:
            myTPHM=TabbedPanelHeader()
            myTPHM.text=str(i)
            self.add_widget(myTPHM)
            if str(i)=='Location':
                myTPLoc=TabbedPanel()
                myTPLoc.do_default_tab=False
                myTPHM.content=myTPLoc
                for j in locList:
                     myTPHL=TabbedPanelHeader()
                     myTPHL.text=str(j)
                     myTPLoc.add_widget(myTPHL)
                     
            if str(i)=='Add':
                myTPHM.content=myTabbedPanel.enterScreen()
                
    def enterScreen():    
        myTabbedPanel.stkEnter(orientation='lr-tb',spacing=4)
        myTabbedPanel.lbl1(text='Tag No',size_hint=(.1,.04))
        myTabbedPanel.lbl2(text='Location',size_hint=(.1,.04))
        myTabbedPanel.lbl3(text='Sex',size_hint=(.1,.04))
        myTabbedPanel.lbl4(text='type',size_hint=(.1,.04))
        myTabbedPanel.txtTag(text='',size_hint=(.1,.06))
        myTabbedPanel.txtLoc(text='',size_hint=(.1,.06))
        myTabbedPanel.txtSex(text='',size_hint=(.1,.06))
        myTabbedPanel.txtType(text='',size_hint=(.1,.06))
        myTabbedPanel.btnAccept(text='add',size_hint=(.1,.04))
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.lbl1)
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.txtTag)
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.lbl2)
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.txtLoc)
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.lbl3)
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.txtSex)
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.lbl4)
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.txtType)
        myTabbedPanel.stkEnter.add_widget(myTabbedPanel.btnAccept)

        myTabbedPanel.btnAcceptBind(myTabbedPanel.btnAccept)

        return myTabbedPanel.stkEnter

    def btnAcceptBind(btnAccept):
        btnAccept.bind(on_press=pressed)
        myTabbedPanel.enterScreen.txtTag.text=''
        myTabbedPanel.enterScreen.txtLoc.text=''
        myTabbedPanel.enterScreen.txtSex.text=''
        myTabbedPanel.enterScreen.txtType.text=''

def pressed(txtTag,txtLoc,txtSex,txtType):
    c.execute("INSERT INTO cattleData VALUES(?,?,?,?)",(txtTag.text,txtLoc.text,txtSex.text,txtType.text))
    con.commit()

class modBtn(Button):
    def __init__(self,tagNo,sex):
        super(modBtn, self).__init__()
        self.tagNo=tagNo
        self.sex=sex

        self.text=str(tagNo)
        self.size_hint=(.06,.06)
        self.color=(1,0,0,1)
        self.background_color=(0,1,.2,1)

        self.bind(on_press=btnPress)    
    
def btnPress(instance):
    print (instance.text,instance.color,instance.sex)

#class createHdr():
#    def bld(self,Text):
#        hdr=TabbedPanelHeader()
#        hdr.text= Text
#        return hdr

class CreateApp(App):
    def build(self):
        return myTabbedPanel()
    

if __name__ == '__main__':
    CreateApp().run()
Reply
#4
You need to learn how to use classes properly
methods should have self as the first parameter
attributes are added by using self.
you should also try and follow pep8 conventions

The following doesn't solve all your issues but is a rough idea of what you are looking for.
class MyDataBase:
    def __init__(self, db_path):
        self.db_path = db_path
        self.con = None
        self.cur = None

    def connect(self):
        self.con = sqlite3.connect(self.db_path)
        self.cur = self.con.cursor()

    def insert_cattledata(self, tag, loc, sex, type_):
        self.cur.execute(
            "INSERT INTO cattleData VALUES(?,?,?,?)", (tag, loc, sex, type_)
        )
        self.con.commit()


class MyTabbedPanel(TabbedPanel):
    def __init__(self, data_base):
        ...
        self.db = data_base
        ...

    def enter_screen(self):
        ...
        self.txtTag = TextInput(text="", size_hint=(0.1, 0.06))
        self.txtLoc = TextInput(text="", size_hint=(0.1, 0.06))
        self.txtSex = TextInput(text="", size_hint=(0.1, 0.06))
        self.txtType = TextInput(text="", size_hint=(0.1, 0.06))
        ...
        stkEnter.add_widget(self.txtTag)
        stkEnter.add_widget(self.txtLoc)
        stkEnter.add_widget(self.txtSex)
        stkEnter.add_widget(self.txtType)
        ...
        btnAccept.bind(on_press=self.on_button)
        ...

    def on_button(self):  # i assume a kivy button event passes no attributes?
        self.db.insert_cattledata(
            self.txtTag.text, self.txtLoc.text, self.txtSex.text, self.txtType.text
        )
        self.txtTag.text = ""
        self.txtLoc.text = ""
        self.txtSex.text = ""
        self.txtType.text = ""


def main():
    my_db = MyDataBase("bovine.db")
    my_db.connect()
    MyTabbedPanel(my_db)


if __name__ == "__main__":
    main()
Reply
#5
Thanks for the advice- you are correct- i need to learn how to use classes properly. And i learned from you that not just the __init__ method needs to utilize -self.
Question???
My understanding of classes is that they are a blue print that define how to do things and information associated with how to do things. And that this blueprint can be used to create endless number of objects. Having lived in the sequential functional world for so long i struggle understanding what is the utility of creating a Class if i am only going to create one object?
Also, does self allow me to access any attribute in any method within the same class?
Thanks
Reply
#6
Classes have the advantage of structuring your code into collections of associated data and methods that make use of that data even if you only make one instance.
Yes, any attribute pre-pended with self can be accessed in other methods of the class instance.
Reply
#7
After attempting to model after above suggestions , the MyDataBase class seems to work well, however; the error below of not recognizing myTPHM has me stumped as the deBug console agrees it is a TabbedPanelHeader widget.

Also can you clarify the need for the __init__ in the MyApp class?
I understand I have to Run the sub-classed App of Kivy and is it OK to add the the data_base and TabbedPannel as arguments in the __init__ method?

Error:
Exception has occurred: TypeError add_widget() missing 1 required positional argument: 'widget' File "/home/mark/Python Environments/FirstEnvProject/ClassTest6.py", line 52, in __init__ self.root_widget.add_widget(self.myTPHM) File "/home/mark/Python Environments/FirstEnvProject/ClassTest6.py", line 103, in main MyApp(my_db,TabbedPanel).run() File "/home/mark/Python Environments/FirstEnvProject/ClassTest6.py", line 107, in <module> main()
from sqlite3 import dbapi2
import kivy
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanelHeader
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
import sqlite3

#con=sqlite3.connect('bovine.db');
#c=con.cursor();
#c.execute(""" CREATE TABLE cattleData
#           (tagNo integer,
#            Loc text,
#            sex text,
#            type text)
#           """)
#c.execute(""" CREATE TABLE locations
#           (Hermas text,
#            Tobaco Barn text,
#            Chambers text,
#            New Barn)
#           """)

locList=["Hermas","Tobbaco Barn","New Barn","Chambers"]
opList=["Location","Add","Edit"]
class MyDataBase:
    def __init__(self,db_path):
        self.db_path=db_path

    def connect(self):
        self.con=sqlite3.connect(self.db_path)
        self.c=self.con.cursor()

    def insert_cattledata(self,tag,loc,sex,type_):
        self.cur.execute("INSERT INTO cattleData VALUES(?,?,?,?)",(tag,loc,sex,type_))
        self.con.commit()


class MyApp(App):
    def __init__(self,data_base,TabbedPanel):
        self.db=data_base
        self.root_widget=TabbedPanel
        self.root_widget.do_default_tab=False
    

        for i in opList:
            myTPHM=TabbedPanelHeader()
            myTPHM.text=str(i)
            self.root_widget.add_widget(myTPHM)
            if str(i)=='Location':
                myTPLoc=TabbedPanel()
                myTPLoc.do_default_tab=False
                self.myTPHM.content=myTPLoc
                for j in locList:
                     myTPHL=TabbedPanelHeader()
                     myTPHL.text=str(j)
                     myTPLoc.add_widget(myTPHL)
                     
            if str(i)=='Add':
                myTPHM.content=self.enterScreen()
        
        return self.root_widget

    def enterScreen(self):    
        stkEnter=StackLayout(orientation='lr-tb',spacing=4)
        lbl1=Label(text='Tag No',size_hint=(.1,.04))
        lbl2=Label(text='Location',size_hint=(.1,.04))
        lbl3=Label(text='Sex',size_hint=(.1,.04))
        lbl4=Label(text='type',size_hint=(.1,.04))
        self.txtTag=TextInput(text='',size_hint=(.1,.06))
        self.txtLoc=TextInput(text='',size_hint=(.1,.06))
        self.txtSex=TextInput(text='',size_hint=(.1,.06))
        self.txtType=TextInput(text='',size_hint=(.1,.06))
        btnAccept=Button(text='add',size_hint=(.1,.04))
        stkEnter.add_widget(lbl1)
        stkEnter.add_widget(self.txtTag)
        stkEnter.add_widget(lbl2)
        stkEnter.add_widget(self.txtLoc)
        stkEnter.add_widget(lbl3)
        stkEnter.add_widget(self.txtSex)
        stkEnter.add_widget(lbl4)
        stkEnter.add_widget(self.txtType)
        stkEnter.add_widget(btnAccept)

        btnAccept.bind(on_press=self.on_button)
        return stkEnter

    def on_button(self):
        self.db.insert_cattledata(self.txtTag.text,self.txtLoc.text,self.txtSex.text,self.txtType.text)
        self.txtTag.text=''
        self.txtLoc.text=''
        self.txtSex.text=''
        self.txtType.text=''


def main():
    my_db=MyDataBase('bovine.db')
    my_db.connect()
    MyApp(my_db,TabbedPanel).run()
    

if __name__ == '__main__':
    main()
Reply
#8
I don't understand what you are trying to do with TabbedPanel but you have just passed in a class of TabbedPanel and not made an actual instance by calling using () ie TabbedPanel()

I don't use kivy so you will have to follow a tutorial to see how kivy code is supposed to be structured.
Reply
#9
Thanks
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Key Binding scope angus1964 1 1,219 Jun-30-2022, 08:17 PM
Last Post: deanhystad
  [Tkinter] binding versus disable DPaul 6 6,791 May-05-2021, 05:17 PM
Last Post: DPaul
  [Tkinter] Binding Entry box to <Button-3> created in for loop iconit 5 4,986 Apr-22-2020, 05:47 AM
Last Post: iconit
  TkInter Binding Buttons ifigazsi 5 4,436 Apr-06-2020, 08:30 AM
Last Post: ifigazsi
  Making text clickable with binding DT2000 10 5,165 Apr-02-2020, 10:11 PM
Last Post: DT2000
  [Tkinter] Setting Binding to Entry created with a loop? p_hobbs 1 2,085 Nov-25-2019, 10:29 AM
Last Post: Larz60+
  Binding functions in Qt Designerr Mocap 12 5,929 Aug-22-2019, 03:38 PM
Last Post: Denni
  Binding functions to Menus in tkinter?? Mocap 1 2,471 Jul-23-2019, 01:37 AM
Last Post: Larz60+
  [Kivy] Kivy property (in .kv) loses binding to a variable (in .py) j.crater 3 5,146 Aug-14-2018, 12:37 PM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020