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
Related
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):
I wrote this to display a button with given image
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
class DatesPage(FloatLayout):
def __init__(self, **kwargs):
super(DatesPage, self).__init__(**kwargs)
self.add_butt = Button(background_normal='plus_butt.png', size_hint=(0.2, 0.1))
self.add_widget(self.add_butt)
class DiaryApp(App):
def build(self):
return DatesPage()
if __name__=='__main__':
DiaryApp().run()
How can i make sure that the image is displayed on the button
You can't get a window with this code. Because you are not calling DiaryApp class correctly.Add brackets after class name.
if __name__=='__main__':
DiaryApp().run()
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__
I want to create a method that can directly access the user-defined properties of a Kivy Widget Class as a list or dict. (In order to pass them in as an argument into another instance of the same class).
python file:
from kivy.uix.behavior import ButtonBehavior
from kivy.uix.image import Image
from kivy.properties import StringProperty
class ExampleWidget(ButtonBehavior, Image):
name = StringProperty()
hometown = StringProperty()
school = StringProperty()
def clone_self(self):
# Psuedo-Code
args = [v for v in self.user_defined_properties]
clone = ExampleWidget(*args)
return clone
I have tried a number of things, such as dir, var and dict as well using the .get() value as defined in the kivy properties docs all to no avail.
My current set up has two methods, one that returns a manually defined dict of properties, the other which creates and returns the clone using the first method.
Using this, my code is functional however I'm quite sure that a lot of it is unnecessary due to some built in method I'm not entirely sure how to access.
Thank you for reading.
You declare your properties on class level. See this code:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import StringProperty, NumericProperty, Property
Builder.load_string('''
<MyWidget>:
Button:
text: 'Print properties'
on_press: root.print_properties()
''')
class MyWidget(BoxLayout):
name = StringProperty()
hometown = StringProperty()
school = StringProperty()
num = NumericProperty()
def print_properties(self):
for k, v in vars(self.__class__).items():
if isinstance(v, Property):
print(k)
class TestApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
TestApp().run()
Compare it with
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import StringProperty, NumericProperty, Property
Builder.load_string('''
<MyWidget>:
Button:
text: 'Print properties'
on_press: root.print_properties()
''')
class MyWidget(BoxLayout):
def __init__(self, *args):
super(BoxLayout, self).__init__(*args)
self.name = StringProperty()
self.hometown = StringProperty()
self.school = StringProperty()
self.num = NumericProperty()
def print_properties(self):
for k, v in vars(self).items():
if isinstance(v, Property):
print(k)
class TestApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
TestApp().run()
EDIT: As I've just discovered, there's also properties() method that should be used instead of vars():
for k, v in self.properties().items():
print(type(v))
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()