Changing position of a Label in Kivy - python

i'm new in kivy programming and while it seems that there is a lot of documentation about this problem online, i don't seem to understand any of it so i hope you could help.
I have 4 Buttons and a label, by pressing the buttons, i'm hoping to move the label in that direction.
I have two variables pX and pY which are the label's position and want it to update its position each time these two are updated.
Thanks in advance.
// main.py
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle, Color
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.floatlayout import FloatLayout
Window.size = (900, 600)
Config.set('graphics', 'resizable', True)
class FloatLayout(FloatLayout):
pX = 0.6
pY = 0.1
class FenetreApp(App):
def build(self):
return FloatLayout()
FenetreApp().run()
//fenetre.kv
<Button>:
size_hint: 0.1, 0.1
background_color: 0.1, 0.5, 0.6, 1
<Label>:
size_hint: 0.1, 0.1
background_color: 1, 0, 0, 1
canvas.before:
Color:
rgb: 0.1, 0.6, 0
Rectangle:
pos: self.pos
size: self.size
<FloatLayout>:
Button:
text: "Up"
pos_hint: {"x":0.8, "top":1}
on_press: root.pY= root.pY +0.1
Button:
text: "Down"
pos_hint: {"x":0.8, "top":0.8}
on_press: root.pY= root.pY -0.1
Button:
text: "Left"
pos_hint: {"x":0.7, "top":0.9}
on_press: root.pX= root.pX -0.1
Button:
text: "Right"
pos_hint: {"x":0.9, "top":0.9}
on_press: root.pX= root.pX +0.1
Label:
name: "L1"
text: "I wanna move"
pos_hint: {"x":root.pY, "top":root.pY} ```

You need to use NumericProperty for numeric values.Otherwise, kivy doesn't update its own childrens positions, texts and other stuffs.But if you don't want to use'em, check this code. I hope its clean to understand how it works:
main.py:
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
Window.size = (900, 600)
kv = Builder.load_string('''
FloatLayout:
pY: .5
pX: .5
Button:
size_hint:.1,.1
background_color: 0.1, 0.5, 0.6, 1
text: "Up"
pos_hint: {"x":0.8, "y":.8}
on_press: self.parent.pY+=.1
Button:
size_hint:.1,.1
background_color: 0.1, 0.5, 0.6, 1
text: "Down"
pos_hint: {"x":0.8, "top":0.8}
on_press: self.parent.pY-=.1
Button:
size_hint:.1,.1
background_color: 0.1, 0.5, 0.6, 1
text: "Left"
pos_hint: {"x":0.7, "top":0.9}
on_press: self.parent.pX-= .1
Button:
size_hint:.1,.1
background_color: 0.1, 0.5, 0.6, 1
text: "Right"
pos_hint: {"x":0.9, "top":0.9}
on_press: self.parent.pX+=.1
Label:
size_hint: .1,.1
text: "I like to moving moving"
pos_hint: {"x":self.parent.pX, "top":self.parent.pY}
''')
class sahm(App):
def build(self):
return kv
if __name__ == '__main__':
sahm().run()

Related

How to integrate elements from KV to Python?

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'

My two screens overlap but only if the popup has been activated

For my very first Kivy project I want to create a basic app that will store my passwords. If you happen to get the access code wrong, a popup will appear that says "Incorrect Password". Whenever I put the password in correctly first try the transitions work with no issues, but if the password is ever wrong and the popup appears, any subsequent attempts will result in the two pages overlapping.
main.py:
import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.floatlayout import FloatLayout
class PassWindow(Screen):
pass
class MainWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class PassPopup(FloatLayout):
pass
def openPopup():
show = PassPopup()
global popupWin
popupWin = Popup(title="Error", content=show, size_hint=(None, None), size=(400, 400))
popupWin.open()
def closePopup():
popupWin.dismiss()
kv = Builder.load_file("my.kv")
class MyApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyApp().run()
my.kv:
#:import openPopup main.openPopup
#:import closePopup main.closePopup
WindowManager:
PassWindow:
MainWindow:
<Button>:
font_size: 30
color: 0.33, 0, 0.51, 1
<Label>:
color: 1, 1, 1, 1
<PassWindow>:
name: "passWin"
id: passWin
Label:
text: "Password Storage"
pos_hint: {"top": 1}
font_size: 50
size_hint: 1, 0.2
Label:
text: "Please Input Code to Access"
pos_hint: {"top": .8}
font_size: 50
size_hint: 1, 0.2
TextInput:
id: codeInput
multiline: False
password: True
font_size: 55
size_hint: 0.6, 0.2
pos_hint: {"x": .2, "top": .6}
Button:
text: "Submit"
size_hint: 0.5, 0.2
pos_hint: {"x": .25, "top": .35}
on_release:
app.root.current = "mainWin" if codeInput.text == "1234" else openPopup()
app.root.transition.direction = "left"
codeInput.text = ""
<PassPopup>:
Label:
text: "Incorrect Password"
size_hint: 0.6, 0.2
pos_hint: {"x": 0.2, "top": 0.8}
font_size: 30
Button:
text: "Close"
size_hint: 0.8, 0.2
pos_hint: {"x": 0.1, "top": 0.3}
on_release:
closePopup()
<MainWindow>:
name: "mainWin"
Button:
text: "Exit"
size_hint: 1, 0.2
on_release:
app.root.current = "passWin"
root.manager.transition.direction = "right"
The logic in your on_release: of the Submit Button is incorrect. The line:
app.root.current = "mainWin" if codeInput.text == "1234" else openPopup()
sets the current screen to "mainWin" if the password provided is "1234", otherwise, it sets the current screen to the return value of openPopup() (which is None). I suspect that is the cause of the strange behavior. To fix that, use the following for the on_release:
on_release:
if codeInput.text == "1234": app.root.current = "mainWin"
else: openPopup()
app.root.transition.direction = "left"
codeInput.text = ""
See the documentation.

Reset previous screen upon changing screen or clicking on a button

For my game, I would like to to reset a screen when the user changes screen.
I have tried many things such as using the Clock and making a update function, but it never really work. The layout does not change even though I explicitly change it in python.
For example, if I have button that becomes disabled upon release, when I change screen, it should not be disabled anymore This something that has been on my mind for a long time and don't quite get it.
I have three small files for this main.py, screen_manager.kv and main.kv. Sorry for this noob question
main.py
from kivy.app import App
from kivy.clock import Clock
from kivy.config import Config
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.widget import Widget
# Setup the window
Config.set('graphics', 'resizable', False)
width = 550
height = 550
Window.size = (width, height)
class OptionWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class Quiz(Widget):
def __init__(self, **kwargs):
super(Quiz, self).__init__(**kwargs)
def update(self, dt):
pass
kv = Builder.load_file('screen_manager.kv')
class Application(App):
CATEGORY = ''
def build(self):
game = Quiz()
Clock.schedule_interval(game.update, 1.0 / 60.0)
return kv
if __name__ == '__main__':
Application().run()
screen_manager.kv
# File name: screen_manager.kv
#:include main.kv
WindowManager:
OptionWindow:
SecondWindow:
<OptionWindow>:
name: 'first'
Button:
text: "Reset SecondWindow"
on_release:
app.root.current = 'second'
root.manager.transition.direction = "right"
<SecondWindow>:
name: 'second'
Quiz:
FloatLayout:
size: root.width, root.height
pos: 0, 0
Button:
text: "Go back"
pos_hint: {'x': 0.4, 'y': 0.2}
size_hint: 0.6, 0.6
on_release:
app.root.current = 'first'
root.manager.transition.direction = "right"
main.kv
<Quiz>:
FloatLayout:
id: thelayout
size: root.width, root.height
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Button:
text: 'press me'
pos_hint: {'x': 0.0, 'y': 0.2}
size_hint: 0.3, 0.3
on_release: self.disabled = True
Thanks for you help
Your code provides for disabling the Button, but there is nothing in your code to re-enable it. Once a Button is disabled, it stays that way until something changes changes it. You can add something to your SecondWindow to re-enable the button every time the SecondWindow is displayed. You can use on_enter or on_pre_enter to trigger something to happen whenever that Screen is displayed. like this:
<SecondWindow>:
name: 'second'
on_pre_enter: quiz.ids.butt.disabled = False
Quiz:
id: quiz
FloatLayout:
size: root.width, root.height
pos: 0, 0
Button:
text: "Go back"
pos_hint: {'x': 0.4, 'y': 0.2}
size_hint: 0.6, 0.6
on_release:
app.root.current = 'first'
root.manager.transition.direction = "right"
Note the added id for the Quiz and the added on_pre_enter:. Also needed is a way to reference the Button. I have done that by adding an id to that Button:
<Quiz>:
FloatLayout:
id: thelayout
size: root.width, root.height
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Button:
id: butt
text: 'press me'
pos_hint: {'x': 0.0, 'y': 0.2}
size_hint: 0.3, 0.3
on_release: self.disabled = True
Now, everytime before the SecondWindow is displayed, the on_pre_enter: is triggered, and the `Button`` is re-enabled.

