Getting text input from the user and print it python using kivy - python

I am trying to print an input given by a user but all I get is: < ObjectProperty name=input >
I can't use Text Input in my py because python quits if I try to run a program with it installed. I have tried putting the popup in the 'test' class but it just comes up with a different error.
Any help is appreciated,
Thank you.
Here is my code:
In my py:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.popup import Popup
class MyPopup(Popup):
pass
class Test(Widget):
pass
class TestApp(App):
def build(self):
return Test()
def Process(self):
text = MyPopup.input
print(text)
if __name__ == '__main__':
TestApp().run()
and in my kv:
#:import Factory kivy.factory.Factory
<MyPopup#Popup>
input: text
auto_dismiss: True
size_hint: 0.4, 0.4
TextInput:
id: text
hint_text: 'insert text'
multiline: False
on_text_validate: app.Process()
<Test>:
canvas:
Color:
rgba: 0, 0, 0, 0
Rectangle:
pos: 0, 0
size: self.width, self.height - self.height/6
Color:
rgba: 1, 1, 1, 0.1
Rectangle:
pos: 0, 0
size: self.width/2 + self.width/10, self.height - self.height/6
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: 0, self.height - self.height/6
size: self.width, self.height/6
Button:
id: GL
text: 'In here'
pos: 0 , root.height - root.height/6
on_parent: GLdropdown.dismiss()
on_release: GLdropdown.open(self)
size_hint_y: None
height: root.height/6
width: root.width/7
DropDown:
id: GLdropdown
on_select: btn.text = '{}'.format(args[1])
Button:
id: 'AV'
text: 'press me'
size_hint_y: None
height: 50
on_release: Factory.MyPopup().open()

If you change:
on_text_validate: app.Process()
to:
on_text_validate: app.Process(self.text)
And change the Process() method to:
def Process(self, text):
print(text)
I think it will work as you want.
The problem is that the line:
text = MyPopup.input
makes text a reference to the ObjectProperty of the class MyPopup. What you really want is a reference to the text of the TextInput, which is simply self.text in the TextInput.

Related

Kivy kv. file throws error "Invalid indentation (too many levels)", why?

I'm trying to get this kv. file to run, but it throws the error "Invalid indentation (too many levels)". For the life of me, I don't understand why. Im suspicious that its the way I am nesting the layouts within the kv. file, but I'm not sure. Any help/critique would be appreciated!
.py file:
from kivy.app import App
import tarot
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
class selectCard(BoxLayout):
def __init__(self, *args, **kwargs):
super(selectCard,self).__init__(*args,**kwargs)
self.my_text = "Background.png"
def on_click(self):
if self.my_text == "Background.png":
self.my_text = tarot.read().one()
self.ids.card_image.source = "Cards\\" + self.my_text + ".png"
print(self.my_text)
else:
self.my_text = "Background.png"
self.ids.card_image.source = "Background.png"
print(self.my_text)
class layout(FloatLayout):
pass
class TarotApp(App):
def build(self):
return selectCard()
TarotApp().run()
.kv file:
<layout>
canvas.before:
Color:
rgba: 0, 1, 0, 1
Rectangle:
pos: self.pos
size: self.size
<seletCard>
layout:
Button:
normal: root.my_text
on_release: root.on_click()
background_color: 1,1,1,1
size_hint: (1,1)
pos_hint: {'center_x':.5,'center_y':.5}
Image:
source: root.my_text
id: card_image
pos: self.parent.pos
size: self.parent.size
#background_color: self.parent.background_color
stretch: True
Button:
normal: root.my_text
on_release: root.on_click()
background_color: 1,1,1,1
#size_hint: (1,1)
pos_hint: {'center_x':.5,'center_y':.5}
Image:
source: root.my_text
id: card_image
pos: self.parent.pos
size: self.parent.size
background_color: self.parent.background_color
stretch: True
I don't think this is an indentation problem. Am I referencing something incorrectly?

Add widget dynamically from outside class (error)

