How to create Dropdown animation in Kivy - python

I'm trying to animate a dropdown symbol to rotate down (when the dropdown option is open) and revert back to it's original position (when dropdown option closes). Please find this attached screenshot.
Here's my py file:
from kivy.lang.builder import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.utils import get_color_from_hex as hex
from kivy.animation import Animation
Builder.load_file("dropdowns_and_btns.kv")
kv = """
#:import hex kivy.utils.get_color_from_hex
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
MyScreenManager:
transition: FadeTransition(duration=0)
IntroPage:
LandingPage:
ResultPage:
<IntroPage>
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
text: "BGF"
color: hex("#ECE4F5")
font_size: 36
pos_hint: {"center": (0.5, 0.7)}
halign: "center"
RoundedGradientButton:
text: "START"
font_size: 20
size_hint: 0.3, 0.08
pos_hint: {"center": (0.5, 0.3)}
on_release: app.root.current = "landing_page"
<LandingPage>
name: "landing_page"
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
icon_color: 1, 0, 1, 1
text: "Please select"
pos_hint: {"center_y": 0.9}
halign: "center"
font_size: 32
color: hex("#ECE4F5")
# Dropdown Label
MDFloatLayout:
size_hint: 0.75, 0.3
pos_hint: {"center": (0.5, 0.5)}
BoxLayout
size_hint: 0.5, 0.9
pos_hint: {"center": (0.26, 0.9)}
MDLabel:
text: "Month"
color: hex("#ECE4F5")
BoxLayout
size_hint: 0.5, 0.9
pos_hint: {"center": (0.79, 0.9)}
MDLabel:
text: "Year"
color: hex("#ECE4F5")
# Dropdown Button
MDGridLayout:
cols: 2
size_hint: 1, 0.3
pos_hint: {"center": (0.5, 0.65)}
spacing: 30
DropdownMenu:
id: month
text: 'Select'
values: [month for month, x in app.temp_db.items()]
on_text: self.text
DropdownMenu:
id: year
text: 'Select'
values: [f"{year}" for year in range(18, 46)]
on_text: self.text
# Find now button
RoundedGradientButton:
text: "FIND NOW"
font_size: 16
size_hint: 0.25, 0.25
pos_hint: {"center": (0.5, 0.15)}
<ResultPage>
name: "result_page"
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
id: result_prefix_label
text: "Congratulations!"
color: hex("#ECE4F5")
font_size: 20
pos_hint: {"center": (0.5, 0.7)}
halign: "center"
MDLabel:
id: result_label
color: hex("#ECE4F5")
font_size: 40
pos_hint: {"center": (0.5, 0.6)}
halign: "center"
Button:
background_normal: ""
background_color: 0, 0, 0, 0
pos_hint: {"center": (0.5, 0.3)}
on_press: app.root.current = "landing_page"
Image:
source: "images/reload.png"
center_x: self.parent.center_x
center_y: self.parent.center_y
size_hint_x: None
height: 50
"""
class IntroPage(Screen):
pass
class LandingPage(Screen):
pass
class ResultPage(Screen):
pass
class MyScreenManager(ScreenManager):
pass
class BabyGenderFinder(MDApp):
temp_db = {"January": 1, "February": 2, "March": 3, "April": 4, "May": 5}
def build(self):
return Builder.load_string(kv)
def DropdownBtnAnimation(self, wid):
ani = Animation(angle=-90, duration=0.02)
ani.start(wid)
BabyGenderFinder().run()
kv file:
#:import hex kivy.utils.get_color_from_hex
#:import Factory kivy.factory.Factory
# Drop down button setting
<DropdownMenu#Spinner>
dropdown_cls: Factory.CustomDropdown
option_cls: Factory.DropdownOptions
color: hex("#87828C")
font_name: "fonts/Poppins-Medium.ttf"
background_normal: ""
background_color: 0, 0, 0, 0
on_release: self.color = hex("ECE4F5") ; app.DropdownBtnAnimation(self.ids.dropdown_sign)
canvas.before:
Color:
rgba: hex("#111140")
RoundedRectangle:
size: self.size
pos: self.pos
radius: [6]
Color:
rgba: hex("#1F1F73")
Line:
width: 1.25
rounded_rectangle: self.x, self.y, self.width, self.height, 6, 6, 6, 6, 100
MDIconButton:
id: dropdown_sign
center_x: self.parent.center_x + 110
center_y: self.parent.center_y
angle: 0
canvas.before:
PushMatrix
Rotate:
angle: self.angle
axis: 0, 0, 1
origin: self.center
canvas.after:
PopMatrix
Image:
source: "images/dropdown.png"
size_hint: None, None
size: 20, 20
# Drop down options setting
<DropdownOptions#SpinnerOption>
color: hex("#ECE4F5")
font_name: "fonts/Poppins-Regular.ttf"
background_normal: ""
background_color: 0, 0, 0, 0
# Drop down options separator setting
canvas:
Color:
rgba: hex("#3D3D99")
Line:
width: 1
points: self.x+10, self.y, self.width-10, self.y
<CustomDropdown#DropDown>:
canvas.before:
Color:
rgba: hex("#1F1F73")
RoundedRectangle:
size: self.size
pos: self.pos
radius: [0, 0, 6, 6]
max_height: 200
# Gradient button settings
<RoundedGradientButton#Button>
background_normal: ""
background_color: 0,0,0,0
font_name: "fonts/Poppins-Medium.ttf"
on_press: self.size_hint = self.size_hint_x/1.05, self.size_hint_y/1.05
on_release: self.size_hint = self.size_hint_x*1.05, self.size_hint_y*1.05
canvas.before:
Color:
rgba: 1, 1, 1, 1
RoundedRectangle:
source: "button_bg.png"
size: self.size
pos: self.pos
radius: [self.size[1]/1.92]
I can make the button rotate down, but I can't seem to make the button go back to normal when dropdown options closes. I also want some actions done when I close Spinner widget (ex: If I clicked outside the dropdown options list when the list is open, I wanna trigger some actions)
I'm fairly new with kivy. Please help me.

