Get textinput value in Kivy app - python

New to Python/Kivy trying to build a test app with an input box, an ok button and a label that should change text when the ok button is clicked. But instead I get 'NameError: global name 'txt1' is not defined'. What am I doing wrong?
# import Kivy
import kivy
import random
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
# my app
class MyApp(App):
# layout
def build(self):
layout = BoxLayout(padding=10, orientation='vertical')
btn1 = Button(text="OK")
btn1.bind(on_press=self.buttonClicked)
layout.add_widget(btn1)
lbl1 = Label(text="test")
layout.add_widget(lbl1)
txt1 = TextInput(text='', multiline=False)
layout.add_widget(txt1)
return layout
# button click function
def buttonClicked(self,btn):
lbl1.text = "You wrote " + txt1.text
# run app
if __name__ == "__main__":
MyApp().run()

Use self.txt1, self.lbl1 etc..
class MyApp(App):
# layout
def build(self):
layout = BoxLayout(padding=10, orientation='vertical')
btn1 = Button(text="OK")
btn1.bind(on_press=self.buttonClicked)
layout.add_widget(btn1)
self.lbl1 = Label(text="test")
layout.add_widget(self.lbl1)
self.txt1 = TextInput(text='', multiline=False)
layout.add_widget(self.txt1)
return layout
# button click function
def buttonClicked(self,btn):
self.lbl1.text = "You wrote " + self.txt1.text
# run app
if __name__ == "__main__":
MyApp().run()
# join all items in a list into 1 big string
Using:
def buttonClicked(self,btn):
lbl1.text = "You wrote " + txt1.text <- only exists in the build method

Related

Cannot add DropDown object at 0x000002D18787E6C0> to window, it already has a parent

I've coded this little app with Kivy that has 3 textbox + 1 dropdown:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.popup import Popup
class Inremapp(App):
def AddDropDownButton(self, name):
self.btn = Button(text=name, size_hint_y=None, height=44)
self.btn.bind(on_release=lambda btn: self.dropdown.select(self.btn.text))
self.dropdown.add_widget(self.btn)
def build(self):
self.operaciones = ["1", "123", "1241", "124121"]
self.window = GridLayout()
self.window.cols = 1
self.window.size_hint = (0.6, 0.7)
self.window.pos_hint = {"center_x": 0.5, "center_y":0.5}
# entrada
labelentrada = Label(text='Entrada: (Día/Mes/Año)')
self.window.add_widget(labelentrada)
txtinday = TextInput(text='', multiline=False)
self.window.add_widget(txtinday)
# salida
labelsalida = Label(text='Salida: (Día/Mes/Año)')
self.window.add_widget(labelsalida)
txtoutday = TextInput(text='', multiline=False)
self.window.add_widget(txtoutday)
# obra
txtobra = TextInput(text='Obra', multiline=False)
self.window.add_widget(txtobra)
# operación
self.dropdown = DropDown()
for operacion in self.operaciones:
self.AddDropDownButton(operacion)
mainbutton = Button(text='Operación')
mainbutton.bind(on_release=self.dropdown.open)
self.dropdown.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x))
self.window.add_widget(self.dropdown)
self.window.add_widget(mainbutton)
return self.window
# run app
if __name__ == "__main__":
Inremapp().run()
The app looks like this when running:
But when I click the dropdown button I get the following error:
Exception has occurred: WidgetException Cannot add
<kivy.uix.dropdown.DropDown object at 0x000002D18787E6C0> to window,
it already has a parent <kivy.uix.gridlayout.GridLayout object at
0x000002D1873CEF10> File "D:\Inrema\TabletConnect\main.py", line 68,
in
Inremapp().run()
The basic example from Kivy docs is working fine but... what I'm missing in my code?
EDIT:
After removing self.window.add_widget(self.dropdown) error disappeared, dropdown is showing up but when I select any element I will always get the latest value, doesn't matters what I select.
EDIT 2:
Changed this line:
self.btn.bind(on_release=lambda btn: self.dropdown.select(self.btn.text))
To this:
self.btn.bind(on_release=lambda btn: self.dropdown.select(btn.text))
And worked fine :)

The Screen Manager is not returning Desired Output in Kivy Python