I´m learning kivy, and it has passed 3 weeks since i face this problem without encounter a solution, so i hope any of u guys could help me, i would appreciate it.
I have a main file:
from app import MyProgramApp
if __name__ == "__main__":
winapp = MyProgramApp()
winapp.run()
from where i start my app. Then i have a directory called "app", inside there is the following "init.py" file.
from kivy.app import App
from kivy.utils import QueryDict, rgba
from kivy.core.window import Window
from .view import MainWindow
Window.minimum_width = 500
Window.minimum_height = 650
Window.maximize()
class MyProgramApp(App):
colors = QueryDict()
colors.primary = rgba('#2D9CDB')
colors.secondary = rgba('#16213E')
colors.succes = rgba('#1FC98E')
colors.warning = rgba('#F2C94C')
colors.danger = rgba('#E85757')
colors.grey_dark = rgba('#C4C4C4')
colors.grey_light = rgba('#F5F5F5')
colors.black = rgba('#A1A1A1')
colors.white = rgba('#FFFFFF')
def build(self):
return MainWindow()
Same folder app, i have the following "view.py".
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.properties import StringProperty
from kivy.uix.screenmanager import ScreenManager
class MainWindow(BoxLayout):
username = StringProperty("Usuario")
def __init__(self, **kw):
super().__init__(**kw)
def on_press_home(self):
self.ids.scrn_mngr.current = "scrn_home"
class ViewManager(ScreenManager):
def __init__(self, **kw):
super().__init__(**kw)
class NavTab(ToggleButtonBehavior, BoxLayout):
text = StringProperty('')
icon = StringProperty('')
def __init__(self, **kw):
super().__init__(**kw)
and finally for that folder i have "myprogram.kv"
#:kivy 2.1.0
#:import Home views.home.Home
<MainWindow>:
spacing: dp(8)
canvas.before:
Color:
rgba: app.colors.white
Rectangle:
pos: self.pos
size: self.size
# NAVIGATION BAR
BoxLayout:
id: nav_menu
size_hint_x: .2
orientation: "vertical"
size_hint_min_x: dp(100)
# LOGO
BoxLayout:
id: logo_nbox
size_hint_y: .1
size_hint_min_y: dp(70)
padding: dp(16)
AnchorLayout:
anchor_x: "right"
size_hint_x: None
width: dp(52)
halign: "left"
Label:
text: "COMPANY"
halign: "center"
BoxLayout:
orientation: "vertical"
Label:
text: "COMPANY"
halign: "center"
Label:
text: "Phrase"
halign: "center"
# OPTIONS
GridLayout:
id: tabs_box
cols: 1
spacing: dp(4)
size_hint_y: .5
canvas.before:
Color:
rgba: app.colors.grey_dark
Rectangle:
pos: self.pos
size: [self.size[0], dp(1)]
NavTab:
text: "Home"
state: "down"
on_press: root.on_press_home()
# BODY
BoxLayout:
size_hint_x: .8
spacing: dp(8)
orientation: "vertical"
padding: [dp(16), dp(8), dp(12), dp(8)]
canvas.before:
Color:
rgba: app.colors.grey_light
Rectangle:
pos: self.pos
size: self.size
# SCREENS
BoxLayout:
ViewManager:
id: scrn_mngr
<ViewManager>:
Screen:
name: "scrn_home"
Home:
id: home
<NavTab>:
background_normal: ""
background_down: ""
background_color: [0,0,0,0]
group: "tabs"
size_hint_y: None
height: dp(45)
spacing: dp(4)
canvas.before:
Color:
rgba: [0,0,0,0] if self.state == "normal" else rgba("#E1F1FF")
Rectangle:
pos: self.pos
size: self.size
Color:
rgba: [0,0,0,0] if self.state == "normal" else app.colors.primary
Rectangle:
pos: [self.pos[0]+self.size[0]-dp(1), self.pos[1]]
size: [dp(8), self.size[1]]
Label:
halign: "left"
valign: "middle"
text: root.text
color: app.colors.grey_dark if root.state == "normal" else app.colors.primary
Then i got another folder called "views" inside i have another folder called "home", inside home we encounter 3 files "init.py", "home.kv", "home.py". the first one "init.py" is the following.
from .home import Home
then we got "home.kv".
#:kivy 2.1.0
<Home>:
orientation: "vertical"
Label:
size_hint_y: .1
text: "Other"
Button:
size_hint_y: .1
text: "popup"
on_press: root.open_popup()
BoxLayout:
size_hint_y: .8
id: home_box
<SomePopup>:
title: "SOME TITLE"
title_align: "center"
title_color: app.colors.primary
size_hint: .25, .8
size_hint_min_x: dp(200)
pos_hint: {"x": .1, "top": .9}
BoxLayout:
orientation: "vertical"
padding: [dp(0), dp(12), dp(0), dp(12)]
Label:
text: "Some text"
Button:
text: "create buttons on box"
on_press: root.modify_home_box()
and finally and the problem that i´m facing is whit the following file "home.py"
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.app import App
Builder.load_file('views/home/home.kv')
class Home(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def open_popup(self):
Factory.SomePopup().open()
class SomePopup(Popup):
def __init__(self, **kw):
super().__init__(**kw)
def modify_home_box(self):
my_app = App.get_running_app().root
my_box = my_app.ids.home.ids.home_box
custom_button = Button(
text = "something"
)
my_box.add_widget(custom_button)
That i´m trying to do is actually modify "home_box" with is store on ids Home dictionary, i also try with ObjectProperty (but that gives and Attribute Error, since i only could read propertys but doesnt modify it), instance of a new Home class doesnt work... searching for current app in App appear doesnt work since Home is store i think on screenManager...
I need add a button or some widget to "home_box" from outside class "SomePopup". I also drop here a repository on github with the whole code. github_repo
I don't know how to solve my issue, and i try with the resources available here on stack as well other net places... any help would be appreciate.
Just a very complicated path to the widget of interest. In your modify_home_box() method, try replacing:
my_app = App.get_running_app().root
my_box = my_app.ids.home.ids.home_box
with:
my_app = App.get_running_app().root
my_box = my_app.ids.scrn_mngr.ids.home.ids.home_box

Proper way of adding a canvas to a label

I'm posting this because I want to add a canvas behind, inside, on top, I don't know, I want a background for the labels, and I have found out that I need a canvas to do that, but I don't know how to do it. I have been able to add a canvas as a background for a label, but since my app needs to be refreshed and resized I bump into problems that I am not able to fix.
I want to make the canvas so that it has the same size as the labels beside eachother, and I want to be able to remove it like when I remove the labels inside "theLayout".
I believe the problem is in the method "refresh" inside the class "HovedVindu".
If it is possible to not change the whole code and fix it so that a beginner like me is able to understand and modify it, I would appreciate it very much, if it is not possible I will still appreciate any help :)
I used paint 3D to visualize what I want to achieve:
main.py:
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
import kivy.uix.boxlayout
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics import Color, Rectangle, Canvas
Builder.load_file("struktur.kv")
sm = ScreenManager()
produkter = [["Melk", "04.06.2022"], ["Ost", "28.07.2022"], ["Tomat", "27.05.2022"], ["Banan", "02.06.2022"]]
class produktManager(object):
def lagreProdukt(self, navn, dato):
self.navn = navn
self.dato = dato
nyProdukt = [self.navn.text, self.dato.text]
if nyProdukt != ["", ""]:
produkter.insert(0, nyProdukt)
class HovedVindu(Screen):
def nyttProdukt(self):
show_popup()
def Refresh(self):
theLayout = self.ids.theLayout
for i in range(10):
for v in theLayout.children:
theLayout.remove_widget(v)
for i in produkter:
newLabel_navn = theLayout.add_widget(Label(text = i[0]))
newLabel_dato = theLayout.add_widget(Label(text = i[1]))
#with theLayout.canvas:
#(Color(0, 1, 1, .1))
#(Rectangle(size = (self.size), pos_hint = (self.pos)))
class P(FloatLayout):
def leggTilNyttProdukt(self, Navn, Dato):
produktManager().lagreProdukt(Navn, Dato)
Navn.text = ""
Dato.text = ""
class MainApp(App):
def build(self):
sm.add_widget(HovedVindu(name="hoved"))
return sm
def show_popup():
show = P()
popupWindow = Popup(title="Legg til ett nytt produkt", content=show, size_hint=(None,None),size=(400,400), title_align="center")
popupWindow.open()
if __name__ == "__main__":
MainApp().run()
struktur.kv:
#:kivy 2.1.0
#:import RiseInTransition kivy.uix.screenmanager.RiseInTransition
<HovedVindu>:
FloatLayout:
size_hint: 1, .1
pos_hint: {"x": 0, "top": 1}
canvas.before:
Color:
rgba: 1, 1, 1, .8
Rectangle:
pos: self.pos
size: self.size
Button:
text: "+"
size_hint: .15, .8
pos_hint: {"x": .8, "top": .9}
on_release: root.nyttProdukt()
Button:
text: "Refresh"
size_hint: .2, .8
pos_hint: {"x": .2, "top": .9}
on_release:
root.Refresh()
FloatLayout:
size_hint: 1, .9
canvas.before:
Color:
rgba: 0, 0, 0, 0
Rectangle:
pos: self.pos
size: self.size
GridLayout:
id: theLayout
cols: 2
rows: 10
Label:
text: "NAVN"
canvas.before:
Color:
rgba: 1, 0, 0, .2
Rectangle:
pos: self.pos
size: self.size
Label:
text: "DATO"
canvas.before:
Color:
rgba: 1, 0, 0, .2
Rectangle:
pos: self.pos
size: self.size
<P>:
TextInput:
id: navn
hint_text: "Navnet på produktet"
size_hint: .6, .15
pos_hint: {"x": .2, "top": .9}
TextInput:
id: dato
hint_text: "Siste forbruksdag"
size_hint: .6, .15
pos_hint: {"x": .2, "top": .7}
Button:
text: "Legg til produkt"
size_hint: 0.8, 0.2
pos_hint: {"x":0.1, "y":0.1}
on_release: root.leggTilNyttProdukt(navn, dato)
In order to have a label with some background color and use it dynamically you can create a dynamic class inherited from Label. You can also create any desired prop. for advanced usage.
First define a class in .py inherited from Label,
class CustomLabel(Label):
background_color = ListProperty([1, 1, 1, 1])
Now design it using kvlang,
<CustomLabel>:
canvas.before:
Color:
rgba: self.background_color
Rectangle:
pos: self.pos
size: self.size
Now your label is ready to use.
def Refresh(self):
...
for n, i in enumerate(produkter, start = 1):
newLabel_navn = theLayout.add_widget(CustomLabel(text = i[0], background_color = [1, 1/n, 1, 0.5]))
newLabel_dato = theLayout.add_widget(CustomLabel(text = i[1], background_color = [1/n, 1, 1, 0.8]))
...

