Why is Kivy FocusBehavior applied to Buttons not working? - python-3.x

In the kivy.FocusBehavior documentation (https://kivy.org/doc/stable/api-kivy.uix.behaviors.focus.html), an example with a FocusButton(FocusBehavior, Button) is given. But using the tab key on Windows 10 to cycle between the buttons added to the GridLayout does not work. What is wrong in the code below ?
from kivy.app import App
from kivy.uix.behaviors.focus import FocusBehavior
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
class FocusButton(FocusBehavior, Button):
def _on_focus(self, instance, value, *largs):
print(self.text)
class FocusBehaviorGUI(GridLayout):
def __init__(self, **kwargs):
super().__init__( **kwargs)
self.cols = 4
self.rows = 2
for i in range(8):
self.add_widget(FocusButton(text=str(i)))
# clicking on a widget will activate focus, and tab can now be used
# to cycle through
class FocusBehaviorApp(App):
def build(self):
return FocusBehaviorGUI()
if __name__ == '__main__':
FocusBehaviorApp().run()

It is working. try changing:
def _on_focus(self, instance, value, *largs):
to:
def on_focus(self, instance, value, *largs):

Related

Python kivy RecursionError: maximum recursion depth exceeded in comparison

I am trying to create a simple app with kivy in python
but when i run this code i get following error
RecursionError: maximum recursion depth exceeded in comparison
import wikipedia
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
class GridLayout(GridLayout):
def __init__(self, **kwargs):
super(GridLayout, self).__init__()
# Number of columns
self.cols = 1
# Second grid Layout
self.second_layout = GridLayout()
self.second_layout.cols = 2
# Creating a text field to show the result of entered query
self.query_result = TextInput(text='', size_hint_y=0.8)
self.second_layout.add_widget(self.query_result) # Adding query result on the screen
# Creating a text input field to get the query from user
self.query = TextInput(text='', multiline=False, hint_text="Enter your Query", size_hint_y=0.1, font_size=20)
self.second_layout.add_widget(self.query)
# Adding Second layout on the screen
self.add_widget(second_layout)
# Creating a submit button
self.submit_button = Button(text="Submit", size_hint_y=0.1, font_size=40, on_press=self.submit)
self.add_widget(self.submit_button)
def submit(self, instance):
try:
query_result_from_wikipedia = wikipedia.page(self.query.text).summary
self.query_result.text = query_result_from_wikipedia
except:
popup = Popup(title='Query Not Found',
content=Label(text='Try to Search Anything else'),
size_hint=(None, None), size=(400, 400))
popup.open()
class MyApp(App):
def build(self):
return GridLayout()
if __name__ == '__main__':
MyApp().run()
But when i remove the second gridlayout from it it runs without errors
The first problem is the name of your class. Don't name a class the same as its subclass:
class GridLayout(GridLayout):
is likely to cause problems. Just change it to something like:
class MyGridLayout(GridLayout):

Why is my kivy program not calling the function from another class?

I think this is more of a python question than a kivy question.
class Keyboard is sharing a method from class GUI. I created a GUI instance called self.a to connected the 2 classes in class Keyboard. Also, I created a keyboard class instance, self.key in class MainApp.
When I use this method, print ("Return button is pressed") the "return" button was able to do the print statement. I understand why it works. When I use the self.a.up() in the method, the return button does not call the up() method from class GUI. It's probably a small detail or a concept that I am missing. This is not an error from the rest of the program. Please help and thanks in advance. Code:
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
class GUI(BoxLayout):
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)
print (self.main_display.text)
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,):
super().__init__()
self.a = GUI()
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()
# print ("Return button is pressed")
return True
class MainApp(App):
def build(self):
key = Keyboard()
return GUI()
if __name__=="__main__":
app = MainApp()
app.run()
I think it works fine but in another object that you can't see. The problem is that you show one object of GUI class on screen. And for the Keyboard class you have created another object that you can't see. So the solution is to use one object of GUI class and operate with it in both of MainApp and Keyboard classes. Something like:
class MainApp(App):
def build(self):
# here we create an object...
self.gui = GUI()
# ...send it to Keyboard class
key = Keyboard(self.gui)
# and return it
return self.gui
class Keyboard(Widget):
def __init__(self, gui):
super().__init__()
# and here we receive that object instead of creating new one
self.a = gui

Kivy - Black screen issue

