Search code examples
pythonkivykivy-language

How can i change the shape of scroll bar in kivy?


In this program i want to round the corners of vertical scroll bar like a RoundedRectangle

RoundedRectangle:
    radius:[10] 

How can i do that?

Code:

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.graphics import Color, Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.app import runTouchApp 
 

Builder.load_string("""

<Button>
    size_hint: (None, None)
    height: 33
    width: 100
    text:'1'
    background_normal: ''
    background_down:'1, .3, .4, .85'
    background_color: 1, .3, .4, .85
  



<TextInput>
    id:test
    selection_color:1, .3, .4, .4
    on_text_validate:app.enter()
    cursor_color: 255/255, 223/255, 5/255, 1
    multiline:False
    height: 33
    width:800
    size_hint: (None, None)
    background_color: 0,0,0,0
    foreground_color: 255/255, 143/255, 5/255, 0.8


    
<Grid>
    
    t1:t1
    b1:b1
    grid:grid
    grid2:grid2

  
    
    GridLayout:

      
        cols:1
        id:grid
        size: root.width  ,root.height 
        
        
        ScrollView:
             
            id:scroll
            bar_height:333
            bar_margin:3
            size_hint: 1,1
            bar_width: 15
            bar_color: 255/255, 143/255, 5/255, 0.8 
            bar_inactive_color:255/255, 143/255, 5/255, 0.8 
            do_scroll_x:False
            do_scroll_y:True
            bar_pos_y:'right'
            scroll_type:['bars','content']
            
            canvas.before:
                Color:
                    rgba:192/255,192/255,192/255,.3
                RoundedRectangle:
                    radius:[10] 
                    size:15 ,root.height 
                    pos:root.width - scroll.bar_width - scroll.bar_margin,0

            
            
            GridLayout:
                height: 5000
                size_hint:1,None
                spacing:6
                id:grid2
                cols:2
                 
            
                Button:
                    id:b1
     
                TextInput:
                    id:t1
                 

""")

c=[1]

class Grid(Widget):
    t1=ObjectProperty(None)
    b1=ObjectProperty(None)
    grid=ObjectProperty(None)
    grid2=ObjectProperty(None)
    test=ObjectProperty(None)
 
    def enter(self):
              c.append(1)
              self.grid2.add_widget(Button(text='%s'%len(c)))
              self.grid2.add_widget(TextInput())
               

gr=Grid() 
class foo(App):

    def build(self):
        Window.clearcolor='#1618388'
       
        return gr
    def enter(self):
        gr.enter()
     





if __name__ == '__main__':
    foo().run()

Solution

  • In order to apply a new design/style over the existing one you can redefine its default style in kvlang as follows,

    First define a dynamic class of the ScrollView redefining it's default style as,

    <-MyScrollView@ScrollView>:
        _handle_y_pos: (self.right - self.bar_width - self.bar_margin) if self.bar_pos_y == 'right' else (self.x + self.bar_margin), self.y + self.height * self.vbar[0]
        _handle_y_size: min(self.bar_width, self.width), self.height * self.vbar[1]
        _handle_x_pos: self.x + self.width * self.hbar[0], (self.y + self.bar_margin) if self.bar_pos_x == 'bottom' else (self.top - self.bar_margin - self.bar_width)
        _handle_x_size: self.width * self.hbar[1], min(self.bar_width, self.height)
        canvas.after:
            Color:
                rgba: self._bar_color if (self.do_scroll_y and self.viewport_size[1] > self.height) else [0, 0, 0, 0]
            RoundedRectangle:
                pos: root._handle_y_pos or (0, 0)
                size: root._handle_y_size or (0, 0)
                radius: [10,]
            Color:
                rgba: self._bar_color if (self.do_scroll_x and self.viewport_size[0] > self.width) else [0, 0, 0, 0]
            RoundedRectangle:
                pos: root._handle_x_pos or (0, 0)
                size: root._handle_x_size or (0, 0)
                radius: [10,]
    

    Now use it wherever you need.

    ...
        GridLayout:
    
          
            cols:1
            id:grid
            size: root.width  ,root.height 
            
            
            MyScrollView:
                id:scroll
                bar_margin:3
                bar_width: 15
                bar_color: 255/255, 143/255, 5/255, 0.8 
                bar_inactive_color:255/255, 143/255, 5/255, 0.8 
                do_scroll_x:False
                scroll_type:['bars','content']
                
                
                GridLayout:
    ...
    

    As a side note creating a dynamic class by its default name is not always a good idea, instead of writing <Button> you can write it like <MyButton@Button>. Now add that MyButton wherever you need to.