Kivy Dynamic Classes - multiple objects

I am trying to simplify the code that generates rows with the same content multiple times by using dynamic classes as shown in the simplified example below.
So far so good, code is simpler but I'm trying to find solutions to access from python for example Label in the second row. In my old solution, I have a unique ID for each widget but now buttons and labels are defined as only ones for all rows, and they have the same ID.
Is there any possibility to access them individually?
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
Builder.load_file("test.kv")
class MyLayout(Widget):
pass
class MyNewApp(App):
def build(self):
return MyLayout()
if __name__ == "__main__":
MyNewApp().run()
test.kv
<RowTemplate#GridLayout>:
cols: 2
Label:
id: row_label
text: 'test'
Button:
id: row_button
text: 'button'
<MyLayout>
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
GridLayout:
size: root.width, root.height
cols: 1
canvas.before:
Color:
rgba: 0, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
RowTemplate: #fist row
RowTemplate: #second row
RowTemplate: #third row
from kivy.properties import StringProperty
class RowTemplate(GridLayout):
button_text = StringProperty('')
label_text = StringProperty('')
test.kv
<RowTemplate>:
cols: 2
Label:
id: row_label
text: root.label_text
Button:
id: row_button
text: root.button_text
Now you can change text dynaminally as bellow.
<MyLayout>:
RowTemplate:
label_text: 'label one'
button_text: 'button one'
RowTemplate:
label_text: 'label two'
button_text: 'button two'

