How to make an input dialog box in kivy? - python

I have made an input dialog box in kivy. But I'm not sure if this is a correct format or correct code or correct way to code. I tried to display an error message itself in the popup below the button. It works while the input is empty, after input, also it's showing the error.
Can anyone help me to do it in a correct way?
Builder.load_string("""
<Main>:
Button:
text: 'Click'
on_press: root.callit()
<design>:
orientation: 'vertical'
cols:2
pos: self.pos
size: root.size
Label:
text: 'Enter Value'
TextInput:
id: val
multiline: False
hint_text:'Age'
input_filter: 'int'
Button:
text: 'Enter'
background_color: 255,0,0,0.9
on_press: root.enter()
Button:
text: 'Cancel'
background_color: 0,1,255,0.7
on_press: root.cancel()
#Label:
# id: er
# foreground_color: [1,250,100,1]
# text: 'Error'
""")
class design(GridLayout):
def __init__(self,**kwargs):
super(design,self).__init__(**kwargs)
#cancel=ObjectProperty(None)
self.er=Label(text='Please enter some input!')
def enter(self):
if self.ids.val.text=='':
print "Enter text"
#self.add_widget(self.er)#Label(text='Please enter some input!',width=200))
#time.sleep(10000)
#self.remove_widget(self.er)
#self.ids.er.text='Please enter some input!'
#self.ids.val.hint_text='Please enter input!'
else:
print self.ids.val.text
#self.ids.val.hint_text='Please enter input!'
self.ids.val.text=''
self.cancel()
def cancel(self):
obj=OpenDialog()
obj.call_pops(1)
class Main(BoxLayout):
pass
def callit(self):
obj=OpenDialog()
obj.call_pops(0)
class OpenDialog(Popup):
global popup
cont=design()
popup=Popup(title='InputDialog',content=cont,size_hint=(None, None), size=(400, 150),auto_dismiss=False)
def call_pops(self,val):
if val==1:
self.close_pops()
elif val==0:
popup.open()
def close_pops(self):
popup.dismiss()
class SriPop(App):
def build(self):
return Main()
if __name__ == '__main__':
SriPop().run()

You need to use the on_text event so that when a number is entered the label stops showing the error. For example:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.properties import NumericProperty, StringProperty, ObjectProperty
from kivy.lang import Builder
Builder.load_string("""
<Main>:
BoxLayout:
orientation: "vertical"
Button:
text: 'Click'
on_press: root.callit()
Label:
id: age_lab
size_hint_y: 0.1
text: root.str_age
<OpenDialog>:
title: 'InputDialog'
size_hint: None, None
size: 400, 120
auto_dismiss: False
text: input.text
lb_error: er
BoxLayout:
orientation: 'vertical'
pos: self.pos
size: root.size
BoxLayout:
orientation: 'horizontal'
Label:
text: 'Enter Value'
TextInput:
id: input
multiline: False
hint_text:'Age'
input_filter: 'int'
on_text: root.error = ''
BoxLayout:
orientation: 'horizontal'
Button:
text: 'Enter'
background_color: 255,0,0,0.9
on_press: root._enter()
Button:
text: 'Cancel'
background_color: 0,1,255,0.7
on_press: root._cancel()
Label:
id: er
foreground_color: 1, 250, 100, 1
color: 1, 0.67, 0, 1
size_hint_y: None
height: 0
text: root.error
""")
class Main(BoxLayout):
age = NumericProperty()
str_age = StringProperty("None")
def callit(self):
obj = OpenDialog(self)
obj.open()
def on_age(self, *args):
self.str_age = "Age: {}".format(self.age)
class OpenDialog(Popup):
_age = NumericProperty()
error = StringProperty()
def __init__(self, parent, *args):
super(OpenDialog, self).__init__(*args)
self.parent = parent
self.bind(_age=self.parent.setter('age'))
def on_error(self, inst, text):
if text:
self.lb_error.size_hint_y = 1
self.size = (400, 150)
else:
self.lb_error.size_hint_y = None
self.lb_error.height = 0
self.size = (400, 120)
def _enter(self):
if not self.text:
self.error = "Error: enter age"
else:
self._age = int(self.text)
self.dismiss()
def _cancel(self):
self.dismiss()
class SriPop(App):
def build(self):
return Main()
if __name__ == '__main__':
SriPop().run()

Related

how to redirect from one page two other page with an if statement