Kivy Selection on Focus

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.

How to remove popup title in kivy

I've been wondering if there is a way to remove the title bar of a popup window:
From this
To this
Thanks in advance!
Edit: Code reference for future use:
<MyPopup#Popup>:
size_hint: None, None
size: 300, 200
title: 'Close'
title_color: 0.7, 0, 0, 0.9
separator_color: 0.4, 0.4, 0.4, 1
title_align: 'center'
BoxLayout:
orientation: 'vertical'
padding: 5, 5, 5, 5
cols: 2
Label:
color: 0.7, 0, 0, 0.9
center_x: root.center_x
center_y: root.center_y
text: 'Are you sure you want to exit?'
BoxLayout:
size_hint: 1, 0.6
Button:
color: 0.7, 0, 0, 0.9
background_color: 0.4, 0.4, 0.4, 0.05
text: 'Yes'
on_release: exit()
Button:
color: 0.7, 0, 0, 0.9
background_color: 0.4, 0.4, 0.4, 0.05
text: 'No'
on_release: root.dismiss()
Use a ModalView instead. This is the base class for popup-style behaviour, Popup is a ModalView with the title added.
You only need to set title property to "" and separator_height property to 0:
Example:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.lang import Builder
Builder.load_string("""
<NoTitleDialog>:
title: "" # <<<<<<<<
separator_height: 0 # <<<<<<<<
size_hint: None, None
size: 400, 200
BoxLayout:
orientation: "vertical"
Label:
text: "Are you sure you want to exit?"
BoxLayout:
size_hint_y: 0.3
Button:
text: "Yes"
Button:
text: "No"
""")
class MainWindow(BoxLayout):
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
self.dialog = NoTitleDialog()
self.dialog.open()
class NoTitleDialog(Popup):
pass
class Example(App):
def build(self):
return MainWindow()
if __name__ == '__main__':
Example().run()

Categories