Adding images for buttons on kivy - python

I wanted to use images to replace buttons on kivy. On youtube what I've seen is people creating an Image widget as a child of the button. But whenever I do this the image becomes a lot smaller than it's native resolution. I've tried resizing it with size_hint but it just doesn't scale. What I've done is just create the the Image widget seperate from the buttons and matched up their size and positions. I'm just curious if this is the only way to go about it or is there a better way to do it.
What I tried to do based on youtube videos:
<MainGrid>:
FloatLayout:
#cols: 1
size: root.width, root.height
Button:
on_release: root.submit_button()
pos_hint: {"x":0.25,"top":0.8}
size_hint: 0.5, 0.2
Image:
source: "arrow1.png"
my "solution":
<MainGrid>:
FloatLayout:
#cols: 1
size: root.width, root.height
Button:
on_release: root.yt_button()
pos_hint: {"x":0.25,"top":0.8}
size_hint: 0.5, 0.2
background_color: 0,0,0,0
Image:
source: "arrow1.png"
pos_hint: {"x": 0, "y": 0.2}

allow_stretch is a better way:
Image:
source: "arrow1.png"
allow_stretch: True

Related

Kivy - Referencing IDs of Subclasses (Nested IDs)

I'm creating a kivy app right now. I'm quite new to Kivy and kv lang and there doesn't seam to be much rumour about it although i find it great to seperate code logic and layout, especially after some pygame development.
So to my actuall problem: I have a wiki-style screen for screenmanager, consisting out of a BoxLayout:
Title as Label
Scrollable Label for the Text (later , there shall be displayed a nested kv file)
Buttons for Navigation (scroll up and go back to main screen)
Now I'm recreating the Navigation buttons to be floating type as known from many webpages and apps. Problem is, I suddendly cant reference my ScrollView anymore. Any help or suggestions?
<Wiki>:
name: "wiki"
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: "picture.jpg"
BoxLayout:
id: box
orientation: "vertical"
padding: 10
spacing: 10
Label:
font_size: 20
size_hint_y: .1
text: root.country_text
ScrollView:
id: scrlvw
BackgroundLabel:
background_color: 220,220,220, 0.5
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
halign: "left"
valign: "top"
text: root.wiki_text
FloatLayout:
size_hint_y: .1
Button:
size_hint_x: .2
pos_hint: {"center_x": .25, "center_y": .5}
text: "Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
FloatButton:
size_hint_x: .2
pos_hint: {"center_x": .75, "center_y": .5}
text: "Up"
on_release:
widget = BoxLayout()
widget.ids.scrlvw.scroll_y = 0
Before, when it worked, it was:
BoxLayout:
FloatLayout:
size_hint_y: .1
Button:
size_hint_x: .2
pos_hint: {"center_x": .25, "center_y": .5}
text: "Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
Button:
size_hint_x: .2
pos_hint: {"center_x": .75, "center_y": .5}
text: "Up"
on_release:
scrlvw.scroll_y = 0
Well as its just a design question, I guess i temporary have to dismiss the floating design. But I would be so pleased if you could help me understand this language better.
As long as the 'kv' code described as "when it worked" is still in the same <Wiki> rule, it should still work. The newer kv code will never work as you are trying to create a new BoxLayout and reference an id in it. That has two problems:
The newly created BoxLayout is not the BoxLayout instance that appears in your GUI, so any changes to it will have no effect on what appears in the display.
Unless you have a <BoxLayout> rule in your kv, the newly created BoxLayout will not have a scrlvw id.
The ids defined within a kv rule are available for use only within that rule. See the documntation.

Kivy - Why does the source image distort in this way when set as Button background_normal image?

