Forum Archive

Help with draw method in custom class

Phuket2

I am trying to create a page dot view, for the want of a better word. When you see the dots/circles at a bottom of a view in iOS to indicate there are multiple pages. Normally you swipe and the dots lite up and dim. What I have listed below all works as far as the numbers go. I took out all the print statements. There is something I don't understand in the draw statement. When the view is first draw, it's drawn correctly. But when I try to change the dot color in the draw function, it does not work. As I say, I am sure the logic is ok as I had print statements everywhere, I am sure it's something about the draw function and ImageContext objects I don't understand.
It's rough at the moment, but the idea is to get it right to share

import ui

class PageIndicator(ui.View):
    def __init__(self, *args, **kwargs):
        self.num_pages = 10
        self.w = 10
        self.h = 10
        self.factor = .6
        self.selected = 2
        self.on_color = 'orange'
        self.off_color = 'black'
        self.frame = (0,0, self.w * self.num_pages, self.h)

    def layout(self):
        self.width = self.w * self.num_pages
        self.height = self.h

    def next(self):
        if self.selected == self.num_pages:
            self.selected = 1
        else:
            self.selected += 1

        # self.draw()
                # edit from @dgelessus , 
                self.set_needs_display()


    def draw(self):
        ui.set_color(self.off_color)
        for i in range(0,self.num_pages +1):
            oval = ui.Path.oval(self.w * i, 0,
                            self.w * self.factor, self.h * self.factor)             
            if (i + 1) == self.selected:
                ui.set_color(self.on_color)
                oval.fill()
                ui.set_color(self.off_color)
            else:
                oval.fill()

class TestClass(ui.View):
    def __init__(self, image_mask = None, *args, **kwargs):
        ui.View.__init__(self, *args, **kwargs)
        self.pg_ind = PageIndicator()
        self.add_subview(self.pg_ind)

        btn = ui.Button(title = 'Next Page')
        btn.action = self.next_page
        btn.width = 100
        btn.height = 32
        btn.border_width = .5
        btn.corner_radius = 3
        btn.bg_color = 'black'
        btn.tint_color = 'orange'
        self.add_subview(btn)
        btn.center = self.center

    def next_page(self, sender):
        self.pg_ind.next()

    def layout(self):
        pg_ind = self.pg_ind
        pg_ind.y = self.bounds.height - (pg_ind.h + 10) 
        pg_ind.x = (self.bounds.width / 2 ) - (pg_ind.width / 2) 


if __name__ == '__main__':
    f = (0,0, 320, 480)
    tc = TestClass( frame = f, bg_color = 'white')
    tc.present('sheet')

Edit

dgelessus

No idea if this has something to do with your problem, but to tell a view "hey, redraw yourself NOW", you should call view.set_needs_display(), not view.draw().

Unrelated suggestion, consider making PageIndicator.selected a zero-based index. Then you can write PageIndicator.draw like this (note how you don't need to add + 1 to self.num_pages anymore):

    def draw(self):
        ui.set_color(self.off_color)
        for i in range(self.num_pages):
            oval = ui.Path.oval(self.w * i, 0,
                            self.w * self.factor, self.h * self.factor)             
            if i == self.selected:
                ui.set_color(self.on_color)
                oval.fill()
                ui.set_color(self.off_color)
            else:
                oval.fill()

And PageIndicator.next like this (modulo is awesome in cases like these):

    def next(self):
        self.selected = self.selected % self.num_pages
        self.set_needs_display()
Phuket2

@dgelessus , super cool. The problem was the set_needs_display().works as expected now, have to say, it's pretty nice. I know what you mean about the zero base. Things started going wrong so I started adjusting things. But just happy it's working. Will go and look at your other ideas. I also have another mistake with scaling the rects for the ovals also. It's just top,left based. But now the basics are working I can get excited again 😱👍

Edit : I also meant to say thank you.