Skip to content Skip to sidebar Skip to footer

How To Target Canvas.before In Kv

In a button i have made a rounded button with canvas.before, and it changes colors as it should. The line is: canvas.before: Color: rgba: btn_color_not_pressed if self.

Solution 1:

You cannot change the variables created in kv. Once your app is running, those variables no longer exist. You can, however, use a Property that is created in kv (or python) as an attribute of a class (or the App itself). Such Properties continue to exist while the App is running, and kivy recognizes such Properties and will automatically handle changes to those Properties. An example is to create a new class that extends Button and has Properties like you want:

<-MyButton@Button>:
    # create the desired properties
    btn_color_not_pressed: [.5, .5, .5,1]
    btn_color_pressed: [.25, .25, .25, 1]

    canvas:
        Color:
            # reference the above properties
            rgba: self.btn_color_not_pressed if self.state=='normal' else self.btn_color_pressed
        RoundedRectangle:
            size: self.size
            pos: self.pos
            radius: [40]
        
        # this is copied from style.kv to show the Button text
        Color:
            rgba: 1, 1, 1, 1Rectangle:
            texture: self.texture
            size: self.texture_size
            pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)

# actually make an instance of the new MyButton class
MyButton:
    btn_color_not_pressed: [1,0,0,1]
    btn_color_pressed: [0,1,0,1]
    text: 'Button Test'

The <-MyButton@Button> creates a new class (MyButton) that extends Button. The prepended - indicates that the default canvas instructions for Button are not to be used and the provided instructions are used instead. Those new Properties can be changed in python code as usual. You can use a similar approach for the source property.

Solution 2:

That brought me a step closer.

My problem now is that the colors only change the button itself or togglebutton-group, but only when you click on them. It only reacts to the new colors when activated (button og group).

The design is not updated

I tried the solution with the - but it made no difference

main.py

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.factory import Factory

kivy.require("1.11.1")


classController(BoxLayout):
    def__init__(self):
        super(Controller, self).__init__()

        ToggleButtonBehavior.allow_no_selection = Falsedefchange_button_color(self,theme):

        if theme == "red":
            Factory.My_tgl_btn.btn_color_pressed = (1,0,0,.7)
            Factory.My_tgl_btn.btn_color_not_pressed = (1,0,0,.5)
        else: # theme == "blue":
            Factory.My_tgl_btn.btn_color_pressed = (0,0,1,.7)
            Factory.My_tgl_btn.btn_color_not_pressed = (0,0,1,.5)

classmainApp(App):
    defbuild(self):
        return Controller()

if __name__ == "__main__":
    mainApp().run()

main.kv

#:set bg_color 1,1,1,.7#:set txt_color 0,0,0,1#:import Factory kivy.factory.Factory<Controller>BoxLayout:orientation:"vertical"background_color:1,1,1,.5background_normal:""Label:text:"THIS IS THE MAIN TEKST"color:txt_colorsize_hint_y:.7BoxLayout:size_hint_y:.15My_tgl_btn:text:"RED theme"group:1state:"down"on_press:root.change_button_color("red")on_release:root.change_button_color("red")My_tgl_btn:text:"Blue theme"group:1on_press:root.change_button_color("blue")on_release:root.change_button_color("blue")BoxLayout:size_hint_y:.15My_tgl_btn:text:"Option1"group:2state:"down"My_tgl_btn:text:"Option2"group:2state:"normal"<My_tgl_btn@ToggleButton>btn_color_pressed:1,0,0,.7btn_color_not_pressed:1,0,0,.5color:txt_colorbackground_color:0,0,0,0background_normal:""canvas.before:Color:rgba:self.btn_color_not_pressedifself.state=='normal'elseself.btn_color_pressedRoundedRectangle:size:self.sizepos:self.posradius: [40]

Solution 3:

Found a solution (here: Kivy: resetting toggle buttons to "normal" on re-entering screen)

It's kind'a ugly, but it works..

Give every button an id ... and then use on_enter for each button and set and change the state.

In the code above it would mean:

on_enter:
   button1.state = "down"
   button1.state = "normal"
   button2.state = "down"
   button2.state = "normal"
   button3.state = "down"
   button3.state = "normal"
   button4.state = "down"
   button4.state = "normal"

It works ... but it is not pretty :|

Post a Comment for "How To Target Canvas.before In Kv"