Posts: 73
Threads: 28
Joined: Oct 2021
Nov-05-2021, 03:07 PM
(This post was last modified: Nov-05-2021, 03:50 PM by Yoriz.
Edit Reason: Added code tags
)
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.
Posts: 2,168
Threads: 35
Joined: Sep 2016
Nov-05-2021, 04:00 PM
(This post was last modified: Nov-05-2021, 04:01 PM by Yoriz.)
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.
Posts: 73
Threads: 28
Joined: Oct 2021
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()
Posts: 2,168
Threads: 35
Joined: Sep 2016
Nov-06-2021, 10:51 AM
(This post was last modified: Nov-06-2021, 10:51 AM by Yoriz.)
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()
Posts: 73
Threads: 28
Joined: Oct 2021
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
Posts: 2,168
Threads: 35
Joined: Sep 2016
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.
Posts: 73
Threads: 28
Joined: Oct 2021
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()
Posts: 2,168
Threads: 35
Joined: Sep 2016
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.
Posts: 73
Threads: 28
Joined: Oct 2021
|