--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/ad2ccf15-f76d-4654-8678-444c1064e07bn%40googlegroups.com.
Here is an example. You use the instance of the tab headers to use switch_to.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.tabbedpanel import TabbedPanel
import itertools
kv = """
BoxLayout:
orientation: 'vertical'
MyPanel:
id: tabbed_panel
do_default_tab: False
TabbedPanelItem:
text: '1'
Label:
text: 'Tab One Content'
TabbedPanelItem:
text: '2'
Label:
text: 'Tab Two Content'
TabbedPanelItem:
text: '3'
Label:
text: 'Tab Three Content'
TabbedPanelItem:
text: '4'
Label:
text: 'Tab Four Content'
BoxLayout:
size_hint_y: None
height: 48
Button:
text: 'Switch tab 1'
on_release: tabbed_panel.tab_one()
Button:
text: 'Cycle through tabs'
on_release: tabbed_panel.cycle_tabs()
Button:
text: 'Switch to tab 4'
on_release: tabbed_panel.tab_four()
"""
class MyPanel(TabbedPanel):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.tabs_cycle = None # use to hold tabs
def on_kv_post(self, base_widget):
self.tabs_cycle = itertools.cycle(self.tab_list[::-1]) # tabs in an iterator to cycle through the tabs
def cycle_tabs(self):
self.switch_to(next(self.tabs_cycle))
def tab_one(self):
self.switch_to(self.tab_list[-1]) # widgets get added in reverse order the last in the list is the first
def tab_four(self):
self.switch_to(self.tab_list[0])
class TabExampleApp(App):
def build(self):
return Builder.load_string(kv)
TabExampleApp().run()
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/ac0f94de-264d-46a9-b356-1ff0aee0e28an%40googlegroups.com.
You can use the id and the switch_to method. I have modified the example to use id at the bottom of this post.
I can be more helpful if you post a complete runnable example. The id is created in kv, and when the kv code is complied an ids dictionary is created where the key is the id and the value is the widget. Widgets created in python do not have an id, and do not populate the ids dictionary. Try printing the ids so you can see how this works. When you press the ‘Switch Tab 1’ button in the example, it will print out the ids in the example.
The code you have highlighted does not make sense to me:
self.ids['E/V']=myTPHM# this one works You are overwriting the value in the ids dictionary.
self.ids['cowE/V']=cowTPHEV# this one goes to the main tabbed panel but does not select down to the sub header needed Again, this is overwriting the ids dictionary.
You can save the header widget to a list or a variable name and then use it as a parameter in switch_to, you do not need to overwrite the ids dictionary. You should treat the ids dict as read-only.
Example updated to use ids:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.tabbedpanel import TabbedPanel
import itertools
kv =
"""
BoxLayout:
orientation: 'vertical'
MyPanel:
id: tabbed_panel
do_default_tab: False
TabbedPanelItem:
id: tab_1
text: '1'
Label:
text: 'Tab One Content'
TabbedPanelItem:
text: '2'
Label:
text: 'Tab Two Content'
TabbedPanelItem:
text: '3'
Label:
text: 'Tab Three Content'
TabbedPanelItem:
id: tab_4
text: '4'
Label:
text: 'Tab Four Content'
BoxLayout:
size_hint_y: None
height: 48
Button:
text: 'Switch tab 1'
on_release:
tabbed_panel.switch_to(root.ids.tab_1)
print(root.ids)
Button:
text: 'Cycle through tabs'
on_release: tabbed_panel.cycle_tabs()
Button:
text: 'Switch to tab 4'
on_release: tabbed_panel.switch_to(root.ids.tab_4)
"""
class MyPanel(TabbedPanel):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.tabs_cycle = None # use to hold tabs
def on_kv_post(self, base_widget):
self.tabs_cycle = itertools.cycle(self.tab_list[::-1]) # tabs in an iterator to cycle through the tabs
def cycle_tabs(self):
self.switch_to(next(self.tabs_cycle))
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/909e10fa-7af5-4e39-96f4-52a62863a7afn%40googlegroups.com.
You have nested tab panels you need to be able to select each tab panel individually. I have highlighted the changes in the code below.
I removed the reference to ids, and created a new dictionary for storing tabs. I used self.tabs to hold the top level tabs, and edit_view_tabs to store the tahns under edit/view. The instance variable self.myTPEV holds the editview tabbed panel.
self.tabs = {} # A dictionary to hold the top tabs
self.edit_view_tabs = {} # hold the edit/view tabs
self.myTPEV = None # holds edit view tabbed panel
The cowBtn_Press method needs to switch each panel to get to the desired position.
def cowBtn_Press(self, instance):
print(instance.text, instance.sex)
self.switch_to(self.tabs['E/V'])
self.myTPEV.switch_to(self.edit_view_tabs['cowE/V'])
A few additional observations:
The coding conventions for python are listed here: https://pep8.org/
While these are for library writers, you will find them helpful and it will help others that are reading your code. Take notice of the conventions for method names and variable names.
It appears that you are creating new widgets for every element in the database. If the total number of entries is small this should not be an issue. If there are 100’s of items in the database you may end up with a performance issue at startup. At startup the creation of 100’s of tabs and widgets will take a surprisingly long time. If this is the case, let me know I can suggest an alternative implementation.
I strongly suggest learning KV, it will remove lots of tedious code, and allow you to make changes to the layouts much quicker.
Edited code below:
"""
Select "location" tab and then "Hermas" child tab and then select a pink button(cow).
It should take you to the "Cow" child tab in the "View/Edit" tab. Interestingly it displays widgets
on the "Cow" header with out the "Cow" tab as if it was part part of the "View/Edit" header.
"""
from sqlite3 import dbapi2
from typing import final
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
from kivy.clock import Clock
from functools import partial
# 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
# (locName text)
# """);
opList = ["Location", "Add", "Edit/View"]
.myCow = myCow
self.tabs = {} # A dictionary to hold the top tabs
self.edit_view_tabs = {} # hold the edit/view tabs
self.myTPEV = None # holds edit view tabbed panel
for i in opList: # add headers for Location, Add, Edit/View
myTPHM = TabbedPanelHeader()
myTPHM.text = str(i)
self.add_widget(myTPHM)
if str(i) == 'Edit/View': # add new tabbed panel with headers for Cow,Calf,Bull
self.tabs['E/V'] = myTPHM
self.myTPEV = TabbedPanel()
self.myTPEV.do_default_tab = False
myTPHM.content = self.myTPEV
cowTPHEV = TabbedPanelHeader()
self.edit_view_tabs['cowE/V'] = cowTPHEV
cowTPHEV.text = 'Cow'
self.myTPEV.add_widget(cowTPHEV)
cowTPHEV.content = self.ev_cowScreen()
calfTPHEV = TabbedPanelHeader()
calfTPHEV.text = 'Calf'
self.myTPEV.add_widget(calfTPHEV)
calfStkLoc = StackLayout(orientation='tb-lr', spacing=4)
calfTPHEV.content = calfStkLoc
bullTPHEV = TabbedPanelHeader()
self.myTPEV.add_widget(bullTPHEV)
bullTPHEV.text = 'Bull'
bullStkLoc = StackLayout(orientation='tb-lr', spacing=4)
bullTPHEV.content = bullStkLoc
if str(i) == 'Location': # add new tabbed panel with headers for all locations
myTPLoc = TabbedPanel()
myTPLoc.do_default_tab = False
myTPHM.content = myTPLoc
for row in self.db.locationList():
location = row[0]
orientation='tb-lr', spacing=4)
myTPHL.content = stkLoc
### add animals to loc tab
for cows in self.db.cowsBy_Loc(location):
tagNo = cows[0]
tagClr = cows[1]
tagYr = cows[2]
type = cows[3]
desc = cows[4]
loc = cows[5]
locDte = cows[6]
birthDte = cows[7]
birthWt = cows[8]
weanDte = cows[9]
weanWt = cows[10]
sex = cows[11]
status = cows[12]
aquired = cows[13]
aquiredDte = cows[14]
disposition = cows[15]
dispDte = cows[16]
aquiredCst = cows[17]
soldAmt = cows[18]
bredByTag = cows[19]
bredByTagClr = cows[20]
bredByTagYr = cows[21]
bredByDes = cows[22]
actCalveDte = cows[23]
calfTagNo = cows[24]
calfTagClr = cows[25]
calfTagYr = cows[26]
on_press=self.cowBtn_Press)
stkLoc.add_widget(Cow)
for calves in self.db.calvesBy_Loc(location):
tagNo = calves[0]
tagClr = calves[1]
tagYr = calves[2]
type = calves[3]
desc = calves[4]
loc = calves[5]
locDte = calves[6]
birthDte = calves[7]
birthWt = calves[8]
weanDte = calves[9]
weanWt = calves[10]
sex = calves[11]
status = calves[12]
aquired = calves[13]
aquiredDte = calves[14]
disposition = calves[16]
dispDte = calves[17]
aquiredCst = calves[15]
soldAmt = calves[18]
damTagNo = calves[19]
damTagClr = calves[20]
damTagYr = calves[21]
sireTagNo = calves[22]
sireTagClr = calves[23]
sireTagYr = calves[24]
finishedWt = calves[25]
finishedDte = calves[26]
lbDayFeed = calves[27]
on_press=self.cowBtn_Press)
stkLoc.add_widget(Calf)
for bulls in self.db.bullsBy_Loc(location):
tagNo = bulls[0]
tagClr = bulls[1]
tagYr = bulls[2]
type = bulls[3]
desc = bulls[4]
loc = bulls[5]
locDte = bulls[6]
birthDte = bulls[7]
birthWt = bulls[8]
weanDte = bulls[9]
weanWt = bulls[10]
sex = bulls[11]
status = bulls[12]
aquired = bulls[13]
aquiredDte = bulls[14]
disposition = bulls[15]
dispDte = bulls[16]
aquiredCst = bulls[17]
soldAmt = bulls[18]
adg = bulls[19]
yw = bulls[20]
sc = bulls[21]
ced = bulls[22]
mm = bulls[23]
on_press=self.cowBtn_Press)
stkLoc.add_widget(Bull)
if str(i) == 'Add':
myTPHM.content = self.addScreen()
# if str(i)=='Edit/View':
# pass
def cowBtn_Press(self, instance):
print(instance.text, instance.sex)
self.switch_to(self.tabs['E/V'])
self.myTPEV.switch_to(self.edit_view_tabs['cowE/V'])
def ev_cowScreen(self):
stkEnter = StackLayout(orientation='tb-lr', spacing=5)
lbl1 = Label(text='Tag No', size_hint=(.15, .05))
txtTag = TextInput(text='', size_hint=(.15, .07))
lbl2 = Label(text='Tag Color', size_hint=(.15, .05))
txtTagClr = TextInput(text='', size_hint=(.15, .07))
lbl3 = Label(text='Tag Yr', size_hint=(.15, .05))
txtTagYr = TextInput(text='', size_hint=(.15, .07))
lbl4 = Label(text='Type', size_hint=(.15, .05))
txtType = TextInput(text='', size_hint=(.15, .07))
lbl5 = Label(text='Description', size_hint=(.15, .05))
txtDes = TextInput(text='', size_hint=(.15, .07))
lbl6 = Label(text='Current Location', size_hint=(.15, .05))
txtLoc = TextInput(text='', size_hint=(.15, .07))
lbl7 = Label(text='Location Date', size_hint=(.15, .05))
txtLocDte = TextInput(text='', size_hint=(.15, .07))
lbl8 = Label(text='Birth Date', size_hint=(.15, .05))
txtBD = TextInput(text='', size_hint=(.15, .07))
lbl9 = Label(text='Birth Wt', size_hint=(.15, .05))
txtBWt = TextInput(text='', size_hint=(.15, .07))
lbl10 = Label(text='Wean Date', size_hint=(.15, .05))
txtWeanDte = TextInput(text='', size_hint=(.15, .07))
lbl11 = Label(text='Wean Wt', size_hint=(.15, .05))
txtWeanWt = TextInput(text='', size_hint=(.15, .07))
lbl11 = Label(text='Sex', size_hint=(.15, .05))
txtSex = TextInput(text='', size_hint=(.15, .07))
lbl12 = Label(text='Status', size_hint=(.15, .05))
txtStatus = TextInput(text='', size_hint=(.15, .07))
lbl13 = Label(text='Aquired', size_hint=(.15, .05))
txtAquired = TextInput(text='', size_hint=(.15, .07))
lbl14 = Label(text='Aquired Date', size_hint=(.15, .05))
txtAquiredDte = TextInput(text='', size_hint=(.15, .07))
lbl15 = Label(text='Aquired cost', size_hint=(.15, .05))
txtAquiredCst = TextInput(text='', size_hint=(.15, .07))
lbl16 = Label(text='Disposition', size_hint=(.15, .05))
txtDispo = TextInput(text='', size_hint=(.15, .07))
lbl17 = Label(text='Disp Date', size_hint=(.15, .05))
txtDispDte = TextInput(text='', size_hint=(.15, .07))
lbl18 = Label(text='Sold Amt', size_hint=(.15, .05))
txtSold = TextInput(text='', size_hint=(.15, .07))
lbl19 = Label(text='Bred date', size_hint=(.15, .05))
txtBredDte = TextInput(text='', size_hint=(.15, .07))
lbl24 = Label(text='Est Calving Date', size_hint=(.15, .05))
txtEstClvDte = TextInput(text='', size_hint=(.15, .07))
lbl20 = Label(text='Bred By TagNo', size_hint=(.15, .05))
txtBullTagNo = TextInput(text='', size_hint=(.15, .07))
lbl21 = Label(text='Bred By Tag Color', size_hint=(.15, .05))
txtBullTagClr = TextInput(text='', size_hint=(.15, .07))
lbl22 = Label(text='Bred By Tag Yr', size_hint=(.15, .05))
txtBullTagYr = TextInput(text='', size_hint=(.15, .07))
lbl23 = Label(text='Actual Calving Date ', size_hint=(.15, .05))
txtActClvDte = TextInput(text='', size_hint=(.15, .07))
lbl25 = Label(text='Calf TagNo', size_hint=(.15, .05))
txtCalfTagNo = TextInput(text='', size_hint=(.15, .07))
lbl26 = Label(text='Calf Tag Color', size_hint=(.15, .05))
txtCalfTagClr = TextInput(text='', size_hint=(.15, .07))
lbl27 = Label(text='Calf Tag Yr', size_hint=(.15, .05))
txtCalfTagYr = TextInput(text='', size_hint=(.15, .07))
btnAccept = Button(text='Add', size_hint=(.1, .05))
return stkEnter
def addScreen(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))
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))
on_press=self.on_button)
return stkEnter
def on_button(self, instance):
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 = ''
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/508847cc-a62c-44f4-8b5b-95b06eb52f2en%40googlegroups.com.
Just for clarification, it appears that programmatically you have to "switch_to" the same tabs in order as you would manually?
In short yes. You have 2 TabbedPanels, one nested below the other. You need to select both the upper tab and the lower tan to display to content you want.
I see what you are doing by storing a reference to the headers in a dictionary for each. Should not the ids route have done the same thing?
The ids dictionary is populated by kv when processing the id tags in the kv language file. It is not a dictionary for random use. You can create your own dictionary and effectively use the same concept – a place to store widgets.
Here ore some references on the use of id and ids.
https://kivy.org/doc/master/guide/lang.html?highlight=kvlang#referencing-widgets
https://kivy.org/doc/master/api-kivy.uix.widget.html?highlight=widget#kivy.uix.widget.Widget.ids
I think I understand why a myTPEV placeholder name was created at the Class Level (i do not know if i said that correctly)- in order to access in the cowBtn_Press method?
Correct. I converted the local variable myTPEV to an instance variable self.myTPEV to it could be accessed in cowBtn_Press.
If you have the possibility of running a few thousand cows, you want to change your approach. In the current approach you are creating about 50 widgets for each cow at startup. This will take quite a lot of time with a few thousand cows. You can create the same visual effect, by getting rid of the tabbed panel, using a set of Toggle buttons to select a cow (as you do with tabs now) but instead of populating all of the widgets at once. Have one set of widgets and populate it with the selected cow.
Also concerning learning KV; thanks for the suggestion… I am going to miss by not learning how to do it in python first?
KV brings a number of benefits. It removes a lot of tedious coding. You will want to learn how the kivy properties work with KV and how id/ids work.
Enjoy the journey.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/cc98bc80-dcc4-4514-8e57-259e14614cbdn%40googlegroups.com.
A button is light weight. If you are going to have lots of buttons, you can put them in a RecycleView. The Recycleview is an efficient scrollable list.
My key point is when you use tabs, you put all of the content on each tab. If you are going to have lots of tabs each with the same set of widgets, you will run into a startup time problem. Have one way to display the data. One set of widgets capable of displaying any cow. Do not replicate the widgets for each cow.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/d11a5df5-77d1-4540-84ae-a4b8c227f398n%40googlegroups.com.