I am making a BoxLayout widget (orientation = 'horizontal') that contains three widgets inside of it, a label, a text box, and a check box.
thisRow = BoxLayout(orientation='horizontal')
l = Label(text='Enter plate 1:\n(Plate #)')
t = TextInput(text = 'this is a text box')
c = CheckBox()
thisRow.add_widget(l)
thisRow.add_widget(t)
thisRow.add_widget(c)
This produces the following widget (thisRow):
After the box is checked...
The rightmost black box is actually the checkbox, and works functionally, however there is no way for the user to know that it is in fact a checkbox. I would expect a smaller empty square in the middle, as is depicted in pictures here.
How do i get the traditional checkbox image (smaller empty square box)? Or generally, how can I make it more obvious that the box is a check box and not just an empty label?
Thank you
This is really interesting question and Malonge tried it in a good way. Right now(1.9.2-dev) there is still fixed size on CheckBox's well, call it a background. It's an image that Widget takes from atlas and changes if the state changes. Therefore until now there was no clear way how to do it. Here is an example. Soon on master there'll be CheckBox(color=[r,g,b,a]) option. Thanks ;)
from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
Builder.load_string('''
<CheckBoxBG>:
Label:
TextInput:
CheckBox:
canvas.before:
Color:
rgb: 1,0,0
Rectangle:
pos:self.center_x-8, self.center_y-8
size:[16,16]
Color:
rgb: 0,0,0
Rectangle:
pos:self.center_x-7, self.center_y-7
size:[14,14]
''')
class CheckBoxBG(BoxLayout):pass
runTouchApp(CheckBoxBG())
Looks like the smaller check box is hidden when the background color is black. Here is an example of a red background.
It's not ideal because I do like the black background, but I can run with it for now. If anyone knows how to do this with a black background that would be great. Thank you
Alternatively, to change your checkboxes background, you can use another image from the atlas or create images and then load them:
mycheckbox= CheckBox(
background_checkbox_normal ='tlas://data/images/defaulttheme/button_disabled'
background_checkbox_down = 'my_checkboxes_checked.png'
)
In Kivy 1.9.2.dev0 (and apparently since version 1.9.0) you can change the background image of checkboxes. By default, Kivy uses for these backgrounds from the atlas*.
background_checkbox_normal = StringProperty('atlas://data/images/defaulttheme/checkbox_off') #when the checkbox is not active.
background_checkbox_down = StringProperty('atlas://data/images/defaulttheme/checkbox_on') # when the checkbox is active.
background_checkbox_disabled_normal = StringProperty('atlas://data/images/defaulttheme/checkbox_disabled_off') #when the checkbox is disabled and not active.
background_checkbox_disabled_down = StringProperty('atlas://data/images/defaulttheme/checkbox_disabled_on') #when the checkbox is disabled and active.
You can have a look here at all the attributes :
*The atlas is a package of multiple textures that reduces the number of images loaded and speedup the application loading. You have see a preview of the atlas in Python Install Folder\Lib\site-packages\kivy\data\images\defaulttheme-0.png
Related
I've made a rule in my kv for the Button class to have a specific background (provided in an image). When I created an ActionBar that contains ActionPrevious and ActionButton widgets, they both seemed to get the same background.
And I would understand that ActionButton instance got that background, since it inherits from Button and ActionItem classes, but why did the ActionPrevious get the same background? It inherits from BoxLayout and ActionItem, neither of which have anything to do with the Button class. What's the reason behind it?
Also, a side question
The ActionPrevious has a property with_previous which, when set to True, adds a clickable arrow. However, the title of the widget remains unclickable. But the docs say that this property would make the whole widget clickable. While it's not a big deal, I'd rather want the entire ActionPrevious widget background to change on press. Is it possible to achieve this?
So what I mean is that when you press the Back arrow, only the space around it and the app icon turns blue, but the text doesn't, as if it's part of a different widget.
Here is the code to visualize the question:
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.actionbar import ActionBar
Builder.load_string('''
<Button>:
background_normal: 'some_file.png'
<MenuBar>:
ActionView:
ActionPrevious:
title: "Log out"
with_previous: True
ActionButton:
text: "Settings"
''')
class MenuBar(ActionBar):
pass
runTouchApp(MenuBar())
Okay, so the truth was in the style.kv file. Basically, ActionPrevious widget has the following structure:
<ActionPrevious>:
GridLayout:
ActionPreviousButton:
GridLayout:
ActionPreviousImage:
id: prev_icon_image # the "back" arrow
ActionPreviousImage:
id: app_icon_image # the app icon
Widget:
# perhaps something to split the title from the GridLayout
Label:
id: title # the title
And the ActionPreviousButton inherits from Button, so that's why the ActionPrevious arrow part was getting that background.
Here also lies the answer to the side question. Since the clickable part is the ActionPreviousButton, and the title is kept in a Label, that is not a child of it, the text is unclickable. So to fix that, one has to create a custom class and put the Label as a child of the ActionPreviousButton.
I'm using Kivy with Python 2.7. I am familiar with how to alter the color of the static button itself, but how do you change the color of the button when you press it? The default is blue.
Thanks for any help.
According to the reference for Button, the property background_down stores the path to an image used for the background while the Button is pressed. This is the default:
background_down = StringProperty(
'atlas://data/images/defaulttheme/button_pressed')
You can change that property to point to a different image oratlas.
The Kivy framework uses background images for button_normal and button_down, which the background_color only tints, so this in the kv language might not behave how you'd expect:
<Button>:
background_color: 1, 0, 0 # Tints the button red
background_normal: 'images/button_normal.png' # A clear image gives a bright red.
background_down: 'images/button_down.png' # A gray image gives a duller red.
border: (2, 2, 2, 2) # Don't stretch the outer two pixels on each edge when resizing.
This style lets you have say a dull border and bright inner and swap them round on the button press.If you use this system though, images will be imported with colours ignored. To fix this and solve your problem remove the background_color:
<Button>:
background_normal: 'images/button_normal.png' # Eg. A red button
background_down: 'images/button_down.png' # Eg. A green button
border: (2, 2, 2, 2) # Don't stretch the outer two pixels on each edge when resizing.
That'll change the colour of the buttons to whatever you've made in the image. It's worth noting that Kivy is excellent at stretching the images out, so if you have single colour buttons or tiny borders, you only need a tiny image, I use 8x8 pixels.
I am working on developing an application using Kivy. I am using Kivy ActionBar for creating a menu bar for my application.
Kindly refer to the image attached
I want to remove the Kivy icon and move the other options(file / edit) to the left. Please find the snippet of my code.
menuAcBar = ActionBar(pos_hint={'top': 1.3})
menuAcView = ActionView()
menuAcBar.add_widget(menuAcView)
menuAcPrevious = ActionPrevious(with_previous=False)
menuAcView.add_widget(menuAcPrevious)
menuAcView.add_widget(ActionButton(text="File"))
menuAcView.add_widget(ActionButton(text="Edit"))
menuAcView.add_widget(ActionButton(text="Documents"))
menuAcView.add_widget(ActionButton(text="help"))
self.add_widget(menuAcBar)
Right on ActionPrevious you can set app_icon. It's a little bit lower in docs. You can set app_icon_width/height for size of the icon or even remove it with app_icon='', but it'll leave white rectangle instead of a "transparent". Leave app_icon be and set only width and height to make it invisible.
The Ä„ctionPrevious has ActionItem's minimum_width property, therefore you need to change it like this:
menuAcPrevious = ActionPrevious(with_previous=False,
app_icon=<your_image>,
app_icon_width=1,
app_icon_height=0,
minimum_width=10,
size_hint_x: None)
Edit:
It seems that ActionPrevious leaves additional unused space even if title='' and minimum_width=1 and you can't access the damn thing through children because it's unregistered, therefore the only thing I came up with is resizing it so you won't see it anymore:
ActionPrevious(
size_hint_x = None,
width = 0,
app_icon_width = 0.1,
with_previous = False)
The goal is a screen which uses one of several images (randomly chosen upon each screen load) as a background.
The app contains the following:
class AnswerScreen(Screen):
bkgd = ""
def choose_bkgd(self):
self.bkgd = "{}.jpg".format(random.randint(0,8))
My kv file contains the following:
<AnswerScreen>
on_pre_enter: root.choose_bkgd()
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: root.bkgd
Unfortunately the background is always just a solid white.
I've added a print call to choose_bkgd(), and it always prints an acceptable file name, and I've also tried using on_enter: but there is no change. If I replace source: with a file name instead of root.bkgd the image displays correctly. This leads me to believe that the background is being generated before the function is being called to set the bkgd variable, but this confuses me as I thought the whole point of on_pre_enter was to execute code prior to the loading of the screen. The kivy docs haven't cleared this up for me. Any help is greatly appreciated.
Make bkgd a kivy property. This is essential to be able to bind to it and have things automatically update when it changes.
from kivy.properties import StringProperty
class AnswerScreen(Screen):
bkgd = StringProperty("")
...
I'm trying to use Kivy to display a background image, so I want the root widget to be the same size as the image. Currently, when I load the image from the kv file it appears as a small thumbnail in the bottom-left corner. The app window appears to be about the correct (full-scale) size, but hard to tell. Code below, any thoughts?
.kv file:
#:kivy 1.8.0
<BarBot_splash>:
BoxLayout:
size: image.size
Image:
id: image
source: 'MainMenu.png'
.py file:
import kivy
kivy.require('1.8.0')
from kivy.app import App
from kivy.uix.widget import Widget
class BarBot_splash(Widget):
def on_touch_up(self, touch):
if touch.x < self.width/3:
#we touched the menu button
pass
elif touch.x > self.width/3*2:
#we touched the custom button
pass
else:
return False
class BarBot(App):
def build(self):
return BarBot_splash()
if __name__=='__main__':
BarBot().run()
In main.py:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
class BarBot_splash(BoxLayout): # subclass BoxLayout.. now it's inherently a Boxlayout
kv:
#:kivy 1.8.0
<BarBot_splash>: # I'm a BoxLayout...
Image:
id: image
source: 'MainMenu.png'
That should do the trick. The BoxLayout should take up the window. It's one child, the Image, should in turn take up the full size of the BoxLayout. Why? Well, someone correct me if I'm wrong, but I think it's because the size_hint property of the BoxLayout and the Image both default to (1, 1), which translates to: "Take up as much space in your parent as you can" or (100% width, 100% height). Though it may not be possible for a child to take up all of it's parents area if there are also other children in the parent, like if you had a few Images in the BoxLayout, or more than one BoxLayout in your app etc.. Setting a size_hint to (.5, .3) would mean take up (50% the width, 30% the height) of your parent/container, or available space.
BarBot_splash is just a widget, so it doesn't apply any position or size to its children, therefore the boxlayout (and thus its child image) have only the default position of (0, 0) and size of (100, 100).
Change BarBot_splash to a BoxLayout or other resizing layout and this will propagate correctly. You also don't need the size: image.size line, this does nothing.
Obviously very old question but I'm new to Kivy and just had to work through a very similar problem and there was very little help on the topic, so this is for future people like me:
I had the same problem but the image was also in a scatter widget. Solution is really simple, just frustrating to find. Hierarchy has to be as follows:
BoxLayout:
Scatter:
size: image.size
Image:
id: image
size: root.size