Increment, Decrement, and clear with buttons kivy

I'm a beginner so please excuse the simplistic question. I'm trying to create a control screen that displays a count. Essentially I want it to get a low signal on one of the GPIO's and advance one integer. I also want the ability to edit the count with "+", "-", and "clear" buttons. This is one of the first bits of code I've ever written so I may be way off base here! Here is the code for the .py:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
import RPi.GPIO as GPIO
startPin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(startPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
class InputButton(Button):
def update(self, dt):
if GPIO.input(startPin) == True:
self.ids.textbox.text +=1
class MainWidget(FloatLayout):
def adv_callback(self, text):
self.ids.textbox.text += 1
def fall_callback(self, text):
self.ids.textbox.text -= 1
def clear_callback(self, text):
self.ids.textbox.text = 0
class MainApp(App):
'''docstring for MainApp'''
def build(self):
return MainWidget()
if __name__=="__main__":
MainApp().run()
and the .kv
# File name main.py
<MainWidget>:
canvas.before:
Color:
rgba: .95, .95, 1, .7
Rectangle:
pos: self.pos
size: self.size
Button:
id: clear
text: 'Clear'
font_size: '50sp'
pos: (650, 0)
size_hint: .2, .3
on_press: root.clear_callback(self.text)
Button:
id: add
text: '+'
font_size: '50sp'
pos: (0, 142)
size_hint: .2, .3
on_press: root.adv_callback(self.text)
Button:
id: less
text: '-'
font_size: '50sp'
pos: (0, 0)
size_hint: .2, .3
on_press: root.fall_callback(self.text)
AsyncImage:
source: '/home/sysop/Pictures/Source_Files_Pocono_logo_on_White_Bg.gif'
size_hint: .5, .3
pos: (200, 285)
TextInput:
id: textbox
multiline: False
readonly: True
size_hint: .5, .3
font_size: '80sp'
pos: (325, 0)
ActionBar:
pos: (0, 432)
ActionView:
ActionPrevious:
title: ""
with_previous: False
ActionOverflow:
ActionButton:
text: "Shutdown"
on_press: app.open_settings()

Categories

Resources