I have a error in my code, I want to get or to print the product text but when i run it it gave me an error.
here is my code:
import kivy
from kivy.properties import ObjectProperty
from selenium import webdriver
import requests
from selectorlib import Extractor
from selenium.webdriver.common.keys import Keys
from kivymd.app import MDApp
from kivy.app import App
from kivy.lang import Builder
KV = '''
BoxLayout:
product: product
size_hint: .8, .8
pos_hint: {"center_x": .5, "center_y": .5}
spacing: dp(100)
orientation: "vertical"
MDTextFieldRound:
id: product
hint_text: 'Enter a product'
icon_left: 'magnify'
on_text_validate: app.System()
'''
class Main(MDApp):
def build(self):
return Builder.load_string(KV)
product = ObjectProperty(None)
def System(self):
print(self.product.text)
if __name__ == "__main__":
Main().run()
it always gave me the next error
File "C:/Users/Yesnia/Desktop/PYTHON/Apps development/App/App_Checking_Store.py", line 34, in
System
print(self.product.text)
AttributeError: 'NoneType' object has no attribute 'text'
help me please
So you build your kv string but have no way to reference it. There are many ways to mend the situation, heres an example.
KV = '''
BoxLayout:
###product: product ### this does not achieve anything, you're just giving
#some generic box layout a product attribute. this does not assign the App attribute.
size_hint: .8, .8
pos_hint: {"center_x": .5, "center_y": .5}
spacing: dp(100)
orientation: "vertical"
MDTextFieldRound:
id: product
hint_text: 'Enter a product'
icon_left: 'magnify'
on_text_validate: app.System()
'''
class Main(MDApp):
product = ObjectProperty(None)
my_kv = None
def build(self):
self.my_kv = Builder.load_string(KV)
self.product = self.my_kv.ids.product
return self.my_kv
def System(self):
print(self.product.text)
notice the comment i've left in your kv string, the addition of the new my_kv attribute to your App class, and the changes I've made to your build function.
Hope this helps!
Related
I would like to have a button on the screen that would open the camera and read a barcode and I would like to show the image of the product based on the barcode and if I press the button again It opens the camera again and does the same job.
Before asking here, I searched examples but couldn't make it working with my limited understanding of kivy.
I have tried using:
https://github.com/kivy-garden/zbarcam
It has following issues for my usecase.
Camera is always open, would like to open only at button click
Doesn't show the output of barcode not sure if it is reading or not.
doesn't say what is the way to pass the output to a method so it can
be processed further
Thanks in advance.
Unfortunately zbarcam of kivy-garden is designed in such away it will always keep the camera running in the background which heats up the device and consumes a lot of power.
Here is an implementation of zbarcam and qrcode that I have created earlier(username:admin ,password:admin). The actual implementation requests the username and password from Mysql database, let me know if you need that.
calc method can be used to get the qrcode string and display the image of the product.
Update
My implementation uses KivyMD here https://github.com/kivymd/KivyMD so you need to have it installed by using
pip install kivymd==0.104.1
It has QR generator from kivygarden here https://pypi.org/project/kivy-garden.qrcode/ you also need to have it installed.
pip install kivy-garden.qrcode
And of course you need pyzbar installed as it is a dependency for both packages
pip install pyzbar
demo.kv
#:import ZBarCam kivy_garden.zbarcam.ZBarCam
#:import ZBarSymbol pyzbar.pyzbar.ZBarSymbol
#:import QRCodeWidget kivy_garden.qrcode
MyLayout:
scr_mngr: scr_mngr
orientation: 'vertical'
ScreenManager:
id: scr_mngr
Screen:
id: screen1
name: 'screen1'
MDSpinner:
id:spinner
size_hint: None, None
size: dp(46), dp(46)
pos_hint: {'center_x': .5, 'center_y': .5}
active: False
MDToolbar:
md_bg_color: 0, 0, 1, 1
title: "Login Screen"
pos_hint:{"top": 1}
elevation: 11
BoxLayout:
orientation: "vertical"
padding: "16dp"
spacing: "16dp"
size_hint_y: None
height: self.minimum_height
pos_hint: {"center_y": .6}
MDLabel:
text: "Log In"
halign: "center"
font_style: "H4"
size_hint_y: None
MDTextField:
id: username
hint_text: "Username "
helper_text_mode: "on_focus"
required: True
MDTextField:
id: password
hint_text: "Password "
helper_text_mode: "on_focus"
required: True
password: True
MDRaisedButton:
text: "LOGIN"
pos_hint: {"center_x": 0.5, "center_y": 0.3}
on_release: root.check_data_login()
Screen:
id: screen2
name: 'screen2'
BoxLayout:
orientation: 'vertical'
MDToolbar:
md_bg_color: 0, 0, 1, 1
id: toolbar
title: "Page 2"
BoxLayout:
orientation: 'vertical'
MDTabs:
Tab:
text: "Scan"
ZBarCam:
id: zbarcam
# optional, by default checks all types
code_types: ZBarSymbol.QRCODE, ZBarSymbol.EAN13
pos_hint: {'center_x': 0.5, 'center_y': 0.75}
size_hint: [1, 1]
MDLabel:
id: qrlabel
#size_hint: None, None
size: self.texture_size[0], 50
pos_hint: {'center_x': 0.5, 'center_y': 0.3}
halign: "center"
text: ', '.join([str(symbol.data) for symbol in zbarcam.symbols])
on_text: root.calc(self.text)
opacity: 1
Tab:
text: "Generate"
BoxLayout:
orientation: 'vertical'
padding: "16dp"
spacing: "16dp"
MDTextField:
id: txtfld
pos_hint: {'center_x': 0.5, 'center_y': 0.75}
size_hint: [0.8,0.2]
hint_text: "Text to be encoded"
mode: "rectangle"
on_text: qr.data = txtfld.text
QRCodeWidget:
id: qr
data: ''
size_hint: [0.8,0.3]
pos_hint: {'center_x': 0.5, 'center_y': 0.3}
show_border: False
login.py
#!/usr/bin/env python
from kivymd.app import MDApp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager as scr_mngr
from kivymd.toast import toast
from kivy.core.window import Window
from kivymd.uix.tab import MDTabsBase
from kivy.uix.floatlayout import FloatLayout
class Tab(FloatLayout, MDTabsBase):
pass
class MyLayout(BoxLayout):
def check_data_login(self):
self.ids['spinner'].active=True
username = self.ids['username'].text
password = self.ids['password'].text
print(username)
print(password)
if not username and not password:
toast("Username and password are required")
elif not username:
toast("Username is required ")
elif not password:
toast("Password is required")
else:
if username == "admin" and password == "admin":
self.ids['spinner'].active=False
self.change_screen("screen2")
else:
self.ids['spinner'].active=False
toast("Wrong username or password")
def change_screen(self, screen, *args):
self.scr_mngr.current = screen
def calc(self, instance):
print(self.ids['qrlabel'].text)
class DemoApp(MDApp):
pass
if __name__ == '__main__':
Window.show_cursor = True
Window.size = (360, 680)
DemoApp().run()
I recently started with kivy and struggled a lot with the ZBarCam as well.
I posted a question and thanks to the comments and answers I could finally come to a working code that:
Starts with camera off
When clicking a button starts the ZbarCam and starts reading
When something is detected (i.e QR is read), ZBarCam stops (as well as the camera) and saves the text in a variable which then you can process it as you want
You can find the working example in https://stackoverflow.com/a/73077097/6018801
Hope it helps
I recently created a android qr code scanner app with ZBarCam.
You can control the camera via the xcamera like this with ids.
self.ids.<zbarcam_ids>.xcamera.play = True
I set it to false when the app is build and use screen manager to with on_enter/leave to enable/disble the camera.
I'm trying to do the same think, my way hope it helps:
try:
import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy_garden.zbarcam import ZBarCam
except:
import subprocess
subprocess.check_call(["python", '-m', 'pip', 'install', 'kivy'])
subprocess.check_call(["python", '-m', 'pip', 'install', 'kivy_garden'])
subprocess.check_call(["python", '-m', 'pip', 'install', 'pyzbar'])
class MainScreen(Screen):
def __init__(self, **kw):
super().__init__(**kw)
self.box = BoxLayout()
self.box.orientation = 'vertical'
self.box.spacing = 20
self.box.padding = 20
self.logo = Image(source='logo.png')
self.box.add_widget(self.logo)
self.btn_add_pick = Button(font_size=30, text='Add Pick')
self.box.add_widget(self.btn_add_qr)
self.btn_remove_pick = Button(font_size=30, text='Delet Pick')
self.box.add_widget(self.btn_remove_pick)
self.add_widget(self.box)
class CameraScreen(Screen):
def __init__(self, **kw):
super().__init__(**kw)
self.box = BoxLayout(orientation = 'vertical')
self.cam = ZBarCam()
self.cam.play = False
self.btn_close = Button(font_size=30, size_hint_y=None, text='Get')
self.box.add_widget(self.cam)
self.box.add_widget(self.btn_close)
self.add_widget(self.box)
class WindowManager(ScreenManager):
def __init__(self, **kv):
super().__init__(**kv)
ms = MainScreen(name="main")
ms.btn_add_pick.bind(on_press=self.switch_to_camera)
ms.btn_remove_pick.bind(on_press=self.switch_to_camera)
self.add_widget(ms)
cs = CameraScreen(name = "camera")
cs.btn_close.bind(on_press=self.switch_to_main)
self.add_widget(cs)
def switch_to_camera(self, instance):
self.current='camera'
self.transition.direction='down'
def switch_to_main(self, instance):
self.current = 'main'
self.transition.direction='up'
class WoodWQApp(App):
def build(self):
wm = WindowManager()
wm.current = 'main'
return wm
if __name__=="__main__":
WoodWQApp().run()
I am working on the same issue from my previous post. Now I added screen manager, and I can switch to different pages.
why is my kivy program not calling the function from another class?
I am still confused about OOP with GUIs, however I tried the following, and none of them worked.
I tried to add an instance of Screen 1() in the main app(), and it did nothing. Then, I tried to add the contractor method init into Screen_1() and it says I don't have a build method. And few other ideas that didn't work at all.
Then I realized that there is no link between Screen_Manager() and Screen_1() because all of my methods are in Screen_1(), but the build method is returning Screen_Manager(). On my kv file, there is this code:
<Screen_Manager>:
Screen_1:
Screen_2:
isn't this is where the program "links" between the Screen_Manager() class to other classes?
if someone can help me understand what I am not understanding and help me correct my problem, it would help me to learn about kivy. I understand, <> is like apply to rules, which has 2 widgets screen 1 and screen 2, and also have their own rules.
here is my main.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.lang.builder import Builder
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.modules import keybinding
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
class Screen_Manager(ScreenManager):
pass
class Screen_1(Screen):
main_display = ObjectProperty()
text_input = ObjectProperty()
def plus_1(self):
self.value = int(self.main_display.text)
self.main_display.text = str(self.value + 1)
def minus_1(self):
self.value = int(self.main_display.text)
self.main_display.text = str(self.value - 1)
def up(self):
self.main_display.text = self.text_input.text
self.text_input.text = ''
class Keyboard(Widget):
def __init__(self, instance):
super().__init__()
self.a = instance
self.keyboard = Window.request_keyboard(None, self)
self.keyboard.bind(on_key_down=self.on_keyboard_down)
def on_keyboard_down(self, keyboard, keycode, text, modifiers):
if keycode[1] == 'enter':
self.a.up()
return True
class Screen_2(Screen):
pass
class MainApp(App):
def build(self):
self.title = "Number Control App"
self.sm = Screen_Manager()
key = Keyboard(self.sm)
return self.sm
if __name__=="__main__":
MainApp().run()
my kv file
<Screen_Manager>:
Screen_1:
Screen_2:
<Screen_1>:
name: "first"
main_display: display_1
text_input: text_input_1
#------inherenting from BoxLayout
BoxLayout:
orientation: "vertical"
#------begining of conent--
BoxLayout:
size_hint_y: 1
#-nexted content------
Label:
id: display_1
text: "0"
font_size: "150sp"
background_color: 0.1, 0.5, 0.6,
#--------
BoxLayout:
size_hint_y: .35
orientation: "horizontal"
#-nexted content------
Button:
text: "-"
font_size : "60sp"
on_press: root.minus_1()
#-nexted content------
Button:
text: "+"
font_size : "35sp"
background_color: (0, 1, 0, 1)
on_press: root.plus_1()
#--------
BoxLayout:
size_hint_y: .15
orientation: "horizontal"
#-nexted content-------
Button:
text: "Config"
size_hint_x: .25
on_release:
root.manager.current = "second"
root.manager.transition.direction = "left"
#-nexted content-------
TextInput:
id: text_input_1
size_hint_x: 1
hint_text: "Enter your initial # here"
multiline: False
#-nexted content-------
Button:
text: "Up"
size_hint_x: .25
on_press: root.up()
<Screen_2>:
name: "second"
Button:
text: "Go Back"
on_press:
app.root.current = "first"
root.manager.transition.direction = "right"enter code here
thanks again for taking the time to help.
Not sure I understand your question, but pressing Enter in your TextInput executed your code:
self.a.up()
but a in your KeyBoard is the Screen_Manager as set at the line:
self.sm = Screen_Manager()
key = Keyboard(self.sm)
and Screen_Manager has no up method. You can fix that by changing the code in your KeyBoard code to:
self.a.current_screen.up()
Note that this will only work when the current screen is Screen_1.
I'm trying to have self.search_results.data printed on my console, but this is not working. Am I using RecycleView the right way? The textbook I'm studying with is from 2014 and uses ListView. I found on the internet that ListView is deprecated. I can't seem to understand how the RecycleView actually works. I've read the documentation, but still can't see.
Kivy:
WeatherRoot:
<WeatherRoot>:
AddLocationForm
<AddLocationForm>:
orientation: "vertical"#
search_input: search_input
search_results: search_results_list
BoxLayout:
height: "40dp"
size_hint_y:None
TextInput:
id: search_input
size_hint_x: 50
focus: True
multiline: False
on_text_validate: root.search_location()
Button:
text: "Search"
size_hint_x: 25
on_press: root.search_location()
Button:
text: "Current Location"
size_hint_x: 25
RecycleView:
id: search_results_list
data: []
Python:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty, ListProperty
from kivy.network.urlrequest import UrlRequest
from kivy.factory import Factory
import json
class WeatherApp(App):
pass
class WeatherRoot(BoxLayout):
pass
class AddLocationForm(BoxLayout):
search_input = ObjectProperty()
search_results = ObjectProperty()
# do something
def search_location(self):
search_template = "http://api.openweathermap.org/data/2.5/find?q=
{}&type=like"
search_url = search_template.format(self.search_input.text)
request = UrlRequest(search_url, self.found_location)
def found_location(self, request, data):
data = json.loads(data.decode()) if not isinstance(data, dict)
else data
cities = ["{} ({})".format(d['name'], d['sys']['country'])
for d in data['list']]
self.search_results.data= cities
print(self.search_results.data)
if __name__ =='__main__':
WeatherApp().run()
The strings in the list should be printed on the console
Kivy ListView » Deprecated
ListView is no longer defined in the recently released stable Kivy version 1.11.0.
Kivy RecycleView » MVC (Model-View-Controller)
The view is generatad by processing the data, essentially a list
of dicts, and uses these dicts to generate instances of the
viewclass as required. Its design is based on the MVC
(Model-view-controller) pattern.
Model: The model is formed by data you pass in via a list of dicts.
View: The View is split across layout and views and implemented using adapters.
Controller: The controller determines the logical interaction and is implemented by RecycleViewBehavior.
Solution
To create a RecycleView of selectable item, one needs to implement the following classes as part of the viewclass. The item is usually a widget e.g. Label, Button, or a group/row of widgets in a layout (BoxLayout or GridLayout).
viewclass
Selectabel recycle layout class, e.g. SelectableRecycleBoxLayout(), or SelectableRecycleGridLayout()
Selectable widget class, e.g. SelectableLabel(), SelectableButton(), or SelectableRow()
data
Creates a list of dicts for data
Example
The following example illustrates the equivalence of a ListView by using RecycleView. The viewclass is a selectable RecycleBoxLayout of Label widget. The app is using OpenWeatherMap's API to retrieve a sample weather data of London, GB (Great Britain).
Note:
To make calls to OpenWeatherMap using the real API point, you need an API key (APPID).
main.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.properties import BooleanProperty, ObjectProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.network.urlrequest import UrlRequest
from kivy.lang import Builder
import json
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableLabel(RecycleDataViewBehavior, Label):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableLabel, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableLabel, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
class AddLocationForm(BoxLayout):
search_input = ObjectProperty()
search_results = ObjectProperty()
def search_location(self):
search_template = "https://samples.openweathermap.org/data/2.5/find?q={}&appid=b6907d289e10d714a6e88b30761fae22"
# search_template = "https://api.openweathermap.org/data/2.5/find?q={}&typle=like&appid=xyz"
search_url = search_template.format(self.search_input.text)
request = UrlRequest(search_url, self.found_location)
def found_location(self, request, data):
data = json.loads(data.decode()) if not isinstance(data, dict) else data
cities = ["{} ({})".format(d['name'], d['sys']['country']) for d in data['list']]
self.search_results.data = [{'text': str(x)} for x in cities]
print(f"self.search_results.data={self.search_results.data}")
class WeatherRoot(BoxLayout):
pass
class TestApp(App):
title = "Weather App"
def build(self):
return Builder.load_file("main.kv")
if __name__ == '__main__':
TestApp().run()
main.kv
WeatherRoot:
<WeatherRoot>:
AddLocationForm:
<SelectableLabel>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (1, 0, 0, 1) if self.selected else (.0, 0.9, .1, .3)
Rectangle:
pos: self.pos
size: self.size
Color:
rgba: (0, 0.9, .1, .3)
Rectangle:
pos: self.pos
size: self.size
<AddLocationForm>:
orientation: "vertical"
search_input: search_input
search_results: search_results_list
BoxLayout:
height: "40dp"
size_hint_y:None
TextInput:
id: search_input
size_hint_x: 50
focus: True
multiline: False
hint_text: 'Your city name'
on_text_validate: root.search_location()
Button:
text: "Search"
size_hint_x: 25
on_press: root.search_location()
Button:
text: "Current Location"
size_hint_x: 25
RecycleView:
id: search_results_list
viewclass: 'SelectableLabel'
SelectableRecycleBoxLayout:
default_size: None, dp(26)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
Output
I'm trying to create a Fahrenheit to Celsius program with Kivy. I keep getting
an error that compute is not defined. I am not sure why this is happening since it is being defined under . Any help would be greatly appreciated. Thanks for any help.
from kivy.app import App
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
runTouchApp(Builder.load_string('''
<Convert>:
id: compute
cols:2
padding: 10
spacing: 10
GridLayout:
cols:2
rows:3
Label:
text: 'Fahrenheit'
TextInput:
id: entry
multiline: False
Label:
text: 'Celsius'
TextInput:
id: result
multiline: False
Button:
text: 'Convert'
on_press: compute.celsius(result.text)
'''))
class Convert(GridLayout):
def Temp(self,celsius):
celsius = (entry-32) * 0.556
if celsius:
try:
self.result.text = str(eval(celsius))
except Exception:
self.result.txt = 'Error'
class ConverApp(App):
def build(self):
return Convert()
if __name__=='__main__':
ConverApp().run()
Your code has the following errors:
When you use compute.celsius() you are assuming that you have a celsius() method in your Convert class but you do not have it.
You must use the Temp() method without passing any arguments to it.
When using self.result you are assuming that result is a member of the Convert class but it is not. If you want to access an element within the hierarchy tree of the .kv you must do it through the id.
from kivy.app import App
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
runTouchApp(Builder.load_string('''
<Convert>:
id: compute
cols:2
padding: 10
spacing: 10
GridLayout:
cols:2
rows:3
Label:
text: 'Fahrenheit'
TextInput:
id: entry
multiline: False
Label:
text: 'Celsius'
TextInput:
id: result
multiline: False
Button:
text: 'Convert'
on_press: root.temp()
'''))
class Convert(GridLayout):
def temp(self):
try:
fahrenheit = self.ids.entry.text
celsius = (int(fahrenheit)-32) * 0.556
self.ids.result.text = str(celsius)
except ValueError:
self.ids.result.text = 'Error'
class ConverApp(App):
def build(self):
return Convert()
if __name__=='__main__':
ConverApp().run()
So, I'm new to kivy and can't get this code to work. I'm trying to update a button text with a popup text input. The popup shows when the button is pressed, and when it's dismissed it should update the text on the button with whatever text was typed in it.
I've tried many variations of this code, but no one have worked. Either nothing happens or I get this error:
AttributeError: 'super' object has no attribute '__getattr__'
Here it is:
main.py
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.popup import Popup
class MainWidget(GridLayout):
pass
class PopText(Popup):
def textChange(self):
MyButton().change()
def getText(self):
text = self.display
return text
class MyButton(AnchorLayout):
def change(self):
self.ids.equip_bt.text = PopText().getText()
print(self.ids.my_bt.text)
class MyApp(App):
def build(self):
return MainWidget()
if __name__ == "__main__":
MyApp().run()
my.kv
#:kivy 1.10.0
#:import F kivy.factory.Factory
<PopText>:
size_hint: .7, .3
title: "Input Text"
on_dismiss: self.textChange()
display: pop_text.text
TextInput:
id: pop_text
focus: True
multiline: False
on_text_validate: root.dismiss()
<MyButton>:
anchor_y: "top"
anchor_x: "right"
Button:
id: my_bt
text: "Input Text"
on_release: F.PopText().open()
<MainWidget>:
cols: 1
rows: 2
MyButton:
MyButton:
Any ideas on how to solve this?
Here is a minimum example of what you are trying to achieve. The hard part is connection the button from the Popup to the Button which opened it. I am going through the app class to achieve that. I got to admit it is not a pretty solution.
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.button import Button
class PopupBttn(Button):
def openPopup(self):
Pop = TextPopup().open(self.text)
class TextPopup(Popup):
def open(self, text, **kwargs):
super(TextPopup, self).open(**kwargs)
self.ids.txtipt.text = text
class MyApp(App):
pass
if __name__ == "__main__":
MyApp().run()
kv file:
BoxLayout:
PopupBttn:
id: bttn
text: 'open Popup'
on_press: self.openPopup()
<TextPopup>:
BoxLayout:
orientation: "vertical"
TextInput:
id: txtipt
Button:
text: "OK"
on_release: app.root.ids.bttn.text=root.ids.txtipt.text
on_release: root.dismiss()
Here is an updated version to use multiple buttons. Unfortunately, you will need to set ids and name to the string of id per Button.
python file
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.properties import StringProperty
class PopupBttn(Button):
def openPopup(self):
print(self.name)
Pop = TextPopup().open(self.text, self.name)
class TextPopup(Popup):
bttnid = StringProperty()
text = StringProperty()
def open(self, text, id, **kwargs):
super(TextPopup, self).open(**kwargs)
self.ids.txtipt.text = text
self.bttnid = id
def setText(self):
App.get_running_app().root.ids[self.bttnid].text = self.text
class MyApp(App):
pass
if __name__ == "__main__":
MyApp().run()
kv file
BoxLayout:
orientation: 'vertical'
PopupBttn:
name: 'one'
id: one
text: 'I am the first Button'
PopupBttn:
name: 'two'
id: two
PopupBttn:
name: 'three'
id: three
PopupBttn:
name: 'four'
id: four
text: 'I am the fourth button'
<PopupBttn>:
text: 'open Popup'
on_press: self.openPopup()
<TextPopup>:
text: txtipt.text
BoxLayout:
orientation: "vertical"
TextInput:
id: txtipt
Button:
text: "OK"
on_release: root.setText()
on_release: root.dismiss()
In order to update both buttons, you need to assign unique id to each of them. Please refer to the example below for details.
Example
main.py
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
class MainWidget(GridLayout):
btn_top = ObjectProperty()
btn_bottom = ObjectProperty()
class PopText(Popup):
pass
class MyButton(AnchorLayout):
my_btn = ObjectProperty()
class TestApp(App):
title = "Changing button text with popup text input Kivy"
def build(self):
return MainWidget()
if __name__ == "__main__":
TestApp().run()
test.kv
#:kivy 1.10.0
#:import F kivy.factory.Factory
<PopText>:
size_hint: .7, .3
title: "Input Text"
TextInput:
focus: True
multiline: False
on_text_validate:
app.root.btn_top.my_btn.text = self.text
app.root.btn_bottom.my_btn.text = self.text
root.dismiss()
<MyButton>:
my_btn: my_bt
anchor_y: "top"
anchor_x: "right"
Button:
id: my_bt
text: "Input Text"
on_release: F.PopText().open()
<MainWidget>:
btn_top: btn_top
btn_bottom: btn_bottom
cols: 1
rows: 2
MyButton:
id: btn_top
MyButton:
id: btn_bottom
Output