Why am I getting black screen for the below code in kivy?
MyGrid class is not instantiating.
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class MyGrid(GridLayout):
def __int__(self, **kwargs):
super(MyGrid, self).__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text="First name="))
self.firstName = TextInput(multiline=False)
self.add_widget(self.firstName)
class Myapp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
Myapp().run()
You've written __int__ instead of __init__

Python Kivy Panel Header unable to render content from class

I am trying to create a simple TabbedPanel with 4 tabs. I want each tab to render the widgets from 4 classes. Kivy seems to not be rendering this simple Label. I want to do this with the libraries and not by creating a .kv file and importing it with Builder.load_file(file). In the code I provided, I only show the default_tab. Thanks in advance.
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader
kivy.require('1.10.1')
class DeployScreen(GridLayout):
def __init__(self, **kwargs):
super(DeployScreen, self).__init__(**kwargs)
self.cols = 1
self.add_widget(Label(text='Deploy'))
return(None)
class NucleusPanel(TabbedPanel):
tab_pos = "top_left"
nuc_panel = TabbedPanel()
nuc_panel.default_tab_text = "Deploy"
nuc_panel.default_tab_content = DeployScreen()
class NucleusApp(App):
def build(self):
return(NucleusPanel())
if __name__ == "__main__":
NucleusApp().run()
Add a constructor for class NucleusPanel()
main.py
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.tabbedpanel import TabbedPanel
class DeployScreen(GridLayout):
def __init__(self, **kwargs):
super(DeployScreen, self).__init__(**kwargs)
self.cols = 1
self.add_widget(Label(text='Deploy'))
class NucleusPanel(TabbedPanel):
def __init__(self, **kwargs):
super(NucleusPanel, self).__init__(**kwargs)
self.tab_pos = "top_left"
self.default_tab_text = "Deploy"
self.default_tab_content = DeployScreen()
class NucleusApp(App):
def build(self):
return NucleusPanel()
if __name__ == "__main__":
NucleusApp().run()
Output

How to get nested Kivy widgets to interact between each other?

I'm playing around with the examples provided in the Kivy tutorial. I was able to create nested widgets, but can't seem to get the buttons to modify objects in the other parts of the screen.
In this example, I've tried to modify the Kivy example script to turn it into a simple login window with a numpad drawn from buttons (let's ignore the vkeyboard for this case, I'm trying to get a hold of buttons...). In short, buttons on the left, login textinput on the right. I cannot seem to have the actions on the buttons affect the text input on the right. It sounds very simple, but I can't seem to figure it out. Should I use a global variable? Am I creating my objects incorrectly for this purpose?
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
class AddNumpad(GridLayout):
def __init__(self, **kwargs):
super(AddNumpad, self).__init__(**kwargs)
self.cols = 3
self.padding = 50
def callback(instance):
print('The button <%s> is being pressed' % instance.text)
# TODO: trying to populate the password textinput here
for i in range(1,10):
btn = Button(text=str(i))
btn.bind(on_press=callback)
self.add_widget(btn)
self.add_widget(Label(text=''))
btn = Button(text='0')
btn.bind(on_press=callback)
self.add_widget(btn)
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.password = TextInput(password=True, multiline=False)
self.cols = 2
self.numpad = AddNumpad()
self.add_widget(self.numpad)
self.entry = ''
self.password.text = self.entry
self.add_widget(self.password)
class MyApp(App):
userInput = ''
def build(self):
return LoginScreen()
if __name__ == '__main__':
MyApp().run()
You can use a custom property and bind it to a callback in your LogginScreen class:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.properties import StringProperty
class AddNumpad(GridLayout):
passwIn = StringProperty() # <<<<<<<<<<<<<
def __init__(self, **kwargs):
super(AddNumpad, self).__init__(**kwargs)
self.cols = 3
self.padding = 50
for i in range(1, 10):
btn = Button(text=str(i))
btn.bind(on_press=self.callback)
self.add_widget(btn)
self.add_widget(Label(text=''))
btn = Button(text='0')
btn.bind(on_press=self.callback)
self.add_widget(btn)
def callback(self, instance):
self.passwIn += instance.text # <<<<<<<<<<<<<
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.password = TextInput(password=True, multiline=False)
self.cols = 2
self.numpad = AddNumpad()
self.numpad.bind(passwIn=self.numpad_pressed) # <<<<<<<<<<<<<
self.add_widget(self.numpad)
self.add_widget(self.password)
def numpad_pressed(self, instance, value):
self.password.text = value
class MyApp(App):
def build(self):
return LoginScreen()
if __name__ == '__main__':
MyApp().run()

Resources