I want this program to read information from the database and if it was correct, go to the main page of the program
Otherwise say that the information is wrong
how to redirect from one page two other page with an if statement
if user input and password was True by pressing button go to home
otherwise print password or user wrong
It is supposed to read data from the database
.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.lang import Builder
from kivy import Config
Builder.load_file("kivy.kv")
class AddUser(Screen):
def changeScreen(self):
self.ids.Gotologin.on_press = self.manager.transition.direction = 'up'
def getUserInfo(self):
name = self.ids.addusername.text
paswd = self.ids.addpassword.text
phone = self.ids.addphone.text
gmail = self.ids.addgmial.text
if len(paswd) == 0 and len(name) == 0:
self.ids.passwordles.text = "Enter your name & Password !"
elif len(paswd) <= 0:
self.ids.passwordles.text = "Add a Pssword !"
elif len(paswd) <= 6:
self.ids.passwordles.text = "Password is too small"
elif len(name) <= 0:
self.ids.passwordles.text = "Enter your Name !"
class Home(Screen):
def add(self):
name = self.ids.Name.text
number = self.ids.Number.text
ID = self.ids.Id.text
Buy = self.ids.Buy.text
sale = self.ids.Sale.text
ex_date = self.ids.exdate.text
usage = self.ids.Usage.text
medicine = self.ids.Medicine.text
Category = self.ids.Catigory.text
class LogIn(Screen):
def get(self):
cr.execute("SELECT * FROM login")
log = cr.fetchall()
user = self.ids.username.text
paswd = self.ids.password.text
Screen_Manager = ScreenManager()
Screen_Manager.add_widget(AddUser(name="Adduser"))
Screen_Manager.add_widget(LogIn(name="Login"))
Screen_Manager.add_widget(Home(name="Home"))
# main class to run application
class MainApp(App):
def build(self):
return Screen_Manager
if __name__ == "__main__":
MainApp().run()
.kv
<AddUser>:
BoxLayout:
canvas.before:
Color:
rgba:0,0,1,1
Rectangle:
size:self.size
pos:self.pos
orientation:"vertical"
BoxLayout:
Label:
id:passwordles
text:""
BoxLayout:
orientation:'vertical'
BoxLayout:
Label:
size_hint_x:.22
text:""
Label:
text:"User Name *"
Label:
text:"Password *"
Label:
text:"Phone Number"
Label:
text:"Gmail"
Label:
size_hint_x:.22
BoxLayout:
Label:
size_hint_x:.22
text:""
TextInput:
id:addusername
size_hint_y:.5
hint_text:"User Name"
TextInput:
id:addpassword
size_hint_y:.5
password:True
hint_text:"Password"
TextInput:
id:addphone
size_hint_y:.5
hint_text:"Phone Number"
TextInput:
id:addgmial
size_hint_y:.5
hint_text:"Gmail"
Label:
size_hint_x:.22
BoxLayout:
Label:
text:""
Button:
id:Gotologin
radius: 100, 100, 100, 100
font_name:"fonts/MTCORSVA.TTF"
color:1,1,0,1
outline:0,0,0,1
outline_width:4
font_size:32
bolde:True
size_hint_y:.8
text:"Login"
on_press:
root.getUserInfo()
root.manager.transition.direction = 'up'
root.manager.transition.duration = .9
root.manager.current = 'Login'
Label:
text:""
BoxLayout:
Label:
text:""
<LogIn>:
BoxLayout:
orientation:'vertical'
canvas.before:
Color:
rgba:0,0,1,1
Rectangle:
size:self.size
pos:self.pos
BoxLayout:
Label:
text:""
BoxLayout:
orientation:'horizontal'
BoxLayout:
size_hint_x:.4
Label:
text:""
BoxLayout:
orientation:"vertical"
TextInput:
id:username
size_hint_y:.3
hint_text:"User Name"
TextInput:
id:password
size_hint_y:.3
hint_text:"Password"
BoxLayout:
orientation:"horizontal"
Label:
size_hint_x:.3
text:""
Button:
id:LoginFromButton
on_press:
root.manager.transition.direction='left'
root.manager.transition.duration = .9
root.manager.current = 'Home'
text:'Login'
font_name:"fonts/MTCORSVA.TTF"
color:1,1,0,1
outline:0,0,0,1
outline_width:4
font_size:32
bolde:True
size_hint_y:.5
Label:
size_hint_x:.3
text:""
BoxLayout:
size_hint_x:.4
Label:
text:""
BoxLayout:
Label:
text:""
<Home>:
Button:
text:"Home"
In your kv, set the on_press to a method, like this:
Button:
id:LoginFromButton
on_press:
root.do_login()
Then, in the LogIn screen class:
def check_login(self):
# do your check for legal login and return True or False
return True
def do_login(self):
if self.check_login():
self.manager.current = 'Home'

