I have all the widgets sized and positioned relative to one another. If I add a "Label:" to the bottom of the kv code it will move everything up to the top. But that can't be the "right" way to do it. What am I missing?
import kivy
kivy.require('1.9.0')
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
<Controller>:
BoxLayout:
orientation: 'vertical'
padding: 20
spacing: 20
TextInput:
hint_text: 'Feed Name'
multiline: False
size_hint: (0.75, None)
height: 30
pos_hint: {'center_x': 0.5}
TextInput:
hint_text: 'Feed URL'
multiline: True
size_hint: (0.75, None)
height: 68
pos_hint: {'center_x': 0.5}
Button:
text: 'Add Feed'
padding: (10, 10)
height: 30
size_hint: (None, None)
pos_hint: {'center_x': 0.5}
''')
class Controller(BoxLayout):
pass
class PodcastApp(App):
def build(self):
return Controller(info='Hello world')
if __name__ == '__main__':
PodcastApp().run()
From the BoxLayout docs:
padding Added in 1.0.0 Padding between layout box and children:
[padding_left, padding_top, padding_right, padding_bottom].
padding also accepts a two argument form [padding_horizontal,
padding_vertical] and a one argument form [padding].
Changed in version 1.7.0: Replaced NumericProperty with
VariableListProperty.
padding is a VariableListProperty and defaults to [0, 0, 0, 0].
Try adding a padding to the bottom of the boxlayout if you want it's children to get pushed toward the top.
for instance giving the padding a value of
[20, 20, 20, 'new bottom padding here']
Related
My problem is when I want to display the value given by the user in the Text input text field.
When I want to get the text value from the input I get an empty value and I cannot display anything in the label field .
Here is my code :
The kv file :
MainGridLayout:
<MainGridLayout>:
cols: 1
rows: 2
BoxLayout:
orientation: 'vertical'
TextInput:
id: my_text_input
text: root.text_input_1
hint_text :'Operations'
multiline:False
pos_hint: {'center_x': 0.5, 'center_y': 0.705}
size_hint: 0.95, 0.5
font_size: '30dp'
Label:
text: root.Display_text
font_size: '45dp'
StackLayout:
Button:
text:"+"
spacing: .2, .2
size: 85, 85
size_hint: None, None
on_press: root.on_button_plus()
The py file :
from kivy.app import App
from kivy.properties import StringProperty
from kivy.uix.gridlayout import GridLayout
# different layouts:
class MainGridLayout(GridLayout):
text_input_1 = StringProperty()
Display_text = StringProperty()
def on_button_plus(self):
print(f'{self.text_input_1}')
# run application:
class CalculatorApp(App):
pass
CalculatorApp().run()
I have created a function in MainGridLayout, on_new_text, that takes as a parameter a TextInput and updates text_input_1 with its value.
In the kv file I have set the on_text property of the TextInput to the on_new_text function and gave the TextInput as a parameter. Every time you modify the text input, the on_new_text function will be called, modifying the text_input_1 property.
You can find more properties like on_text in the kivy documentation.
The kv file:
MainGridLayout:
<MainGridLayout>:
cols: 1
rows: 2
BoxLayout:
orientation: 'vertical'
TextInput:
id: my_text_input
hint_text :'Operations'
multiline:False
pos_hint: {'center_x': 0.5, 'center_y': 0.705}
size_hint: 0.95, 0.5
font_size: '30dp'
on_text: root.on_new_text(self)
Label:
text: root.Display_text
font_size: '45dp'
StackLayout:
Button:
text:"+"
spacing: .2, .2
size: 85, 85
size_hint: None, None
on_press: root.on_button_plus()
The py file:
from kivy.app import App
from kivy.properties import StringProperty
from kivy.uix.gridlayout import GridLayout
# different layouts:
class MainGridLayout(GridLayout):
text_input_1 = StringProperty()
Display_text = StringProperty()
def on_new_text(self, text_input):
self.text_input_1 = text_input.text
def on_button_plus(self):
print(f'{self.text_input_1}')
class CalculatorApp(App):
pass
CalculatorApp().run()
Actually, you don't need the variables text_input_1 and Display_text. To display the text from the my_text_input on the label you can add text: my_text_input.text instead of text: root.Display_text. Now, when the text of my_text_input changes, the label's text will change automatically and you don't need any functions. In on_button_plus() method you can do the same and print my_text_input's text using its text property (from all MainGridLayout's ids you take only my_text_input and print its text). The line text: root.text_input_1 unnecessary, too.
Here is my editted version of your code:
The .py file
from kivy.app import App
from kivy.properties import StringProperty
from kivy.uix.gridlayout import GridLayout
class MainGridLayout(GridLayout):
def on_button_plus(self):
print(f'{self.ids.my_text_input.text}')
class CalculatorApp(App):
pass
CalculatorApp().run()
The .kv file
MainGridLayout:
<MainGridLayout>:
cols: 1
rows: 2
BoxLayout:
orientation: 'vertical'
TextInput:
id: my_text_input
hint_text :'Operations'
multiline:False
pos_hint: {'center_x': 0.5, 'center_y': 0.705}
size_hint: 0.95, 0.5
font_size: '30dp'
Label:
text: my_text_input.text # change the text automatically
font_size: '45dp'
StackLayout:
Button:
text:"+"
spacing: .2, .2
size: 85, 85
size_hint: None, None
on_press: root.on_button_plus()
I'm trying to make a simple application that uses buttons to cycle through different strings with a label, but how would one get the strings from the .py file to the KV string?
For example, I want it to say '[x_string]' in the middle of the screen. When the user presses a button (arrow facing right), it goes to '[y_string]' instead. When the user presses the other button (arrow facing left), it goes back to '[x_string]', etc.
Here is the code I have so far.
from PyDictionary import PyDictionary
from kivy.metrics import dp
from kivy.properties import StringProperty
from kivymd.uix.list import OneLineIconListItem
from kivymd.uix.menu import MDDropdownMenu
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.toolbar import MDToolbar
from kivy.core.window import Window
from kivymd.uix.dialog import MDDialog
from kivymd.uix.button import MDFlatButton
from kivymd.uix.swiper import MDSwiper
from kivymd.uix.label import MDLabel
from pathlib import Path
KV = '''
ScreenManager:
Screen1:
<Screen1>:
name: 'screen'
MDScreen:
name: 'screen'
MDToolbar:
title: 'Test App'
elevation: 20
pos_hint: {'top': 1}
md_bg_color: (1, 1, 1, 1)
specific_text_color: (76/255, 76/255, 77/255, 1)
right_action_items: [["information"],["home"]]
FloatLayout:
# Left Arrow
Button:
background_normal: 'buttonsNormal/chevron_arrow_left.png'
background_down: 'buttonsDown/chevron_arrow_left_down.png'
size_hint: (0.06, 0.16)
pos_hint: {'center_x': 0.06, 'center_y': 0.445}
border: [0, 0, 0, 0]
# Right Arrow
Button:
background_normal: 'buttonsNormal/chevron_arrow_right.png'
background_down: 'buttonsDown/chevron_arrow_right_down.png'
size_hint: (0.06, 0.16)
pos_hint: {'center_x': 0.94, 'center_y': 0.445}
border: [0, 0, 0, 0]
'''
Window.size = (1280, 720)
class Screen1(Screen):
def build(self):
MDLabel(
text = 'Raise your arm.',
font_size = dp(56),
halign = 'center'
)
class MainApp(MDApp):
dialog = None
def build(self):
sm = ScreenManager()
sm.add_widget(Screen1(name = 'follow_screen'))
return Builder.load_string(KV)
MainApp().run()
I am leaving out about 800 lines of completely unrelated code, so that's why there are so many imported modules as the top.
Thank you!
You can add a Label to the Screen1 kv:
Label:
text: root.text
size_hint: 0.25, 0.25
color: 0,0,0,1
size: self.texture_size
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
The text for this Label is set to root.text, which should be a StringProperty in the Screen1 class:
class Screen1(Screen):
text = StringProperty('x_string')
Then, you can adjust the value of the StringProperty Like this:
# Left Arrow
Button:
background_normal: 'buttonsNormal/chevron_arrow_left.png'
background_down: 'buttonsDown/chevron_arrow_left_down.png'
size_hint: (0.06, 0.16)
pos_hint: {'center_x': 0.06, 'center_y': 0.445}
border: [0, 0, 0, 0]
on_press:
root.text = 'x_string'
# Right Arrow
Button:
background_normal: 'buttonsNormal/chevron_arrow_right.png'
background_down: 'buttonsDown/chevron_arrow_right_down.png'
size_hint: (0.06, 0.16)
pos_hint: {'center_x': 0.94, 'center_y': 0.445}
border: [0, 0, 0, 0]
on_press:
root.text = 'y_string'
I want to make a 2 Slide Carousel with auto scrolling in KivyMD with Python. On Startup, the App starts from the The first Slide of Carousel and it should be changed to 2nd slide after 3 seconds.
Here is my Code
.kv
<WelcomeScreen>:
MDFloatLayout:
md_bg_color : 1, 1, 1, 1
Carousel:
id: caraousel
on_current_slide: app.current_slide(self.index)
MDFloatLayout:
Image:
source: "Assets/1.png"
pos_hint: {"center_x": .5, "center_y": .6}
size_hint: .3, .3
MDLabel:
text: "Slide 1"
pos_hint: {"center_y": .087}
halign: "center"
font_name: "Poppins-Light"
font_size: "14sp"
color: rgba(135, 143, 158, 200)
MDFloatLayout:
Image:
source: "Assets/2.jpg"
pos_hint: {"center_x": .5, "center_y": .7}
size_hint: .8, .8
MDLabel:
text: "Slide 2"
pos_hint: {"center_y": .47}
halign: "center"
font_name: "Poppins-Regular"
font_size: "25px"
color: rgba(1, 3, 23, 225)
.py
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen,ScreenManager, NoTransition
from kivy.utils import rgba
from kivy.core.window import Window
from kivy.core.text import LabelBase
from kivy.clock import Clock
Window.size = (310, 580)
class WelcomeScreen(Screen):
pass
class AppApp (MDApp):
def build(self):
return Builder.load_file('app.kv')
def current_slide(self, index):
pass
AppApp().run()
Anyone can help me with this Issue? Thanks in Advance.
You can use method Clock.schedule_interval to perform automatic loading of sliders. Trigger that action from anywhere in your code, for example to make it happen from the very beginning, trigger it from the method on_start of class app as,
app.kv file.
<WelcomeScreen>:
MDFloatLayout:
md_bg_color : 1, 1, 1, 1
Carousel:
id: caraousel
on_current_slide: app.current_slide(self.index)
MDFloatLayout:
Image:
source: "Assets/1.png"
pos_hint: {"center_x": .5, "center_y": .6}
size_hint: .3, .3
MDLabel:
text: "Slide 1"
pos_hint: {"center_y": .087}
halign: "center"
# font_name: "Poppins-Light"
font_size: "14sp"
color: rgba(135, 143, 158, 200)
MDFloatLayout:
Image:
source: "Assets/2.jpg"
pos_hint: {"center_x": .5, "center_y": .7}
size_hint: .8, .8
MDLabel:
text: "Slide 2"
pos_hint: {"center_y": .47}
halign: "center"
# font_name: "Poppins-Regular"
font_size: "25px"
color: rgba(1, 3, 23, 225)
main.py file.
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen,ScreenManager, NoTransition
from kivy.utils import rgba
from kivy.core.window import Window
from kivy.core.text import LabelBase
from kivy.clock import Clock
Window.size = (310, 580)
class WelcomeScreen(Screen):
pass
class AppApp(MDApp):
def build(self):
Builder.load_file('app.kv')
return WelcomeScreen()
def on_start(self):
# Access the carousel.
carousel = self.root.ids.caraousel
# Set infinite looping (optional).
carousel.loop = True
# Schedule after every 3 seconds.
Clock.schedule_interval(carousel.load_next, 3.0)
def current_slide(self, index):
pass
AppApp().run()
Update:
Try avoiding the App's instance name as AppApp and related .kv file as app.kv simultaneously, that might cause problems during auto .kv loading. However loading the file explicitly and then returning the root from method build (or declaring in .kv file) should work.
I'm trying to have kivy select the text of a TextInput widget on focus but when I try it seems to select it when it unfocuses and retains the selection. Any ideas how I can select it on focus and on unfocus deselect? I've attached my code below if someone wants to have a play around.
kv file:
<TextInput>:
size_hint: 0.9, 0.5
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
multiline: False
<Button>:
text: "Press Me"
size_hint: (0.1, 0.5)
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
<MainLayout>:
canvas.before:
Color:
rgba: 0.15, 0.15, 0.16, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
padding: 10
BoxLayout:
padding: 10
TextInput:
text: "Directory"
Button:
text: "Browse"
on_press: root.browse_btn()
BoxLayout:
padding: 10
TextInput:
text: "Prefix"
on_focus: self.select_all()
TextInput:
text: "File"
on_focus: self.select_all()
TextInput:
text: "Suffix"
on_focus: self.select_all()
BoxLayout:
padding: 10
Button:
id: button_one
text: "Confirm"
on_press: root.confirm_btn()
Button:
text: "Cancel"
on_press: root.cancel_btn()
python file:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivy.config import Config
Config.set('graphics', 'resizable', 0)
class MainLayout(BoxLayout):
button_id = ObjectProperty(None)
def browse_btn(self):
print("Hey")
def confirm_btn(self):
print("Confirm")
def cancel_btn(self):
print("Cancel")
class BatchRenameApp(App):
def build(self):
self.title = "Batch File Rename"
Window.size = (750, 250)
return MainLayout()
if __name__ == '__main__':
app = BatchRenameApp()
app.run()
Well hidden in the TextInput documentation:
Selection is cancelled when TextInput is focused. If you need to show
selection when TextInput is focused, you should delay (use
Clock.schedule) the call to the functions for selecting text
(select_all, select_text).
So, in your kv, start by importing Clock:
#: import Clock kivy.clock.Clock
Then you can use it in a TextInput rule:
TextInput:
text: "Prefix"
on_focus: Clock.schedule_once(lambda dt: self.select_all()) if self.focus else None
The if self.focus makes sure the select_all only happens when the TextInput gains focus.
I'm using the Kivy library for the first time and I'm trying to develop a simple UI with a TabbedPanel. I would set the size (x) of each tab (in the code TabbedPanelItem) to fit at the entire TabbedPanel's width but if I use height or size_hint in the .kv file, seems they doesn't work.
Here my kv code:
#:import sm kivy.uix.screenmanager
ScreenManagement:
transition: sm.FadeTransition()
SecondScreen:
<SecondScreen>:
tabba: tabba
name: 'second'
FloatLayout:
background_color: (255, 255, 255, 1.0)
BoxLayout:
orientation: 'vertical'
size_hint: 1, 0.10
pos_hint: {'top': 1.0}
canvas:
Color:
rgba: (0.98, 0.4, 0, 1.0)
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'MyApp'
font_size: 30
size: self.texture_size
BoxLayout:
orientation: 'vertical'
size_hint: 1, 0.90
Tabba:
id: tabba
BoxLayout:
orientation: 'vertical'
size_hint: 1, 0.10
pos_hint: {'bottom': 1.0}
Button:
background_color: (80, 1, 0, 1.0)
text: 'Do nop'
font_size: 25
<Tabba>:
do_default_tab: False
background_color: (255, 255, 255, 1.0)
# I would these three tabs' width filling the entire TabbedPanel's width
TabbedPanelItem:
text: 'First_Tab'
Tabs:
TabbedPanelItem:
text: 'Second_Tab'
Tabs:
TabbedPanelItem:
text: 'Third_Tab'
Tabs:
<Tabs>:
grid: grid
ScrollView:
do_scroll_y: True
do_scroll_x: False
size_hint: (1, None)
height: root.height
GridLayout:
id: grid
cols: 1
spacing: 10
padding: 10
size_hint_y: None
height: 2500
Here my Python code:
# coding=utf-8
__author__ = 'drakenden'
__version__ = '0.1'
import kivy
kivy.require('1.9.0') # replace with your current kivy version !
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.properties import StringProperty, ObjectProperty,NumericProperty
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.utils import platform
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
class Tabs(ScrollView):
def __init__(self, **kwargs):
super(Tabs, self).__init__(**kwargs)
class Tabba(TabbedPanel):
pass
class SecondScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("layout2.kv")
class MyApp(App):
def build(self):
return presentation
MyApp().run()
I've read about using a StripLayout inside the TabbedPanel but I don't know if is a good solution and how to apply it correctly. Any suggestions?
I have experimented a bit with your code and after reading the TabbedPanel Docs i found out that tab_width specifies the width of the tab header (as tab_height is for the height). To use it in your kivy file you have to add the following line:
<Tabba>:
do_default_tab: False
tab_width: self.parent.width / 3
background_color: (255, 0, 255, 1.0)
# I would these three tabs' width filling the entire TabbedPanel's width
TabbedPanelItem:
.
.
.
the rest of your kivy file
What we added in this line is that each tab will be the 1/3 of it's parent width.
This even works for fewer or more tabs than 3. If you add more tabs, a horizonal scroll bar will be added to scroll through the extra tabs.
I hope I was helpful.