There is no such error shown in the Python output shell.
What I want is that , the first page should be the Login page or as here, the "ConnectingPage" then Welcome Should Be shown, and then at last a Set of buttons named from 0 to 99 be shown.
Here is the code :
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen, FallOutTransition
from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.core.window import Window
class ConnectingPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text = "Usename:"))
self.username = TextInput(multiline=False)
self.add_widget(self.username)
self.add_widget(Label(text = "Password:"))
self.password = TextInput(multiline=False,password = True)
self.add_widget(self.password)
self.joinbutton = Button(text="Join")
self.joinbutton.bind(on_release = self.click_join_button)
self.add_widget(Label())
self.add_widget(self.joinbutton)
def click_join_button(self, instance):
username = self.username.text
password = self.password.text
#if username == "venu gopal" and password == "venjar":
MyApp.screen_manager.current = "Info"
MyApp.screen_manager.current = "Chat"
class InfoPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 1
self.message = Label(text = "welcome",halign="center", valign="middle", font_size=30)
self.add_widget(self.message)
class SomeApp(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
# Make sure the height is such that there is something to scroll.
layout.bind(minimum_height=layout.setter('height'))
for i in range(100):
btn = Button(text=str(i), size_hint_y=None, height=40)
layout.add_widget(btn)
root = ScrollView(size_hint=(1, None), size=(Window.width, Window.height))
root.add_widget(layout)
if __name__ == "__main__":
runTouchApp(root)
class MyApp(App):
screen_manager = ScreenManager(transition=FallOutTransition(duration=2)) # this make screen_manager a class vaiable
def build(self):
# self.screen_manager = ScreenManager()
self.connecting_page = ConnectingPage()
screen = Screen(name='Connect')
screen.add_widget(self.connecting_page)
self.screen_manager.add_widget(screen) # add screen to ScreenManager
# Info page
self.info_page = InfoPage()
screen = Screen(name='Info')
screen.add_widget(self.info_page)
self.screen_manager.add_widget(screen) # add screen to ScreenManager
# Chat App
self.chat_app = SomeApp()
screen = Screen(name='Chat')
screen.add_widget(self.chat_app)
self.screen_manager.add_widget(screen) # add screen to ScreenManager
# return ConnectingPage()
return self.screen_manager
if __name__ == "__main__":
MyApp().run()
The Problem is that: the set of Buttons are getting shown in the start. When the Cross is pressed to close the kivy window, then the Login page is shown and then "welcome" and then the buttons again.
I want It to show from the second Step.
What I believe is that the "line 61" in the code is making a problem. When the code is run it first shows the buttons and so on.
Please Help me find the solution for the above Problem.
Your __init__() method of the SomeApp class starts an App running with the lines:
if __name__ == "__main__":
runTouchApp(root)
and that runTouchApp() does not return until that App completes. So when you run your code, it stops a the line:
self.chat_app = SomeApp()
To fix that, just replace:
if __name__ == "__main__":
runTouchApp(root)
with:
self.add_widget(root)

how to Change colour of a particular button in gridLayout in kivy

I am trying to make tambola coin picker with Python and Kivy and I am new to kivy.
Here, I created gridlayout buttons from 1 to 90. I want to change the color of particular button in gridlayout when its number is picked. I am facing issues to update gridlayout with new colored button. Here I am attaching my code. screenshot
#!/usr/bin/python
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Color
import random
coins = random.sample(range(1,91), 90)
#print(coins)
picked_coins=[]
current_coin=0
#print(picked_coins)
class Housie(FloatLayout):
def __init__(self,**kwargs):
super(Housie,self).__init__(**kwargs)
self.title = Label(text="Housie Coin Picker",font_size = 50,size_hint=(1, .55),pos_hint={'x':0, 'y':.45})
self.main_label = Label(text = "Click PICK NUMBER", size_hint=(1, .60),pos_hint={'x':0, 'y':.35})
self.picked_ones = Label(text = "picked_coins", size_hint=(1, .40),pos_hint={'x':0, 'y':.40})
self.help_button = Button(text = "PICK NUMBER", size_hint=(.3, .1),pos_hint={'x':.65, 'y':.1},on_press = self.update)
self.add_widget(self.title)
self.add_widget(self.main_label)
self.add_widget(self.picked_ones)
self.add_widget(self.help_button)
self.add_widget(self.userinterface())
def userinterface(self):
self.layout = GridLayout(cols = 10,size_hint=(.50, .50))
for i in range(1,91):
self.layout.add_widget(Button(background_color=(1,0,0,1),text =str(i)))
return self.layout
def update(self,event):
for coin in coins:
if coin not in picked_coins:
current_coin=coin
picked_coins.append(coin)
self.main_label.text = str(coin)
for i in self.layout.children:
if i.text == str(coin):
#What to do Here?
break
self.picked_ones.text = "Picked coins = {}".format(" ".join(str(sorted(picked_coins))))
class app1(App):
def build(self):
return Housie()
if __name__=="__main__":
app1().run()
You can bind a method to each Button like this:
def userinterface(self):
self.layout = GridLayout(cols = 10,size_hint=(.50, .50))
for i in range(1,91):
self.layout.add_widget(Button(background_color=(1,0,0,1),text=str(i), on_release=self.butt_pressed))
return self.layout
def butt_pressed(self, button):
button.background_normal = ''
button.background_color = (1,0,0,1)
Th butt_pressed() method changes the background color of the pessed Button.

Kivy python create a tab bar

I started with kivy, I have generally understood the main concepts (it's quite similar to tkinter)
but there is something that I can not do, I would like to create a tab bar at the top of my window (as there is in the web browser)
The only tutorial I find does not look like my code: https://kivy.org/docs/api-kivy.uix.tabbedpanel.html
my code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
class MyApp(App):
# layout
def build(self):
layout = BoxLayout(orientation='vertical')
# use a (r, g, b, a) tuple
blue = (0, 0, 1.5, 2.5)
red = (2.5, 0, 0, 1.5)
btn = Button(text='Touch me!', background_color=blue, font_size=120)
btn.bind(on_press=self.callback)
btn2 = Button(text='btn2', background_color=red, font_size=120)
layout.add_widget(btn)
layout.add_widget(btn2)
self.label = Label(text="------------", font_size='50sp')
layout.add_widget(self.label)
btn1 = Button(text="OK")
btn1.bind(on_press=self.buttonClicked)
layout.add_widget(btn1)
self.lbl1 = Label(text="test")
layout.add_widget(self.lbl1)
self.txt1 = TextInput(text='', multiline=False)
layout.add_widget(self.txt1)
return layout
def callback(self, event):
print("button touched") # test
self.label.text = "button touched"
# button click function
def buttonClicked(self,btn):
self.lbl1.text = "You wrote " + self.txt1.text
# run app
if __name__ == "__main__":
MyApp().run()
# join all items in a list into 1 big string
I try to add tabpannel but i have two question :
1) how can i change name of tab ? and remove "defaulttab"
2) why my widget not in my tab ?
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.tabbedpanel import TabbedPanelItem
class MyApp(App):
# layout
def build(self):
layout = BoxLayout(orientation='vertical')
# use a (r, g, b, a) tuple
blue = (0, 0, 1.5, 2.5)
red = (2.5, 0, 0, 1.5)
tab=TabbedPanel()
tabitem=TabbedPanelItem()
tab.add_widget(tabitem)
layout.add_widget(tab)
btn = Button(text='Touch me!', background_color=blue, font_size=120)
btn.bind(on_press=self.callback)
btn2 = Button(text='btn2', background_color=red, font_size=120)
tabitem.add_widget(btn)
tabitem.add_widget(btn2)
self.label = Label(text="------------", font_size='50sp')
tabitem.add_widget(self.label)
btn1 = Button(text="OK")
btn1.bind(on_press=self.buttonClicked)
tabitem.add_widget(btn1)
self.lbl1 = Label(text="test")
tabitem.add_widget(self.lbl1)
self.txt1 = TextInput(text='', multiline=False)
tabitem.add_widget(self.txt1)
return layout
def callback(self, event):
print("button touched") # test
self.label.text = "button touched"
# button click function
def buttonClicked(self,btn):
self.lbl1.text = "You wrote " + self.txt1.text
# run app
if __name__ == "__main__":
MyApp().run()
# join all items in a list into 1 big string