Kivy Popup misbehaviour when called from inside 'on_enter'

I am trying to display a Popup in case today is a date on DB.
the problem is the popup pops, but it seems to be built behind the main screen.
I am supposing this is due to be called on "on_enter" method, but couldn't work around this.
Please, note that this "Settings" button is being rendered from the Main screen not from the popup itself.
Here is my main.py:
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from datetime import date, datetime
from calendar import weekday
from kivymd.toast import toast
from kivymd.uix.list import TwoLineIconListItem
from kivymd.uix.picker import MDDatePicker, MDTimePicker
from datahelper import CreateTable, InsertEstudo, DeletStudy, ReadStudy, UpdateStudy
from kivy.factory import Factory
class Gerenciador(ScreenManager):
pass
class Main(Screen):
# def verificar_estudos(self):
def on_enter(self, *args):
ler_dbestudos = ReadStudy()
resultado = ler_dbestudos.ler_estudos()
for s in resultado:
dia = s[2].split("-")[-1]
mes = s[2].split("-")[-2]
ano = s[2].split("-")[0]
print(f"{dia}/{mes}/{ano}")
dia_hoje = date.today().day
mes_hoje = date.today().month
ano_hoje = date.today().year
if int(dia) == dia_hoje:
print('Hoje é dia de revisão de matéria')
tudo = self.children
Factory.DiaDeRevisao().open()
if int(dia) + 14 == dia_hoje:
print('Hoje é dia de revisão de matéria')
Factory.DiaDeRevisao().open()
if int(mes)+1 == mes_hoje:
print('Hoje é dia de revisão de matéria')
Factory.DiaDeRevisao().open()
class Revisao(Screen):
def ver_estudos(self, *args):
read_studies = ReadStudy()
studies = read_studies.ler_estudos()
for s in studies:
self.ids.scrollviewid.add_widget(TwoLineIconListItem(text=s[1], secondary_text=s[2]))
def ver_lista(self, *args):
for r in range(20):
self.ids.scrollviewid.add_widget(TwoLineIconListItem(text='Azul', secondary_text="Texto Secundário"))
class AddStudy(Screen):
def open_calendar(self):
date_dialog = MDDatePicker(callback=self.get_date)
if self.ids.dtinist.focused == True:
date_dialog.open()
def get_date(self, *args):
'''
:type date: <class 'datetime.date'>
'''
print(args[0])
print(type(args[0]))
self.ids.dtinist.focused = False
self.ids.dtinist.text = str(args[0])
self.ids.dtinist.focused = False
return args[0]
def open_clock(self):
time_dialog = MDTimePicker()
time_dialog.bind(time=self.get_time)
if self.ids.tminist.focused == True:
time_dialog.open()
def get_time(self,*args):
self.ids.tminist.focused = False
self.ids.tminist.text = str(args[1])
self.ids.tminist.focused = False
return args[1]
def selected(self, path, selection):
tipo = selection[0].split(".")[-1]
print(tipo)
if tipo == 'mp3':
toast('Arquivo MP3 selecionado')
with open(selection[0], 'rb') as f:
barq = f.read()
insert = InsertEstudo()
insert.criar_novo_estudo()
def confirm_new(self):
materia = self.ids.materia_estudo.text
data_estudo = self.ids.dtinist.text
hora_estudo = self.ids.tminist.text
insert_new_study = InsertEstudo()
if insert_new_study.criar_novo_estudo(materia, data_estudo, hora_estudo):
toast('Estudo adicionado com sucesso')
else:
toast('Algo deu muito errado. O estudo não foi adicionado. Tente novamente mais tarde')
class SettingsScreen(Screen):
def select_path(self, path):
print(path)
'''It will be called when you click on the file name
or the catalog selection button.
:type path: str;
:param path: path to the selected directory or file;
'''
self.exit_manager()
toast(path)
def open_file_manager(self):
self.file_manager.show('/') # output manager to the screen
self.manager_open = True
def exit_manager(self):
self.manager_open = False
self.file_manager.close()
class SelectAlarm(Screen):
def selected(self, path, selection):
tipo = selection[0].split(".")[-1]
print(tipo)
if tipo == 'mp3':
toast('Arquivo MP3 selecionado')
with open(selection[0], 'rb') as f:
barq = f.read()
insert = InsertEstudo()
insert.criar_novo_estudo()
else:
toast('Por favor, seleecione um arquivo mp3')
class BoraEstudarApp(MDApp):
def on_pause(self):
return True
def build(self):
data_hoje = f"{date.today().year}-{date.today().month}-{date.today().day}"
sm = Gerenciador()
sm.add_widget(Main(name='Principal'))
sm.add_widget(SettingsScreen(name='Preferencias'))
sm.add_widget(AddStudy(name='NovaMateria'))
sm.add_widget(Revisao(name='Revisoes'))
sm.add_widget(SelectAlarm(name='SelecionarAlarme'))
return sm
if __name__ == "__main__":
boraestudar = BoraEstudarApp()
boraestudar.run()
and here is my kv file:
#:import Factory kivy.factory.Factory
<ScreenManager>:
<DiaDeRevisao#Popup>:
title: 'Atenção dia de revisão'
auto_dismiss: False
size_hint:0.7,0.7
BoxLayout:
canvas.before:
Color:
rgba:(1,1,1,1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
orientation:'vertical'
MDLabel:
text:'Hoje é dia de revisão'
Button:
text: 'OK'
on_press: root.dismiss()
<FileChooserPop#Popup>:
title:'Escolha o arquivo de audio MP3'
BoxLayout:
canvas.before:
Color:
rgba:(0,0,0,0.35)
Rectangle:
size: self.size
pos: self.pos
orientation: 'vertical'
BoxLayout:
size_hint_y: None
height: sp(52)
Button:
text: 'Icon View'
on_press: fc.view_mode = 'icon'
Button:
text: 'List View'
on_press: fc.view_mode = 'list'
FileChooser:
id: fc
FileChooserIconLayout
FileChooserListLayout
BoxLayout:
size_hint_y: None
MDTextButton:
size_hint_x:0.4
text: 'Voltar'
on_press: root.dismiss()
MDIconButton:
halign:'center'
icon:'content-save'
on_press:root.selected(fc.path, fc.selection)
on_release: root.manager.current = 'Principal'
<Main>:
BoxLayout:
orientation:"vertical"
spacing:'50dp'
padding:'70dp'
BoxLayout:
MDTextButton:
text: 'Revisões'
on_press: root.manager.current = 'Revisoes'
# on_release:Factory.FileChooserPop().open()
BoxLayout:
Button:
text: 'Settings'
on_press: root.manager.current = 'Preferencias'
BoxLayout:
MDIconButton:
icon: "plus"
on_press: root.manager.current = 'NovaMateria'
<AddStudy>:
BoxLayout:
orientation:'vertical'
spacing:'100sp'
padding: '100dp'
MDTextField:
id:materia_estudo
hint_text: 'Matéria'
MDTextField:
id: dtinist
text: ''
hint_text: 'data do Estudo'
on_focus: root.open_calendar()
MDTextField:
id:tminist
text:''
hint_text: 'Hora do Estudo'
on_focus: root.open_clock()
BoxLayout:
MDTextButton:
text:'Voltar'
on_press: root.manager.current = 'Principal'
MDTextButton:
text: 'Salvar'
on_press: root.confirm_new()
<SettingsScreen>:
BoxLayout:
MDTextButton:
text: 'Selecionar Alarme'
on_press: root.manager.current = 'SelecionarAlarme'
<SelectAlarm>:
BoxLayout:
canvas.before:
Color:
rgba:(0,0,0,0.35)
Rectangle:
size: self.size
pos: self.pos
orientation: 'vertical'
BoxLayout:
size_hint_y: None
height: sp(52)
Button:
text: 'Icon View'
on_press: fc.view_mode = 'icon'
Button:
text: 'List View'
on_press: fc.view_mode = 'list'
FileChooser:
id: fc
FileChooserIconLayout
FileChooserListLayout
BoxLayout:
size_hint_y: None
MDTextButton:
size_hint_x:0.4
text: 'Voltar'
on_press: root.manager.current = 'Principal'
MDIconButton:
halign:'center'
icon:'content-save'
on_press:root.selected(fc.path, fc.selection)
on_release: root.manager.current = 'Principal'
<Revisao>:
BoxLayout:
orientation:'vertical'
BoxLayout:
ScrollView:
do_scroll_y: True
size_hint_y: None
height: '500dp'
MDList:
id:scrollviewid
BoxLayout:
size_hint_y: 0.15
MDTextButton:
size_hint_x: None
text:"Voltar"
on_release: root.manager.current = 'Principal'
MDTextButton:
text:"Ver Lista"
on_release: root.ver_estudos()
This is odd and I couldn't figure this out.
I appreciate any help. Cheers!
The problem is that the on_enter() event is triggered too early, so it the Popup gets drawn before the Main Screen. You can fix that by adding a very short delay before displaying the Popup. I changing the:
Factory.DiaDeRevisao().open()
to:
Clock.schedule_once(lambda dt: Factory.DiaDeRevisao().open())
will provide that delay and allow the Popup to display on top of the Screen.

Kivy: changing image source on screen

After much headbanging, I've created an app that opens the FileChooser and picks an image. A function will then transform the image and change it on the screen.
< FirstScreen > is just something to start with, relatively unimportant.
< SecondScreen > is the file chooser. The path may need editing. < ThirdScreen > shoudl show the image along with buttons that will eventually lead elsewhere.
I suspect the problem is that the line
sm.current = "_third_screen_"
is creating a new instance separate to everything else I've passed items too. How do I show the image I selected?
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
Builder.load_string("""
<MyScreenManager>:
FirstScreen:
SecondScreen:
ThirdScreen:
<FirstScreen>:
name: '_first_screen_'
BoxLayout:
orientation: "horizontal"
Label:
id: first_screen_label
text: "Hi, I'm the home page"
BoxLayout:
orientation: "vertical"
Button:
text: "Okay!"
on_press: root.manager.current = '_second_screen_'
Button:
text: "Cancel!"
on_press: app.stop()
<SecondScreen>:
name: '_second_screen_'
id: file_chooser
BoxLayout:
id: file_chooser_box_layout
orientation: "horizontal"
Button
text: "Open"
on_press:
root.callback_image_and_other_stuff(file_chooser_list_view.selection)
FileChooserListView:
id: file_chooser_list_view
<ThirdScreen>:
name: '_third_screen_'
BoxLayout:
orientation: "vertical"
id: third_screen
Label:
id: main_title
text: "Upload"
size_hint: (1, 0.1)
Image:
id: main_image
source: root.img
size_hint: (1, 0.75)
BoxLayout:
orientation: "horizontal"
padding: 10
size_hint: (1, 0.15)
Button:
text: "Okay"
size_hint: (0.5, 1)
on_press: image_viewer.image_accepted_by_user(filechooser.selection)
Button:
text: "Cancel"
size_hint: (0.5, 1)
on_press: root.manager.current = '_first_screen_'
""")
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
def callback_image_and_other_stuff(self, new_image_address):
# do other stuff here also, then pass new_image_address along
new_image_address = new_image_address[0].replace("\\", "/")
third_screen = ThirdScreen()
third_screen.callback_image(new_image_address)
class ThirdScreen(Screen):
img = ObjectProperty(None)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
def callback_image(self, new_image_address):
sm.current = "_third_screen_"
self.img = new_image_address
self.ids.main_image.source = self.img
print(self.img)
# Create the screen manager
sm = ScreenManager() # Problem?
sm.add_widget(FirstScreen(name='_first_screen_'))
sm.add_widget(SecondScreen(name='_second_screen_'))
sm.add_widget(ThirdScreen(name='_third_screen_'))
class MyApp(App):
def build(self):
return sm
if __name__ == '__main__':
MyApp().run()
Every time you use some_obj = SomClass() you are creating a new object, in your case that is what you are doing, you are creating a new ThirdScreen different from the one shown by that you do not observe the image, the solution is that you have to access to the initial object using the ScreenManager and name screen.
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
Builder.load_string("""
<FirstScreen>:
BoxLayout:
orientation: "horizontal"
Label:
id: first_screen_label
text: "Hi, I'm the home page"
BoxLayout:
orientation: "vertical"
Button:
text: "Okay!"
on_press: root.manager.current = '_second_screen_'
Button:
text: "Cancel!"
on_press: app.stop()
<SecondScreen>:
id: file_chooser
BoxLayout:
id: file_chooser_box_layout
orientation: "horizontal"
Button
text: "Open"
on_press:
root.callback_image_and_other_stuff(file_chooser_list_view.selection)
FileChooserListView:
id: file_chooser_list_view
<ThirdScreen>:
BoxLayout:
orientation: "vertical"
id: third_screen
Label:
id: main_title
text: "Upload"
size_hint: (1, 0.1)
Image:
id: main_image
source: root.img
size_hint: (1, 0.75)
BoxLayout:
orientation: "horizontal"
padding: 10
size_hint: (1, 0.15)
Button:
text: "Okay"
size_hint: (0.5, 1)
on_press: image_viewer.image_accepted_by_user(filechooser.selection)
Button:
text: "Cancel"
size_hint: (0.5, 1)
on_press: root.manager.current = '_first_screen_'
""")
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
def callback_image_and_other_stuff(self, new_image_address):
if new_image_address:
third_screen = self.manager.get_screen("_third_screen_")
# do other stuff here also, then pass new_image_address along
new_image_address = new_image_address[0].replace("\\", "/")
third_screen.callback_image(new_image_address)
class ThirdScreen(Screen):
img = ObjectProperty(None)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
def callback_image(self, new_image_address):
sm.current = "_third_screen_"
self.img = new_image_address
self.ids.main_image.source = self.img
print(self.img)
# Create the screen manager
sm = ScreenManager() # Problem?
sm.add_widget(FirstScreen(name='_first_screen_'))
sm.add_widget(SecondScreen(name='_second_screen_'))
sm.add_widget(ThirdScreen(name='_third_screen_'))
class MyApp(App):
def build(self):
return sm
if __name__ == '__main__':
MyApp().run()

Call def from one class to another class in python

I have two file demo.py and demo.kv.
Can anyone tell me how to call function from one class to another class?I want to call def calculate(self): from def on_text(self, text_input, value):.Now i am using code
def on_text(self, text_input, value):
App.get_running_app().User.calculate()
But it gives error AttributeError: 'Test' object has no attribute 'User'
demo.py
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
from kivy.uix.popup import Popup
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)
class User(Popup):
total_value = ObjectProperty(None)
def add_more(self):
self.ids.rows.add_row()
def calculate(self):
rows = self.ids.rows
total = 0
for row in rows.children:
text = row.ids.number_input.text
total += int(text) if text != "" else 0 # validate if the entry is not empty
self.total_value.text = str(total)
class Row(BoxLayout):
col_data = ListProperty(["?", "?", "?", "?", "?"])
button_text = StringProperty("")
col_data3 = StringProperty("")
col_data4 = StringProperty("")
def __init__(self, **kwargs):
super(Row, self).__init__(**kwargs)
self.ids.number_input.bind(text=self.on_text)
def on_text(self, text_input, value):
print('Calling')
App.get_running_app().User.calculate()
class Rows(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class rv(BoxLayout):
data_items = ListProperty([])
mode = StringProperty("")
def __init__(self, **kwargs):
super(rv, self).__init__(**kwargs)
def add(self):
self.mode = "Add"
popup = User()
popup.open()
class MainMenu(BoxLayout):
content_area = ObjectProperty()
def display(self):
self.rv = rv()
self.content_area.add_widget(self.rv)
class Test(App):
def build(self):
self.root = Builder.load_file('demo.kv')
return MainMenu()
if __name__ == '__main__':
Test().run()
demo.kv
<Row>:
size_hint_y: None
height: self.minimum_height
height: 40
Button:
text: root.button_text
size_hint_x: None
top: 200
TextInput:
text: root.col_data3
width: 300
TextInput:
id: number_input
text: root.col_data4
width: 300
input_filter: 'int'
<Rows>:
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
<User>:
id: user
total_value:total_value
BoxLayout:
orientation: "vertical"
padding : 20, 5
BoxLayout:
orientation: "horizontal"
#padding : 10, 10
spacing: 10, 10
size: 450, 40
size_hint: None, None
Label:
size_hint_x: .2
text: "Number"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .4
text: "name"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .4
text: "Value"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
padding : 10, 5
spacing: 10, 10
size: 200, 40
size_hint: None, None
Label:
size_hint_x: .7
text: "Total value"
TextInput:
id: total_value
on_focus:root.test()
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more()
<rv>:
BoxLayout:
orientation: "vertical"
Button:
size_hint: .25, .03
text: "+Add"
on_press: root.add()
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
BoxLayout:
orientation: "vertical"
<MenuButton#Button>:
text_size: self.size
valign: "middle"
padding_x: 5
size : (100, 40)
size_hint : (None, None)
background_color: 90 , 90, 90, 90
background_normal: ''
color: 0, 0.517, 0.705, 1
border: (0, 10, 0, 0)
<MainMenu>:
content_area: content_area
BoxLayout:
orientation: 'vertical'
spacing : 10
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
size_hint_y: 2
MenuButton:
text: 'Menu'
size : (50, 12)
on_release: root.display()
BoxLayout:
id: content_area
size_hint_y: 30
One way to solve this problem without accessing the tree of kivy hierarchies is using global variables, but it is advisable not to abuse this type of variables since the errors generated by its misuse are difficult to trace.
[...]
class Row(BoxLayout):
[...]
def on_text(self, text_input, value):
print('Calling')
popup.calculate()
class rv(BoxLayout):
[...]
def add(self):
self.mode = "Add"
global popup
popup = User()
popup.open()
[...]
This may be a duplicate of this question: Im New on kivy Python classes
Firstly:
class Test(App):
def build(self):
self.root = Builder.load_file('demo.kv')
return MainMenu()
This is a bit unnecessary, you can instead do:
class demo(App):
def build(self):
return MainMenu()
App's search for a kv file with a lowercase name equal to the App's name.
Secondly:
<User>:
id: user
total_value:total_value
This is not how you use ids in the kivy Widgets. When you define a Kivy Widget, ie:
class KivyWidgetName(KivyLayout):
pass
<KivyWidgetName>:
You're creating a class. When you add your custom widget to a parent Widget, you are creating an Object of that KivyWidget Class. Sometimes however if you're making more than one, you need to give them ids so their parent can separate them from each other.
ie:
<RootWidget>:
KivyWidgetName:
id: first_instance
KivyWidgetName:
id: second_instance
So now RootWidget can access two different versions of the class, if it wants to access the first one, it can do:
self.ids.first_instance
You can also access them by the index number in which they appear, so this
can also be done by:
self.ids[1]
However explicit is typically better than implicit
Thirdly, you had the right idea to this:
App.get_running_app().User.calculate()
but it should actually be something like this:
App.get_running_app().root.ids.[INSERTID]
So in this case, you're getting the root widget of app (which is ), then you need to use the ids to get to the proper address.
For example, take this:
:
User:
id: 'user_one'
User:
id: 'user_two'
To access the user calculate function, you can do this:
App.get_running_app().root.ids.user_one.calculate
If you however have a number of children, you'll have to seek all of their ids until you find user:
For example:
<TestWidget>:
User:
id: 'user_one'
User:
id: 'user_two'
<RootWidget>:
TestWidget:
id: 'test_one'
TestWidget:
id: 'test_two'
So to get to user one of test two, you can do this:
App.get_running_app().root.ids.test_two.ids.user_one.calculate
You might need to re-arrange your rootwidget to be something else that just contains your main menu to help you with this but that decision is up to you ultimately.

Python/Kivy : How to pass TextBox value in .kv file from one class to another class

Can anyone tell me?
I have two file test.py and test.kv.
I have a textBox which id : state . How to pass state.text value in root.get_value(state.text) and get value in function of def get_value
test.py
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
Window.size = (450, 525)
class display(Screen):
state = ObjectProperty(None)
def add_more(self):
self.ids.rows.add_row()
def get_value(self,arg1):
print(arg1)
class Row(BoxLayout):
button_text = StringProperty("")
state = ObjectProperty(None)
class Rows(BoxLayout):
orientation = "vertical"
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
test().run()
test.kv
<Row>:
state : state
orientation: "horizontal"
spacing: 0, 5
Button:
text: root.button_text
size_hint_x: .2
TextInput:
text : "Test1"
size_hint_x: .8
id : state
display:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
Button:
size_hint_x: .2
text: "+Add More"
valign: 'bottom'
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
Label:
size_hint_x: .2
text: "SN"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value"
valign: 'bottom'
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
padding : 10, 0
spacing: 10, 10
size_hint: .5, .7
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
on_release:
root.get_value(state.text)
Button:
text: 'Cancel'
on_release: root.dismiss()

Categories

Resources