Forum Archive

[lab] easy way to make pics using ui.Button

Phuket2

Not for experts, for newbies like me!
The code below is very limited on styles. But as you can see very easy to add params to btn_image func to modify the result.


'''
    Pythonista Forum - @Phuket2
'''
import ui, editor
import calendar

def btn_image(text, w = 256):
    btn = ui.Button( title = text)
    btn.frame = (0, 0, w, w)
    btn.bg_color = 'teal'
    btn.tint_color = 'white'
    btn.font = ('Arial Rounded MT Bold', w * .4)
    btn.corner_radius = btn.width / 2
    with ui.ImageContext(w, w) as ctx:
        btn.draw_snapshot()
        return ctx.get_image()

if __name__ == '__main__':

    for i in range(1, 13):
        m_name = calendar.month_abbr[i]
        btn_image( m_name, w = 48).show()

    for i in range(1, 11):
        btn_image( str(i) , w = 32).show()

    lst = ['stop', 'start', 'go' , 'wait']
    for lb in lst:
        btn_image( lb, w = 256).show()

abcabc

Very good idea. Although draw_snapshot is very slow, it is good for making images only once (or occasionally) . Doing this directly in image context seems bit difficult (things like getting round shape, adjusting size with draw_string etc.) Even transformations are bit easier here. Here is a slightly complicated example (our old circular layout example).

import ui, editor
import calendar
from math import pi

def make_btn(text, w = 256, v=None):
    btn = ui.Button( title = text)
    btn.frame = (0, 0, w, w)
    btn.bg_color = 'teal'
    btn.tint_color = 'white'
    btn.font = ('Arial Rounded MT Bold', w * .4)
    btn.corner_radius = btn.width / 2
    btn.center=v.bounds.center()
    btn.transform=ui.Transform.rotation(-2.*pi*i/N).concat(
        ui.Transform.translation(0,-(v.height/2-btn.height/2))).concat(
        ui.Transform.rotation(2.*pi*i/N))
    return btn

w1= 576
v=ui.View(frame=(0,0,w1, w1))
v.bg_color=(1,1,1)
N=12
for i in range(0,N):
    a = make_btn(calendar.month_abbr[i+1], w=48, v=v) 
    v.add_subview(a)

with ui.ImageContext(w1, w1) as ctx:
    v.draw_snapshot()
    img = ctx.get_image()

img.show()
Phuket2

@abcabc yeah agreed. It's a little slow. I wanted a quick and dirty way to supply ui.ListDataSource items.image with a non builtin image. That's how I found myself writing the above. Otherwise could just use the ui.Button or just Draw it real time. But as you point out, it's ok for a small number of images. Sometimes you just need to pass an image unless you want to do a bunch of extra work. Eg. I could render the cells contents, but if you can avoid better I think.

Phuket2

I was doing something like the below.


'''
    Pythonista Forum - @Phuket2
'''
import ui, editor
import calendar

def btn_image(text, w = 256, *args, **kwargs):
    btn = ui.Button( title = text)
    btn.frame = (0, 0, w, w)
    btn.bg_color = 'teal'
    btn.tint_color = 'white'
    btn.font = ('Arial Rounded MT Bold', w * .4)
    btn.corner_radius = btn.width / 2
    for k, v in kwargs.items():
        if hasattr(btn, k):
            setattr(btn, k, v)

    with ui.ImageContext(w, w) as ctx:
        btn.draw_snapshot()
        return ctx.get_image()

class MonthDataSource(ui.ListDataSource):
    def __init__(self, items = [], *args, **kwargs):
        lst = []
        for m in range(1, 13):
            rec = dict(title = calendar.month_name[m] , image=btn_image(calendar.month_abbr[m][0], w = 26, bg_color = 'deeppink'), accessory_type = 'checkmark' )
            lst.append(rec)
        items = lst
        super().__init__(items, *args, **kwargs)

class TableBase(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.tv = ui.TableView(name='table')
        self.tv.flex = 'wh'
        self.add_subview(self.tv)   

class MonthTable(TableBase):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.tv.data_source = MonthDataSource()

    def layout(self):
        if self.superview:
            self.frame = self.superview.bounds

class MyClass(ui.View):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)       

if __name__ == '__main__':
    _use_theme = True
    w, h = 300, 600
    f = (0, 0, w, h)

    mc = MyClass(frame=f, bg_color='white', name='Months')
    mc.add_subview(MonthTable())

    if not _use_theme:
        mc.present('sheet', animated=False)
    else:
        editor.present_themed(mc, theme_name='Oceanic', style='sheet', animated=False)
Phuket2

@abcabc , you should take a look at this module for guestures if you have not seen it Github. @JonB pointed me to this one. I have just started to try it. It's nice. Very easy to get up,and running. Especially for a long press. Is simple. Pinch is also easy, but I can see the more you have your head around the Transforms then do anything. Anyway, if you haven't seen, I think this would be right up your alley