In your kv, you can set the angle back to 0 when the text is changed on the DropdownMenu:
DropdownMenu:
id: month
text: 'Select'
values: [month for month, x in app.temp_db.items()]
on_text: self.ids.dropdown_sign.angle=0
Or, you can eliminate the animation completely, and just set the angle of the icon to depend on whether the DropdownMenu is open:
MDIconButton:
id: dropdown_sign
center_x: self.parent.center_x + 110
center_y: self.parent.center_y
# angle: 0
canvas.before:
PushMatrix
Rotate:
angle: 90 if root.is_open else 0 # adjusts angle of icon
axis: 0, 0, 1
origin: self.center
canvas.after:
PopMatrix
Image:
source: "images/dropdown.png"
size_hint: None, None
size: 20, 20

To create dropdown animation, we can create close animation method just like DropdownBtnAnimation in PY file:
class BabyGenderFinder(MDApp):
temp_db = {"January": 1, "February": 2, "March": 3, "April": 4, "May": 5}
def build(self):
return Builder.load_string(kv)
def DropdownBtnAnimation(self, wid):
ani = Animation(angle=-90, duration=0.02)
ani.start(wid)
def dropdown_btn_close_animation(wid):
ani = Animation(angle=0, duration=0.02)
ani.start(wid)
And use on_is_open property in kv:
<DropdownMenu#Spinner>
dropdown_cls: Factory.CustomDropdown
option_cls: Factory.DropdownOptions
color: hex("#87828C")
font_name: "fonts/Poppins-Medium.ttf"
background_normal: ""
background_color: 0, 0, 0, 0
on_is_open: app.DropdownBtnAnimation(self.ids.dropdown_sign) if self.is_open == True else app.dropdown_btn_close_animation(self.ids.dropdown_sign)
on_release: self.color = hex("ECE4F5")
canvas.before:
Color:
rgba: hex("#111140")
RoundedRectangle:
size: self.size
pos: self.pos
radius: [6]
Color:
rgba: hex("#1F1F73")
Line:
width: 1.25
rounded_rectangle: self.x, self.y, self.width, self.height, 6, 6, 6, 6, 100

Related

I had a problem with creating a popup in kivy with rounded edges