I am having an issue when placing an icon.png as the background_normal of a button within Kivy. When the image is displayed within the button there are black areas that stretch from the sides of the icon. Some icons appear as the they are stretched forwards from the middle as well. All icons used have a transparent background colour.
I have ensured the source image is the same res (80x80px) as the button it is placed within. Also tried setting allow_stretch to False and kee_ration to True. None seem to fix the issue.
This is how the icon should display
This is how it is being displayed within the button(ignore the brown canvas colour)
Below is the .kv section which creates the Button within a BoxLayout and then applies the source image as the background
<SettingsScreen>
name: "Settings"
size: self.width, self.height
BoxLayout:
size: root.width, root.height
cols:1
orientation: 'vertical'
spacing: 2
canvas.before:
Color:
rgba: hex('#D29F7C')
Rectangle:
size: self.size
BoxLayout:
size_hint: (None, None)
size: (1920, 80)
orientation: 'horizontal'
Button:
background_colour: 0, 0, 0, 0
background_normal: r'C:\Users\James\Documents\Coding\Python\Practice Projects\Gardening App\Icons\Home.png'
allow_stretch: False
keep_ratio: True
size_hint: (None, None)
size: (80, 80)
canvas.before:
Color:
rgba: hex('#AB9D92')
Rectangle:
pos: self.pos
size: self.size
bold: True
color: 0.7, 0.7, 0.7, 1
font_hinting: 'normal'
font_size: 40
font_name: 'calibril.ttf'
text: 'Menu'
on_release:
app.root.current = "Menu"
root.manager.transition.direction = 'right'
Issue seems to arise when the image being applied to the background of the button is the same resolution as the button itself. When the image size was decreased to slightly below that of the button the distortion disappeared.

How do I make a widget with the same size as an image in kivy

I want to have a banner on the bottom of my application which scales with varying width. However, I can't get the size of the widget to correspond to the size of the image and because of that, I leave some blank space underneath the banner itself. How can this be done?
Here my try:
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#6ec4c1")
Rectangle:
size: self.size
pos: self.pos
GridLayout:
cols: 3
pos_hint: {"top": 0.95}
size_hint: 1, 0.05
ImageButton:
source: "images/back_arrow.png"
on_release: app.change_screen("home_screen")
Image:
source: "images/icon.png"
Label:
text: ""
Image:
id: banner
keep_ratio: True
allow_stretch: True
size_hint: 1, None
source: "images/banner.png"
This code does place the picture at the bottom! But ideally, I'd like to have it stay at the bottom with full-screen width and scale in y to fit it. Is this possible?
What I want and it only works for this specific aspect ratio of the screen
When I change the width of the screen I'd like it to scale in y to fit the screen instead it keeps y constant
By default, the size_hint of any Widget is (1,1). which means that your Image will be the same size as its containing FloatLayout. So you can set values for size_hint, or you can set size_hint: None, None and then provide values for size. Also, pos_hint: {"bottom": 1} will not work, since bottom is not a supported key for pos_hint. If you want the Image at the bottom, use pos_hint: {'y':0}, but the default value for pos is (0,0), so you shouldn't even need the pos_hint: {'y':0}.
Also, if you set a size_hint to None without providing the corresponding width or height, then the default width or height (which is 100) will be used.
I think I am finally getting what you want. You can use BoxLayout instead of FloatLayout. The BoxLayout will set the size of its children to fit its available space (see documentation). So, perhaps something like this will work:
BoxLayout:
orientation: 'vertical'
canvas.before:
Color:
rgb: utils.get_color_from_hex("#6ec4c1")
Rectangle:
size: self.size
pos: self.pos
GridLayout:
cols: 3
pos_hint: {"top": 0.95}
size_hint: 1, 0.05
ImageButton:
source: "images/back_arrow.png"
on_release: app.change_screen("home_screen")
Image:
source: "images/icon.png"
Label:
text: ""
Image:
id: banner
keep_ratio: True
allow_stretch: True
# size_hint: 1, None
source: "images/banner.png"
Note that setting size_hint: 1, 0.05 in the GridLayout means that 95% of the BoxLayout will be given to the banner.

How to place widgets above and relative to an image in kivy?

