Set a numeric keyboard to my kivy app python - android

I have a kivy app with some textinput and I want to show in my smartphone a numeric keyboard. I've been reading about it and I think that with the property input_type=number I could get the right result but I realised that with the kivy updates doesn't work nowadays. How could I get the numeric keyboard when my textinput is focused? With the app in landscape mode it could be useful or the keyboard still will take half screen? Here do you have the code:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
class LoginScreen(GridLayout):
def __init__(self,**kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols=2
self.add_widget(Label(text='Subject'))
self.add_widget(Label(text=''))
self.add_widget(Label(text='1'))
self.add_widget(TextInput(multiline=False))
self.add_widget(Label(text='2'))
self.add_widget(TextInput(multiline=False))
self.add_widget(Label(text='3'))
self.add_widget(TextInput(multiline=False))
self.add_widget(Label(text='4'))
self.add_widget(TextInput(multiline=False))
b1=Button(text='Exit',background_color=[0,1,0,1],height=int(Window.height)/9.0) #doesn't work properly
self.add_widget(b1)
b2=Button(text='Run',background_color=[0,1,0,1],height=int(Window.height)/9.0) #doesn't work properly
self.add_widget(b2)
b1.bind(on_press=exit)
class SimpleKivy(App):
def build(self):
return LoginScreen()
if __name__=='__main__':
SimpleKivy().run()

I think is a bit late, bu maybe someone looks for it tomorrow.
Is true you should change the input_type propery of your TextInput, in your case for example:
self.add_widget(TextInput(multiline=False, input_type = 'number'))
I suggest you create a new custom widget for that in order works in android and desktop, like this that implement a maxdigits property:
class IntegerInput(TextInput):
def __init__(self, **kwargs):
super(IntegerInput, self).__init__(**kwargs)
self.input_type = 'number'
def insert_text(self, substring, from_undo=False):
if substring.isnumeric():
if hasattr(self, "maxdigits"):
if len(self.text) < self.maxdigits:
return super(IntegerInput,self).insert_text(substring, from_undo=from_undo)
else:
return super(IntegerInput, self).insert_text(substring, from_undo=from_undo)

Related

Can a TextEntry.text with readonly be manipulated by code?

Like, can an output-only TextEntry(readonly=True) be changed with TextEntry.insert_text()? Does the readonly refers ONLY to the user part of the GUI?
I assume you actually mean TextInput. If so, the answer is: no, you cannot change the text in code using insert_text, but you can change it using a simple text=.
John Anderson has already given an answer.
You can download the Kivy Launcher or QPython from google playstore so that you can test your kivy codes without using a desktop.
Here is a simple code with TextInput using QPython2:
#-*-coding:utf8;-*-
#qpy:2
#qpy:kivy
#qpy:fullscreen
from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.button import Button
class TestingText(Widget):
def __init__(self):
super(TestingText, self).__init__()
self.size = Window.size
self.t = TextInput(readonly=True)
self.b1 = Button(text="Insert")
self.b2 = Button(text="Set")
self.t.center = self.center
self.b2.right = self.right
self.b1.on_press = self.inserttext
self.b2.on_press = self.settext
self.add_widget(self.t)
self.add_widget(self.b1)
self.add_widget(self.b2)
def inserttext(self):
self.t.insert_text("insertme")
def settext(self):
self.t.text = "setme"
class Test(App):
def build(self):
return TestingText()
Test().run()

Python Kivy Screen Inheritance

Background: I am using solely Python to implement the Kivy screens. I have two screens that both contain a list, and two rows of buttons. I thought it would be good programming practice to create a screen class that has those layouts, and then use inheritance to create the two screens and add buttons to the layouts as needed.
The Problem: However, when I do this I find that in the child screens I cannot access self.manager.current <-- specifically '.current' It also does not have access to self.manager.transition. I wish to understand why this happens, and how/what things are inherited here.
Question: Does anybody know why or how it is not inheriting the parent screen's manager's properties?
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.listview import ListView, ListItemButton
from kivy.adapters import listadapter
from kivy.uix.button import Button
from kivy.properties import ListProperty, StringProperty
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
class ListScreen(Screen): # This is the super class that I am trying to inherit through
itemList = ListProperty([])
selected_value = StringProperty()
layout = BoxLayout(orientation ='vertical')
top_buttons=BoxLayout(size_hint_y=0.1)
scrollable_list=ListView(adapter=listadapter, size_hint_y=0.8)
scrollable_list.data=itemList
scrollable_list.selection_mode='single'
scrollable_list.allow_empty_selection=False
# scrollable_list.cls=ListItemButton <-- Unrelated bug here, ignore this line
bot_buttons=BoxLayout(size_hint_y=0.1)
def __init__(self, **kwargs):
super(ListScreen, self).__init__(**kwargs)
def finalize_widgets(self):
self.layout.add_widget(self.top_buttons)
self.layout.add_widget(self.scrollable_list)
self.layout.add_widget(self.bot_buttons)
self.add_widget(self.layout)
def change(self,change):
self.selected_value = 'Selected: {}'.format(change.text)
def change_screen(self, screen_name):
self.manager.current = screen_name # <-- Here is the problem
class SubScreen(ListScreen):
# This is one of the child classes, intended to inherit Screen through the parent ListScreen class.
def __init__(self, **kwargs):
super(SubScreen, self).__init__(**kwargs)
save = Button(text='Save')
load = Button(text='Load')
new_d = Button(text='New')
new_s = Button(text='New Search')
self.top_buttons.add_widget(save)
self.top_buttons.add_widget(load)
self.top_buttons.add_widget(new_d)
self.top_buttons.add_widget(new_s)
new_s.bind(on_press = self.change_screen('search'))
class ListBuilderApp(App):
def build(self):
sm = ScreenManager(transition=SlideTransition())
sm.add_widget(SubScreen(name='list'))
sm.add_widget(SearchResults(name='results'))
sm.add_widget(SearchScreen(name='search'))
return sm
if __name__ == "__main__":
ListBuilderApp().run()
Well, I don't see ScreenManager which is basically what you get with self.manager(object), so...
No ScreenManager with Screens added either in python or kv like widgets(add_widget()), no self.manager inside any of the Screens - you can't access something that isn't there.
Add some class which will be a root for your Screens and make it ScreenManager + add Screens as children.
Edit:
I was blind probably, but I didn't see on_press=.. stuff. There is the problem, because you didn't assign the function to an event, rather called the function right when you put ('search') at the end. (try do self.parent and you'll see)
Kivy events(at least "on_") catch the function, but not the parameters, not directly. That's why you need to use partial
from functools import partial
new_s.bind(on_press = partial(self.change_screen,'search'))
With this the error is gone, but some adapter binding jumps out which I really don't have a clue how to fix as I don't use it that much.

Breaking Main loop in kivy (Freezing Screen)

I got and issue that when i bind a function with an button that works good but when i bind a function which has a infinite loop in it so screen freezes and other button do not works as example below....please give me solution to break that loop using another button..
from kivy.uix.popup import Popup
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.boxlayout import BoxLayout
from kivy.uix.stacklayout import StackLayout
class APPLICATION_START(FloatLayout):
def __init__(self, **kwargs):
super(MyApp, self).__init__(**kwargs)
self.buone = Button(text="Start Loop",pos=(0,180),size=(470,90),size_hint=(None,None))
self.logi.bind(on_release=self.loooop)
self.exitbtn = Button(text="exit",pos=(0,90),size=(235,70),size_hint=(None,None))
self.exitbtn.bind(on_press=exit)
def loooop(self,instance):
while True:
# do any Activity
#I want to break this loop when someone press on exit button
class MyApp(App):
def build(self):
return APPLICATION_START()
if __name__ == '__main__':
MyApp().run()
The gui can't update until your function returns, which it doesn't.
Either use a thread for your task, or if it is composed of many repetitions of a short task you can do Clock.schedule_interval(your_function, some_timestep) to run it repeatedly.

Kivy: Widgets are adding up

So earlier today I asked about a widget error to which inclement responded to.
His answer worked, but not perfectly. My original problem was adding a widget from a function after a button click, but every time I click the button it adds one more of itself. So first click it says "hi", second click it says "hi hi" and so on.
Here is my code(example script):
import kivy
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
textshow = BoxLayout()
def answer(answer):
text = Label(text=str(answer))
textshow.add_widget(text)
Builder.load_string('''
<main>:
Button:
on_release: root.show()
''')
class main(BoxLayout):
def show(self):
answer("test")
App.get_running_app().popup.open()
class apprun(App):
def build(self):
self.popup = Popup(content=textshow)
return main()
apprun().run()
It's because your answer function adds a widget to textshow, but you never remove any widgets so you just get more and more.
You'd be better off putting this all in a specific class rather than in these global scope variables. For instance, you could make your own popup class displaying some text however you like, and simply set this text with a StringProperty. Then you could either store one or just make a new instance each time with the text property you want.

Kivy TextInput and Fonts

the code in question
txt = TextInput(text='%s'%default, multiline=False, size_hint=(0.5,1))
txt.font_name = gAssets + "FreeSans.ttf"
Txt.font_size = 14
If I comment out the font_name attribute the text in the input lines up about right. (still sits a little bit high in the box but workable)
(using the normal TextInput with the default font (DroidSans.ttf))
However once I uncomment the line that sets it to FreeSans.ttf (larger character set) It now sits way to high in the text field
(using normal TextInput with FreeSans.ttf)
I am using kivy 1.3 and have been unsuccessful at getting the padding attribute to work(however I would be happy to use it if someone could demonstrate how to use it with a TextInput.)
You can alter padding inside your code using VariableListPropery. Example:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.properties import VariableListProperty
class MyTextInput(TextInput):
padding = VariableListProperty(['24dp', '48dp'])
class MyApp(App):
def build(self):
return MyTextInput(text='This is an example text', multiline=False)
if __name__ == '__main__':
MyApp().run()
This code requires 1.7 version, as noted in documentation of the widget. I recommend uprgrading as I don't even see any API archive anywhere to check how it was setted before.

Categories

Resources