Download Progress bar in Kivy

I am trying to build an app that downloads a file, whose progress can be tracked on a kivy app.
I have looked at the example here and here for the download progress.
This is my code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.popup import Popup
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.clock import Clock
import urllib
URL = "http://s9.videozoo.me/S/saenai_heroine_no_sodatekata_flat_-_11.mp4?st=Ow7pwXbRt6vPWE-kr5Sn1A&e=1498847899&start=0"
class PopupBox(Popup):
pop_up_text = ObjectProperty()
def update_pop_up_text(self, p_message):
self.pop_up_text.text = p_message
class MyApp(App):
# layout
def show_popup(self):
self.pop_up = Factory.PopupBox()
self.pop_up.update_pop_up_text('Running some task...')
self.pop_up.open()
def build(self):
layout = BoxLayout(padding=10, orientation='vertical')
btn1 = Button(text="OK")
btn1.bind(on_press=self.buttonClicked)
layout.add_widget(btn1)
self.lbl1 = Label(text="test")
layout.add_widget(self.lbl1)
self.txt1 = TextInput(text='', multiline=False)
layout.add_widget(self.txt1)
return layout
# button click function
def buttonClicked(self, btn):
self.lbl1.text = "You wrote " + self.txt1.text
self.show_popup()
self.download_file(URL)
self.pop_up.dismiss()
def download_file(self, url):
u = urllib.request.urlopen(url)
meta = u.info()
metaInfo = str(meta).split()
fileTotalbytes = int(metaInfo[46])
data_blocks = []
total = 0
while True:
block = u.read(1024)
data_blocks.append(block)
total += len(block)
hash = ((60 * total) // fileTotalbytes)
print("[{}{}] {}%".format('#' * hash, ' ' * (60 - hash), int(total / fileTotalbytes * 100)), end="\r")
if not len(block):
break
data = b''.join(data_blocks) # had to add b because I was joining bytes not strings
u.close()
# run app
if __name__ == "__main__":
MyApp().run()
However, I am confused as to how do I bind the download_file function with the kivy widget functionality so as to make it work. How do I appropriately modify the print function so as to make it work with the widget
If you block in the mainthread kivy can no longer update the GUI. Instead create a new thread and use the #mainthread annotation to do gui updates.
Instead of the print you have to manipulate kivy widgets. You could create a rectangle and increase the width to 100%. You could create a textinput and output your text there.

Categories