I learnt that in Qt we do have some ways to make a QpushButton with :
I am looking to make Buttons behavior similar in kivy as well . Is it possible ? I learnt that we can change background Image changed to a Image with rounded shape Changing the background color of a Button in Kivy
but this is not that satisfying as the button still looks very normal . There s no shadow affect . Even when we click on the corners outside the button it is treated s if button is clicked .
I have gone through documentation of Kivy Button as well as Label and tried to change the behavior and look of a button . Can someone advice on how to make a button look better We can try to have :
Below is a code which i just created for exploring more into buttons in Kivy :
__author__ = 'pbatra'
#Good info about background
#https://stackoverflow.com/questions/20181250/changing-the-background-color-of-a-button- in-kivy/20181407#20181407
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.uix.image import Image
from kivy.graphics import Color
gui = '''
<MenuScreen>:
canvas.before:
BorderImage:
# BorderImage behaves like the CSS BorderImage
border: 10, 10, 10, 10
texture: self.background_image.texture
pos: self.pos
size: self.size
GridLayout:
size_hint: .1, .1
pos_hint: {'center_x': .5, 'center_y': .5}
rows: 1
Button:
text: 'Play'
font_size: 20
font_name: 'DroidSans'
bold: True
italic: True
height: 10
background_color: (0.5, 0.7, 0.5, 0.9)
#Read more about them from documentation
background_normal: './images/orange.png'
background_down: './images/green.png'
border: 30,30,30,30
color: (1, .3, .8, .5)
on_press: self.text = 'Oh yeah'
'''
class MenuScreen(Screen):
background_image = ObjectProperty(
Image(
source='../Examples/examples/widgets/sequenced_images/data/images/button_white_animated.zip',
anim_delay=.5))
Builder.load_string(gui)
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
class MyJB(App):
def build(self):
return sm
if __name__ == '__main__':
MyJB().run()
The problem with using background_normal = '' is that it blows away the kivy button image with raised edges/shadowing and setback. One way to get a raised button of a specific color would be to make your own atlas using gimp or other editors.
To change the background color of the button, use the CSS background-color property and give it a value of a color of your taste. In the .button selector, you use background-color:#0a0a23; to change the background color of the button.
In other words, it can have 'RGB' values > 1. So to get an exact button color with the kivy button defaulttheme for raised edges, use:
Use the box-shadow property to add shadows to a button: Use the opacity property to add transparency to a button (creates a "disabled" look). Tip: You can also add the cursor property with a value of "not-allowed", which will display a "no parking sign" when you mouse over the button:
Button in kivy starts with a ButtonBehavior which is combined with a Label adding properties like background_normal/down...for handling textures on the canvas.
Knowing this you can simply combine ButtonBehavior with any other widget you choose. Eg.
from kivy.base import runTouchApp
from kivy.lang import Builder
kv = '''
<ButImage@ButtonBehavior+AsyncImage>
FloatLayout:
# we don't specify anything here so float layout takes the entire size of the window.
ButImage:
id: but
# take 50% size of the FloatLayout
size_hint: .5, .5
# Make Button change it's opacity when pressed for visual indication
opacity: 1 if self.state == 'normal' else .5
source: 'http://www.victoriamorrow.com/sitebuildercontent/sitebuilderpictures/enter_button.gif'
# Introduce Label incase you want text on top of the image
Label:
center: but.center
# change text acc to but state
text: "Normal" if but.state == 'normal' else 'down'
'''
if __name__ == '__main__':
runTouchApp(Builder.load_string(kv))
Here we just set the ButtonBehavior to be combined with a AsyncImage which downloads the image from web for your background.
you should see something like this
Animation affect in background
This would be as simple as changing the source to animated gif or list of images inside a .zip.
from kivy.base import runTouchApp
from kivy.lang import Builder
kv = '''
<ButImage@ButtonBehavior+AsyncImage>
FloatLayout:
ButImage:
id: but
size_hint: .5, .5
opacity: 1 if self.state == 'normal' else .5
allow_stretch: True
keep_ratio: False
source: 'http://media1.policymic.com/site/article-items/2095/1_gif.gif'
Label:
center: but.center
text: "Normal" if but.state == 'normal' else 'down'
'''
if __name__ == '__main__':
runTouchApp(Builder.load_string(kv))
Look at the sequence images example This was done before ButtonBehaviors were introduced so it even has a example of a AnimatedButton class using the older method which is essentially not needed any more.
Shadow Effect:
There are many ways to do this too.
You could either add a shadow to a widget/layout and have the button on top of this widget/layout take up less space than the shadow so as to account for touch on the shadows.
Or Create your own CustomButtonBehavior class derived from ButtonBehavior that overrides collidepoint
method to only return True for custom collision. There is a example of using custom collision for widgets. You could even set the Image's keep_data
property to True and later check pixel data for alpha to determine if you want to return true for collision.
Rounded edges etc.
Simply use a image with rounded edges kivy supports use of BorderImage Instruction which is equivalent to css borderimage in terms of functionality. Kivy's own button by default uses this. Try and experiment with border attribute of BorderImage.
from kivy.app import App from
kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
class lay(FloatLayout):
def __init__(self, **kwargs):
super(lay,self).__init__(**kwargs)
self.btn = Button(background_normal='image_state_on.png',
background_down='image_state_off', size_hint_x = .50, size_hint_y = .50)
self.add_widget(self.btn)
class ImageButton_APP(App):
def build(self):
return lay()
ImageButton_APP().run()
I think this is more effective. I am using two kind of image.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With