The first problem is that you cannot pass an action as a keyword argument to the ui.Button constructor. It's a bit unfortunate that this is silently ignored instead of raising an exception... but you have to assign the action attribute separately.
Unfortunately, your code will crash after you do so. The reason for this is that the container view (and with it, the buttons) get garbage-collected because there are no references to them anymore after get_condensed_list returns. The underlying (ObjC) views still exist, but the Python objects are gone, which leads to garbage pointers and crashes... In short, you have to keep a reference to the btn_container view somehow. I would suggest that you simply assign it as an attribute of v (something like v.button_container = btn_container). This requires some refactoring of your get_condensed_list method. This should work:
# coding: utf-8
# This file is part of https://github.com/marcus67/rechtschreibung
import ui
from objc_util import *
DEFAULT_X_SPACING = 8
DEFAULT_HEIGHT = 44
class ButtonItemCondenser (object):
def __init__(self, button_item_list, x_spacing=DEFAULT_X_SPACING):
self.button_item_list = button_item_list
self.x_spacing = x_spacing
def get_condensed_list(self):
# see https://forum.omz-software.com/topic/2724/spacing-of-buttonitem-s
i = 0
x = 0
btn_container = ui.View(name='test')
for button_item in self.button_item_list:
btn = ui.Button(image=button_item.image, action=button_item.action)
#button_item.action(btn_container)
width = button_item.image.size[0]
btn.frame = (x, 0, width, DEFAULT_HEIGHT)
x = x + width + self.x_spacing
btn_container.add_subview(btn)
i = i + 1
x = x - self.x_spacing
btn_container.frame = (0, 0, x , DEFAULT_HEIGHT)
btn_item = ui.ButtonItem()
btn_item_objc = ObjCInstance(btn_item)
btn_item_objc.customView = ObjCInstance(btn_container)
return [btn_item]
def handle_action(sender):
#print "handle_action: sender.name=%s" % sender.name
print str(sender)
#def handle_action():
# print "handle_action"
def test():
icon_names = [ 'iob:beaker_32', 'iob:beer_32', 'iob:bag_32' ]
button_item_list = map(lambda name : ui.ButtonItem(image=ui.Image.named(name), action=handle_action), icon_names)
condenser = ButtonItemCondenser(button_item_list)
v = ui.View(frame=(0, 0, 400, 400), name='Demo')
v.background_color = 'white'
condensed_list = condenser.get_condensed_list()
normal_item = ui.ButtonItem(image=ui.Image.named('iob:checkmark_32'), action=handle_action)
condensed_list.append(normal_item)
v.right_button_items = condensed_list
v.present('sheet')
if __name__ == '__main__':
test()