AttributeError: 'super' object has no attribute '__getattr__'
from kivy.app import Appfrom kivy.core.window import Windowfrom kivy.lang import Builderfrom kivy.properties import ObjectProperty, StringPropertyfrom kivy.uix.anchorlayout import AnchorLayoutfrom kivy.uix.boxlayout import BoxLayoutfrom kivy.uix.floatlayout import FloatLayoutfrom kivy.uix.gridlayout import GridLayoutfrom kivy.uix.popup import Popupfrom kivy.uix.togglebutton import ToggleButton
Builder.load_string('''
#:kivy 1.11.1
<NumberInput@TextInput>:
pos_hint: {'center_x': .5, 'center_y': .5} padding: [6, 0.9*(self.height-self.line_height)/2] input_filter: 'int' multiline: False text: '10'
<GridButton@ToggleButton>: id: self.id state: 'down' text: self.id.replace('b','') size_hint: None, None size: 30, 30
<MainScreen>:
grid_size_x: grid_size_x grid_size_y: grid_size_y
BoxLayout: orientation: 'vertical' GridLayout: cols:2 Label: text: 'Grid size (X)' NumberInput: id: grid_size_x Label: text: 'Grid size (Y)' NumberInput: id: grid_size_y Button: text: 'Make grid' on_release: root.open_popup()
<PopupScreen>:
orientation: 'vertical' size: root.size pos: root.pos Label: text: 'This is a grid' size_hint_y: None height:30 Button: text: 'Print' on_release: root.print_output() size_hint_y: None height:30 Button: text: 'Cancel' on_release: root.cancel() size_hint_y: None height:30 ''')
class GridButton(ToggleButton): id = StringProperty('') # <- likely cause pass
class PopupScreen(BoxLayout):
print_output = ObjectProperty(None) cancel = ObjectProperty(None)
class MainScreen(FloatLayout):
grid_size_x = ObjectProperty(None) grid_size_y = ObjectProperty(None) def dismiss_popup(self): self._popup.dismiss() # return window to adjusted size Window.size = self.current_size
def get_values(self):
# print grid size
print(f"x size: {self.grid_size_x.text}" + '\n' + f"y size: {self.grid_size_y.text}") ########################################### ### get states of grid buttons ### ### for example, ### ### print(state of button with id: b1) ### ### or get list of 'up' buttons ### ########################################### print(self._popup.ids.b1.state) # <- doesn't work...
def open_popup(self): # get grid sizes x_grid = int(self.grid_size_x.text) y_grid = int(self.grid_size_y.text)
# remember main screen window size self.current_size = Window.size # set popup window size Window.size = 100+x_grid*30, 200+y_grid*30 # set content of popup content = PopupScreen(print_output=self.get_values, cancel=self.dismiss_popup) # create grid grid = GridLayout(cols=x_grid, size_hint=(None,None), size=(x_grid*30, y_grid*30)) # add buttons to grid for i in range(x_grid * y_grid): grid.add_widget(GridButton(id='b'+str(i+1))) # <- likely cause
# center grid with AnchorLayout grid_wid = AnchorLayout(anchor_x='center', anchor_y='center') grid_wid.add_widget(grid)
# add grid to popup content.add_widget(grid_wid, 2)
# open popup self._popup = Popup(title="Popup", content=content) self._popup.open()
# define Base Class of Kivy Appclass TestApp(App):
def build(self): Window.size = 200, 150 return MainScreen()
# run programif __name__ == '__main__': TestApp().run()
The id only works for id’s defined in kivy. When kivy is parsed the id’s get put into the ids dictionary. The ids dict provides a way to access the objects defined in kv.
Here you know that all of your toggle buttons are in grid. I created an instance variable, self.grid to hold the grid. This lets us access the children of grid, all of the ToggleButtons you added.
print(self.grid.children) # The children in grid
for b in self.grid.children:
print(f'text:{b.text} state:{b.state}')
Here is the your code with the fixes:
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.uix.togglebutton import ToggleButton
Builder.load_string(
'''
#:kivy 1.11.1
<NumberInput@TextInput>:
pos_hint: {'center_x': .5, 'center_y': .5}
padding: [6, 0.9*(self.height-self.line_height)/2]
input_filter: 'int'
multiline: False
text: '10'
<GridButton>: # defined in python remove @ToggleButton
)
)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.grid = None # use to hold grid
def dismiss_popup(self):
self._popup.dismiss()
# return window to adjusted size
Window.size = self.current_size
def get_values(self):
# print grid size
print(f"x size: {self.grid_size_x.text}" + '\n' +
f"y size: {self.grid_size_y.text}")
###########################################
### get states of grid buttons ###
### for example, ###
### print(state of button with id: b1) ###
### or get list of 'up' buttons ###
###########################################
print(self.grid.children) # The children in grid
for b in self.grid.children:
print(f'text:{b.text} state:{b.state}')
def open_popup(self):
# get grid sizes
x_grid = int(self.grid_size_x.text)
y_grid = int(self.grid_size_y.text)
# remember main screen window size
self.current_size = Window.size
# set popup window size
Window.size = 100 + x_grid * 30, 200 + y_grid * 30
# set content of popup
content = PopupScreen(print_output=self.get_values,
cancel=self.dismiss_popup)
# create grid
self.grid = GridLayout(cols=x_grid,
size_hint=(None, None),
size=(x_grid * 30, y_grid * 30))
# add buttons to grid
for i in range(x_grid * y_grid):
self.grid.add_widget(GridButton(id='b' + str(i + 1))) # <- likely cause
# center grid with AnchorLayout
grid_wid = AnchorLayout(anchor_x='center',
anchor_y='center')
grid_wid.add_widget(self.grid)
# add grid to popup
content.add_widget(grid_wid, 2)
# open popup
self._popup = Popup(title="Popup", content=content)
self._popup.open()
--
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/9fc8410f-700e-4afe-a2cd-5f932364107ao%40googlegroups.com.
super().__init__(**kwargs)
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-...@googlegroups.com.
Here is something useful to read while you ponder the magic of super(): https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
Here is the what you need to know in short form.
It is convention to declare the instance variables of a class in the __init__() method.
If the class has a parent class, and you are overload __init__(), you also need to call the parents __init__(). The magic line super().__init__(**kwargs), calls the parents __init__(). **kwargs is the dictionary that holds the keyword arguments that were passed in.
I like this reference on **kwargs. https://realpython.com/python-kwargs-and-args/
This should help to demystify the magic ancient spells!
1.The user sets the grid size in main window
2.A grid of toggle buttons is created in a popup
3.The user edits the states of toggle buttons
4.A list of 'up' buttons is printed as output
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/e8481eba-a7f0-4c68-ac72-192430e3bddfo%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/e8481eba-a7f0-4c68-ac72-192430e3bddfo%40googlegroups.com.