I am currently working on an app for students, which describes various practical experiments.
The app consists of several AccordionItems.
The problem arises with one of them, where I want to embed an image, which keeps its aspect ratio but adapts to be as big as possible. To explain parts of the image, I would like to put semi-transparent buttons on interesting devices/objects that provide information in text form at on_release.
By stretching the app window in x or y direction and the fact that stretching the image is not allowed, there are areas above and below or to the right and left of the window that do not belong to the actual image.
How can scale and position the buttons depending on the current size of the image?
I tried to work with RelativeLayout, but the buttons seem to be oriented to the whole window, which I can't understand.
I also tried to work with ids, but I don't have the understanding to use it effectively.
Here some current code:
class LaserApp(App):
pass
if __name__ == '__main__':
#Config.set('graphics', 'fullscreen', 'auto')
Config.set('graphics', 'fullscreen', '0')
Config.set('graphics', 'window_state', 'windowed')
Config.write()
LaserApp().run()
#:import ScrollEffect kivy.effects.scroll.ScrollEffect
#:import Button kivy.uix.button.Button
Accordion:
AccordionItem:
title: 'titel1'
collapse: False
AccordionItem:
title: 'titel2'
AccordionItem:
title: 'relevant content'
RelativeLayout:
canvas:
Image
size_hint: 1, 1
pos: self.pos
size: self.texture_size
source: 'background.png'
canvas.after:
RelativeLayout:
Button: #Button i want to align and resize depending on Image: / 'background.png'
AccordionItem:
title: 'titel4'
Any comments and help are very welcome.
Many Thanks in advance
P.S.: Please excuse the bad description.
For your problem it sounds like you want something like this?:
_____________
| | | |
_____________
| | | |
_____________
| | | |
_____________
You have to create multiple buttons with:
RelativeLayout:
size_hint: 1,1
pos: self.pos
Button:
background_color: 0,0,0,.25 #rgba only, this makes the button semi-transparent
pos_hint: {'x': .66, 'y': 0}
size_hint: .33, .33
on_release: print/function
Button:
background_color: 0,0,0,.25
pos_hint: {'x': .33, 'y': 0}
size_hint: .33, .33
on_release: print/function
Button:
background_color: 0,0,0,.25
pos_hint: {'x': 0, 'y': 0}
size_hint: .33, .33
on_release: print/function
Button:
background_color: 0,0,0,.25
pos_hint: {'x': .66, 'y': .33}
size_hint: .33, .33
on_release: print/function
Button:
background_color: 0,0,0,.25
pos_hint: {'x': .33, 'y': .33}
size_hint: .33, .33
on_release: print/function
Button:
background_color: 0,0,0,.25
pos_hint: {'x': 0, 'y': .33}
size_hint: .33, .33
on_release: print/function
Button:
background_color: 0,0,0,.25
pos_hint: {'x': .66, 'y': .66}
size_hint: .33, .33
on_release: print/function
Button:
background_color: 0,0,0,.25
pos_hint: {'x': .33, 'y': .66}
size_hint: .33, .33
on_release: print/function
Button:
background_color: 0,0,0,.25
pos_hint: {'x': 0, 'y': .66}
size_hint: .33, .33
on_release: print/function
As long as you have a Layout attached to your image with size_hint: 1,1 and pos: self.pos this will bind the Layout to the same size and position of your image widget. The buttons in the example code should populate tiles that are 1/9 the size of the Layout as 9 are set in increments of .33 if you want more, just add more with the correct size_hint and pos_hint values. If RelativeLayout is an issue try using FloatLayout or BoxLayout, FloatLayout is similar to putting a blank canvas up and you can fill this widget anyway you see fit and BoxLayout functions by filling itself with children vertically or horizontally depending on how you set the orientation:. If this didnt fully answer your question or you need more help please let me know.

How can I position and size my image Button

I am new to kivy, I want to create my basic UI for android application,
and I tried to code down below, I first create my boxlayout to separate my UI into three parts: title part, main part, and icon part,
actually my question is about how to size and position my icon image button
<MyLabel#Label>:
color: .8, .9, 0, 1
font_size: 32
text_size: self.width, None
size_hint_y: None
height: self.texture_size[1]
<MyBoxLayout>:
orientation: 'vertical'
BoxLayout:
size_hint: 1, .1
Label:
text: "Face-Reg"
font_size: 50
color: .8, .9, 0, 1
text_size: self.size
ScrollView:
size_hint: 1, .8
MyLabel:
text: str ('Hello This is My New Project ' * 100)
BoxLayout:
size_hint: 1, .1
Button:
size_hint_x: 0.25
Image:
source: 'icon/server.png'
size:self.texture_size
Button:
size_hint_x: 0.25
Image:
source: 'icon/add.png'
size:self.texture_size
Button:
size_hint_x: 0.25
Image:
source: 'icon/recog.png'
size:self.texture_size
Button:
size_hint_x: 0.25
Image:
source: 'icon/renew.png'
size:self.texture_size
The output screen snapshot is:
1
Four Icon are overlapped together, also the size is not match to the button size
how can I fix that? Thanks
You can adjust the size and pos using those properties of the Image. For example, here is how you might adjust the third Button:
Button:
id: b3
size_hint_x: 0.25
Image:
source: 'icon/recog.png'
allow_stretch: True
keep_ratio: False
size: b3.size
pos: b3.pos
Note the id assigned to the Button. That id is used to assign the same size and position to the Image. The allow_stretch: True property makes the Image stretch to fit the specified size, and the keep_ratio: False allows the image to be stretched unevenly. See the Image documentation for more details.

Categories

Resources