I tried to create a white popup window with rounded edges as the first image by using a canvas, but when I write canvas.after or canvas.before it comes behind or above the popup window content, so how I can make it looks like the first image?
.py file:
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.core.text import LabelBase
from kivy.uix.popup import Popup
Window.size = [300,600]
class MyLayout(Widget):
pass
class Exercise(App):
def build(self):
#Window color
Window.clearcolor = (249/255.0, 249/255.0, 249/255.0, 0)
Builder.load_file("myfile.kv")
#Loading .kv file
return MyLayout()
if __name__ == "__main__":
Exercise().run()
.kv file:
#: import Factory kivy.factory.Factory
<MyPopup#Popup>
auto_dismiss: False
title: ""
separator_height: 0
size_hint: 0.8, 0.4
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba:(255/255,255/255,255/255,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [40]
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 0, 10, 10, 10
border: 50
border_color: (1,1,1,1)
Label:
text: "Good job"
color: 0,0,0,1
font_size: 16
CloseButton:
text: "Close"
color: 0,0,0,1
size_hint: (None , None)
width: 105
height: 40
pos_hint: {'center_x':0.5}
on_release: root.dismiss()
<MyLayout>:
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 20,40
#spacing: 20
Label:
font_size: 20
text: 'Click the button'
color: 0, 0, 0, 1
MyButton:
font_size: 20
text: "Button"
color: (0,0,0,1)
size_hint: (None , None)
width: 250
height: 50
pos_hint: {'center_x':0.5}
on_release: Factory.MyPopup().open()
<CloseButton#Button>:
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba:(252/255,131/255,87/255,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [20]
<MyButton#Button>
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba:(252/255,131/255,87/255,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [25]
Remove the canvas.before from the first part of the Popup and add it to the BoxLayout. Adjust the size and position of the canvas.before to make it cover the default background.
Here is the modified Popup definition that will work.
<MyPopup#Popup>
auto_dismiss: False
title: ""
separator_height: 0
size_hint: 0.8, 0.4
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 0, 10, 10, 10
border: 50
border_color: (1,1,1,1)
canvas.before:
Color:
rgba: 1, 1, 1, 1
RoundedRectangle:
pos: self.x - 20, self.y - 20
size: self.width + 40, self.height + 60
radius: [40]
Label:
text: "Good job"
color: 0,0,0,1
font_size: 16
CloseButton:
text: "Close"
color: 0,0,0,1
size_hint: (None , None)
width: 105
height: 40
pos_hint: {'center_x':0.5}
on_release: root.dismiss()

Storing selection of TextInput when not is focus (Kivy)

I have a TextInput and a button, and my aim is to be able to select some text from the TextInput and then push a button which calls a function that prints: selection_text, selection_to, and selection_from.
However, because the TextInput is not in focus when the button is pushed, the selection is lost and the function returns nothing AND/OR incorrect values.
I have seen this line of code in similar questions but I have not been able to figure out what it is meant to do, via messing with the code or looking at the TextInput docs, since I have only seen it called from within an 'on_focus' function
Clock.schedule_once(lambda dt: new_post_input.selection_text)
I have not been able to recreate the issue in an example program yet since it works when I have taken the widgets into their own program
main.py
from kivy.app import App
from kivy.properties import BooleanProperty, StringProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.modules import inspector
from kivy.core.window import Window
class NewPost(FloatLayout):
buttons_disabled = BooleanProperty(False)
cancle_button_disabled = BooleanProperty(True)
preview_text = StringProperty()
def make_bold(self, new_post_input, selected):
print('Selected = ' + selected)
print('Button has been pushed')
def preview_post(self, Button, cancleButton, TextInput, Label):
#self.preview_text = ('Hello\n' + TextInput.text)
self.buttons_disabled = True
self.cancle_button_disabled = False
Label.opacity = 1
Label.pos_hint = {'center_x': 0.5, 'center_y': 0.5}
TextInput.opacity = 0
cancleButton.opacity = 1
cancleButton.pos_hint = {'center_x': 0.5, 'center_y': 0.5}
Button.opacity = 0
Button.pos_hint = {'center_x': 0.5, 'center_y': -1}
#print(TextInput.text)
def back_from_preview(self, Button, previewButton, TextInput, Label):
self.buttons_disable = False
self.cancle_button_disabled = True
Label.opacity = 0
Label.pos_hint = {'center_x': 0.5, 'center_y': -1}
TextInput.opacity = 1
Button.opacity = 0
Button.pos_hint = {'center_x': 0.5, 'center_y': -1}
previewButton.opacity = 1
previewButton.pos_hint = {'center_x': 0.5, 'center_y': 0.5}
class SelectionApp(App):
def build(self):
inspector.create_inspector(Window, SelectionApp)
SelectionApp().run()
selection.kv
PageLayout:
Label:
text: 'Swipe to the next page'
font_size: dp(50)
Label:
text: 'And again'
canvas.before:
Color:
rgba: (0,.8,.8,1)
RoundedRectangle:
size: self.size
radius: [dp(6),]
pos: self.x, self.y
NewPost:
id: new_post
canvas.after:
Color:
rgba: 0,1,0,1
Line:
width: dp(1.6)
rounded_rectangle:(self.x, self.y, self.width, self.height, dp(5))
BoxLayout:
id: main_new_post
orientation: 'vertical'
padding: '10dp', '16dp'
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
canvas.before:
Color:
rgba: 0, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
AnchorLayout:
size_hint: 1, .05
anchor_x: 'right'
anchor_y: 'center'
Label:
text: 'New Post'
size_hint: None, None
size: '100dp', '30dp'
color: .8, 0, 0, 1
font_size: '16dp'
#pos_hint: {'center_x': 0.8, 'center_y': 0.5}
Label:
size_hint: 1, .035
text: ''
font_size: '1dp'
BoxLayout:
orientation: 'vertical'
padding: '10dp', 0
size_hint: 1, .38
FloatLayout:
TextInput:
id: new_post_input
#disabled: new_post.buttons_disabled
opacity: 1
background_color: 0, 0, 0, 1
foreground_color: 1, 1, 1, 1
background_disable_normal: True
multiline: True
font_size: '15dp'
padding: '10dp', '10dp'
selection_color: (.8, 0, 0, .5)
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
allow_copy: True
#on_focus: new_post.on_focus(self)
canvas.after:
Color:
rgba: 1,1,1,1
Line:
width: dp(1.6)
rounded_rectangle:(self.x, self.y, self.width, self.height, dp(5))
BoxLayout:
orientation: 'vertical'
id: preview_new_post_label
opacity: 0
pos_hint: {'center_x': 0.5, 'center_y': -1}
canvas.before:
Color:
rgba: (.8,.8,.8,1)
RoundedRectangle:
size: self.size
radius: [dp(6),]
pos: self.x, self.y
canvas:
Color:
rgba:0.8,0,0,1
Line:
width: dp(1.6)
rounded_rectangle:(self.x,self.y,self.width,self.height, dp(5))
ScrollView:
always_overscroll: False
bar_color: (0,0,0,0)
Label:
text: ('Someone:\n' + new_post_input.text)
padding: "10dp", "12dp"
size_hint: None, None
height: self.texture_size[1]
width: self.parent.width
font_size: "12dp"
text_size: self.width, None
color: 0,0,0,1
multiline: True
markup: True
BoxLayout:
orientation: 'horizontal'
size_hint: 1, .08
padding: '10dp', 0
AnchorLayout:
anchor_x: 'left'
anchor_y: 'center'
Label:
text: 'Text Modification'
font_size: '12dp'
size_hint: None, None
BoxLayout:
orientation: 'vertical'
padding: '10dp', 0
size_hint: 1, .12
BoxLayout:
orientation: 'horizontal'
#padding: '10dp', 0
canvas.after:
Color:
rgba: 1, 1, 1, 1
Line:
width: 1.6
rounded_rectangle:(self.x, self.y, self.width, self.height, 5)
ScrollView:
GridLayout:
id: container_x
size_hint_x: None
rows: 1
col_default_width: dp(95)
width: self.minimum_width
spacing: dp(7)
Button:
text: "Bold"
font_size: '14dp'
color: 1, 1, 1, 1
background_color: .2, .2, .2, 0
on_press: new_post.make_bold(new_post_input, new_post_input.selection_text)
canvas.before:
Color:
rgba: (.2,.2,.2,0) if self.state=='normal' else (.3,.3,.3,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [dp(6),]
canvas:
Color:
rgba: (1,1,1,1) if self.state=='normal' else (1,1,1,1)
Line:
width: dp(1.2)
rounded_rectangle:(self.x,self.y,self.width,self.height, dp(6))
BoxLayout:
orientation: 'horizontal'
size_hint: 1, .08
#padding: '10dp', 0
AnchorLayout:
anchor_x: 'left'
anchor_y: 'center'
Label:
text: 'Post Category'
font_size: '12dp'
size_hint: None, None
BoxLayout:
orientation: 'vertical'
padding: '10dp', 0
size_hint: 1, .12
BoxLayout:
orientation: 'horizontal'
#padding: '10dp', 0
canvas.after:
Color:
rgba: 1, 1, 1, 1
Line:
width: 1.6
rounded_rectangle:(self.x, self.y, self.width, self.height, 5)
ScrollView:
GridLayout:
id: container_x
size_hint_x: None
rows: 1
col_default_width: dp(95)
width: self.minimum_width
spacing: dp(7)
ToggleButton:
text: "Opinion"
font_size: '14dp'
color: 1, 1, 1, 1
background_color: .2, .2, .2, 0
on_press: new_post.update_catagory(self, 'opinions')
canvas.before:
Color:
rgba: (.2,.2,.2,0) if self.state=='normal' else (.3,.3,.3,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [dp(6),]
canvas:
Color:
rgba: (1,1,1,1) if self.state=='normal' else (1,1,1,1)
Line:
width: dp(1.2)
rounded_rectangle:(self.x,self.y,self.width,self.height, dp(6))
Demo program working: YouTube link
Thank you for any suggestions/solutions :)
Update
It turns out that the selection seems to stop working when the TextInput is within a PageLayout with more than 2 pages in it, (Which it is in my program).
I have created a rough demo program to show the problem and have put it in .py and .kv
You can achieve that by creating a custom TextInput instance and overriding one of its method.
class MyTextInput(TextInput):
selected_text = StringProperty("")
# Use this prop. instead of 'selection_text'.
def cancel_selection(self):
self.selected_text = self.selection_text
super().cancel_selection()
Now use this instance and the new property wherever you need.
In .kv,
FloatLayout:
MyTextInput:
id: new_post_input
.
.
.
Button:
text: "Bold"
font_size: '14dp'
color: 1, 1, 1, 1
background_color: .2, .2, .2, 0
on_press: new_post.make_bold(new_post_input, new_post_input.selected_text)

How to color background of MDLabel properly in kivy app

Trying to color background of MDLabel (Label) in kivy app. But can not adjust width of the Label to be exactly the size of the text (content).
GridLayout:
cols: 1
BoxLayout:
orientation: 'vertical'
size_hint_y: None
padding: dp(7)
# pos_hint: {'top': 1}
background_color: (1,1,0,1)
height: self.minimum_height
canvas.before:
Color:
rgba: self.background_color
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint_y: None
# pos_hint: {'top': 1}
height: self.minimum_height
background_color: (0,1,0,1)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
size: self.size
pos: self.pos
MDLabel:
text: 'Some text'
size_hint_y: None
size: self.texture_size
MDLabel:
id: trying_to_color_background
text: 'Width'
halign: 'right'
size_hint_x: None
size: self.texture_size
getting this
enter image description here
if i try to remove last row of the code "size: self.texture_size". it looks like this
enter image description here
but i want the background to be the size of the text content (size of red border in the image below). if there will be more letters in the text, i want the background to be wider
enter image description here
Set it as,
...
MDLabel:
id: trying_to_color_background
text: 'Width'
halign: 'right'
size_hint: None, None
size: self.texture_size
text_size: None, None
lbl_state = MDLabel(text="state", md_bg_color = [.119, .136, .153, 1])
lbl_state = MDLabel(text="state", theme_text_color = "Custom", md_bg_color = [.119, .136, .153, 1])
from kivy.utils import get_color_from_hex
lbl_state = MDLabel(text="state", theme_text_color = "Custom", md_bg_color = get_color_from_hex("#7dcbb1"))
MDLabel:
id: trying_to_color_background
theme_text_color: "Custom"
md_bg_color = .119, .136, .153, 1
Example for different colors:
0, 0, 0, 1 - dark
1, 1, 1, 1 - white
.7, .7, .7, 1 - gray
1, 0, 0, 1 - red
0, 1, 0, 1 - green
0, 0, 1, 1 - blue

How to change the text on different labels from the same TextInput field?

In my program I have a button that adds a new box. When you press a button in this new box it adds a new box, and so on. In each box I have a label, and I want to be able to change this text from the same textinput field. But I dont want the same text in each box, so I want to select the box, write the text, and then press a button so that the text is passed from the input field to that specific box/label. I have removed everything else from my app, so I will show you a complete code so you can try the program to understand what I mean.
I have tried to use a button on the main widget, but then I dont know how to choose which box that should be updated. I have also tried to use a button in the box (called "R" in the code), but then I only gets an error.
If i use the code that is commented out i get this error:
"AttributeError: 'super' object has no attribute '__getattr__'"
I would really appreciate some help! Thanks a lot.
This is the python file:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
class Home(FloatLayout):
def first(self, *args):
a = box()
self.ids.frame.add_widget(a)
b = a.ids.btn3
b.bind(on_press=self.second)
c = a.ids.btn1
c.bind(on_press=self.textedit)
def second(self, *args):
d = box()
e = d.ids.mains
e.pos_hint={"right": .5, "top": .7}
self.ids.frame.add_widget(d)
f = d.ids.btn3
f.bind(on_press=self.third)
g = d.ids.btn1
g.bind(on_press=self.textedit)
def third(self, *args):
h = box()
i = h.ids.mains
i.pos_hint = {"right": .3, "top": .9}
self.ids.frame.add_widget(h)
j = h.ids.btn1
j.bind(on_press=self.textedit)
def textedit(self, *args):
print("Hello")
#k = self.ids.tinput.text
#l = self.ids.lab
#l.text = k
def textedit2(self, *args):
print("hei")
#This is the submitbutton on the main widget
class HiApp(App):
def build(self):
return Home()
class box(FloatLayout):
pass
if __name__ == "__main__":
HiApp().run()
This is the .kv file
<Home>:
FloatLayout:
id: frame
size_hint_y: 1
pos_hint:{"right":1,"top":1}
canvas.before:
Color:
rgba: (1, 1, 1, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
id: boks
orientation: "vertical"
size_hint_x: .20
size_hint_y: .15
pos_hint:{"right":1,"top":1}
canvas.before:
Color:
rgba: (0, 1, 0, 1)
Rectangle:
size: self.size
pos: self.pos
TextInput:
id: tinput
hint_text: "Frome here"
Button:
id: t_sub
text: "Submit"
on_press: root.textedit2()
Button:
id: start
text: "Start"
font_size: 20
color: 0, 0, 0, 1
background_normal: ''
background_color: .88, .88, .88, 1
size_hint: .1, .1
pos_hint:{"right":.5,"top":.35}
on_press: root.first()
<box>:
BoxLayout:
id: mains
orientation: "vertical"
size_hint_x: .18
size_hint_y: .13
pos_hint:{"right":.3,"top":.5}
canvas.before:
Color:
rgba: (.20, .05, .0, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
id: c1
size_hint_y: .25
pos_hint:{"left":.1,"top":.5}
GridLayout:
rows: 1
cols: 3
padding: 4
spacing: 4
Button:
id: btn1
text: "R"
font_size: 30
color: 0, 0, 0, 1
background_normal: ''
background_color: .88, .88, .88, 1
size_hint: .3, .3
pos_hint:{"left":.5,"top":.5}
on_press:
Button:
id: btn2
text: "-"
font_size: 30
color: 1, 0, 0, 1
background_normal: ''
background_color: .88, .88, .88, 1
size_hint: .3, .3
pos_hint:{"left":.5,"top":.5}
on_press:
Button:
id: btn3
text: "+"
font_size: 30
color: 0, 1, 0, 1
background_normal: ''
background_color: .88, .88, .88, 1
size_hint: .3, .3
pos_hint:{"left":.5,"top":.5}
on_press:
GridLayout:
rows: 1
cols: 2
padding: 4
spacing: 4
Label:
id: lab
text: "Text here"
TextInput:
hint_text: "0"
Problem
I want to write the text in the inputfield with the id: tinput
(upper left corner) and then press the button (R) so that the text
goes from the inputfield to the label.
Solution
The solution to is use the following keywords in kv file:
app - always refers to the instance of your application
root - refers to the base widget/template in the current rule
Snippets - kv file
Button:
id: btn1
text: "R"
font_size: 30
color: 0, 0, 0, 1
background_normal: ''
background_color: .88, .88, .88, 1
size_hint: .3, .3
pos_hint:{"left":.5,"top":.5}
on_press:
lab.text = app.root.ids.tinput.text
Output

Kivy: Can I freely change the position of text within a button? and add another text in the button?

t3.py
#-*- coding: utf-8 -*-
__version__ = "1.0"
import kivy
import os
kivy.require('1.10.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.core.window import Window
Window.size = (540, 960)
class StationTest(Screen):
def __init__(self, **kwargs):
super(StationTest, self).__init__(**kwargs)
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("t3.kv")
class Test2App(App):
def build(self):
return presentation
Test2App().run()
t3.kv
# -*- coding: utf-8 -*-
#:kivy 1.10.0
#:import NoTransition kivy.uix.screenmanager.NoTransition
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
#:import Button kivy.uix.button.Button
ScreenManagement:
transition: SlideTransition(direction='left')
StationTest:
<StationTest>:
name: 'StationTest'
canvas:
Rectangle:
pos: self.pos
size: self.size
source: 'image/background.png' #backgroundimage
header: _header
ScrollView:
FloatLayout:
size_hint_y: None
height: 500
BoxLayout:
id: _header
orientation: 'vertical'
size_hint: 1, 0.10
pos_hint: {'top': 1.0}
anchor: _anchor
canvas:
Color:
rgba: 0.8, 0.6, 0.4, 1.0
Rectangle:
pos: self.pos
size: self.size
Label:
text: "STATION > STATION"
font_size: 40
BoxLayout
id: _anchor
size_hint_y: 0.3
canvas.before:
Color:
rgba: 0.3, 0.5, 0.8, 1.0
Rectangle:
pos: self.pos
size: self.size
Label:
text: "TEST1234"
BoxLayout:
orientation: 'vertical'
#size_hint: 1, 0.35
size: 1,0.35
spacing: 10
pos_hint:{"center_x":0.5,"y":-0.6}
padding: 0, -200, 0, 0
GridLayout:
cols: 1
rows: 10
spacing: 0
padding: [0,100]
on_parent:
for i in range(10): txt = 'abcdef'; self.add_widget(Button(text = txt, text_size=(cm(2), cm(2)), background_color=(255,255,255,1),
pos=self.pos, id=txt, color=(0,0,0,1))) # 0~1.0
i want add '123456' text apart from 'abcdef' in one button. i can code txt = 'abcdef' + '123456' but this is not i wanted. I would like to add the texts in the button and apply the desired options to each text, but it is not easy.
on_parent:
for i in range(10): txt = 'abcdef'; self.add_widget(Button(text = txt, text_size=(cm(2), cm(2)), background_color=(255,255,255,1),
pos=self.pos, id=txt, color=(0,0,0,1))) # 0~1.0
So I have two questions.
1.Can I put two texts that can move independently in one button?
2.Is it possible to set the position of the text freely within the button?
Can I put two texts that can move independently in one button? No, you cannot
Is it possible to set the position of the text freely within the button? No, you cannot
Solution
Create custom button with inheritance of ButtonBehavior and BoxLayout. Inside the BoxLayout, there are three Label widgets.
Snippet
<CustomLabel#Label>:
text_size: root.width, None
size: self.texture_size
valign: 'center'
halign: 'right'
<CustomButton>:
color: 0, 0, 0, 1 # black color text
orientation: 'vertical'
canvas.before:
Rectangle:
size: self.size
pos: self.pos
size_hint: 1, None
height: 60
padding: 5, 5, 5, 5
background_color: [0.50196, 0.50196, 0.50196, 1] if self.state == 'normal' else [0, 1, 1, 1]
AnchorLayout:
canvas.before:
Color:
rgba: [1, 1, 1, 1] if root.background_color is None else root.background_color
Rectangle:
size: self.size
pos: self.pos
AnchorLayout:
anchor_x: 'left'
anchor_y: 'top'
CustomLabel:
text: root.route
color: root.color
halign: 'left'
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
CustomLabel:
text: root.stations
color: root.color
AnchorLayout:
canvas.before:
Color:
rgba: [1, 1, 1, 1] if root.background_color is None else root.background_color
Rectangle:
size: self.size
pos: self.pos
anchor_x: 'right'
anchor_y: 'bottom'
CustomLabel:
text: root.commute
color: root.color
Example
main.py
#-*- coding: utf-8 -*-
__version__ = "1.0"
import os
import kivy
kivy.require('1.11.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
Window.size = (540, 960)
from kivy.uix.button import ButtonBehavior
from kivy.properties import StringProperty
def oopath(ndid, uor):
path = os.path.join(os.path.dirname(__file__), ndid + '.txt')
return path
##############################################################################################################
class StationTest(Screen):
def __init__(self, **kwargs):
super(StationTest, self).__init__(**kwargs)
oo = oopath('TESTTEST', 0)
self.rpandgv(oo)
def rpandgv(self, path):
with open(path) as businfo:
Businfo = []
for line in businfo:
Businfo.append(line.rstrip())
self.businfolist = Businfo
self.lenbil = int(len(Businfo))
self.numberoflist = int(len(Businfo)/3)
def populate_businfo(self, instance):
for x in range(0, self.lenbil, 3):
instance.add_widget(CustomButton(route=self.businfolist[x], stations=self.businfolist[x+1], commute=self.businfolist[x+2]))
class ScreenManagement(ScreenManager):
pass
class CustomButton(ButtonBehavior, BoxLayout):
route = StringProperty('')
stations = StringProperty('')
commute = StringProperty('')
def on_release(self):
print("\troute={0}, stations={1}, commute={2}".format(self.route, self.stations, self.commute))
presentation = Builder.load_file("test.kv")
class Test2App(App):
def build(self):
return presentation
Test2App().run()
test.kv
# -*- coding: utf-8 -*-
#:kivy 1.11.0
#:import NoTransition kivy.uix.screenmanager.NoTransition
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
#:import Button kivy.uix.button.Button
ScreenManagement:
transition: SlideTransition(direction='left')
StationTest:
<StationTest>:
name: 'StationTest'
canvas:
Rectangle:
pos: self.pos
size: self.size
source: 'image/background.png' #backgroundimage
header: _header
ScrollView:
FloatLayout:
size_hint_y: None
height: 500
BoxLayout:
id: _header
orientation: 'vertical'
size_hint: 1, 0.10
pos_hint: {'top': 1.0}
anchor: _anchor
canvas:
Color:
rgba: 0.8, 0.6, 0.4, 1.0
Rectangle:
pos: self.pos
size: self.size
Label:
text: "STATION > STATION"
font_size: 40
BoxLayout
id: _anchor
size_hint_y: 0.3
canvas.before:
Color:
rgba: 0.3, 0.5, 0.8, 1.0
Rectangle:
pos: self.pos
size: self.size
Label:
text: "TEST1234"
BoxLayout:
orientation: 'vertical'
#size_hint: 1, 0.35
size: 1,0.35
spacing: 10
pos_hint:{"center_x":0.5,"y":-0.6}
padding: 0, -200, 0, 0
GridLayout:
cols: 1
rows: 10
spacing: 0
padding: [0,100]
on_parent:
root.populate_businfo(self)
<CustomLabel#Label>:
text_size: root.width, None
size: self.texture_size
valign: 'center'
halign: 'right'
<CustomButton>:
color: 0, 0, 0, 1 # black color text
orientation: 'vertical'
canvas.before:
Rectangle:
size: self.size
pos: self.pos
size_hint: 1, None
height: 60
padding: 5, 5, 5, 5
background_color: [0.50196, 0.50196, 0.50196, 1] if self.state == 'normal' else [0, 1, 1, 1]
AnchorLayout:
canvas.before:
Color:
rgba: [1, 1, 1, 1] if root.background_color is None else root.background_color
Rectangle:
size: self.size
pos: self.pos
AnchorLayout:
anchor_x: 'left'
anchor_y: 'top'
CustomLabel:
text: root.route
color: root.color
halign: 'left'
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
CustomLabel:
text: root.stations
color: root.color
AnchorLayout:
canvas.before:
Color:
rgba: [1, 1, 1, 1] if root.background_color is None else root.background_color
Rectangle:
size: self.size
pos: self.pos
anchor_x: 'right'
anchor_y: 'bottom'
CustomLabel:
text: root.commute
color: root.color
Output

Categories