im really new in Kivy and i would like to make an app where i could create a MDIconButton that is draggable, and if possible, droppable in any BoxLayout? Is that possible in KivyMD or Kivy? Also is there a Kivy function where whenever I hold down a button, it'll display some kind of small dialogue box that contains details that can be entered by the user. thanks!
Rather than use Drag-N-Drop from kivy-garden just use the DragBehavior class! It comes directly installed with Kivy and it'll save you having to install kivy-garden.
https://kivy.org/doc/stable/api-kivy.uix.behaviors.drag.html
Here is some example code of how it's used:
from kivy.uix.label import Label
from kivy.app import App
from kivy.uix.behaviors import DragBehavior
from kivy.lang import Builder
# You could also put the following in your kv file...
kv = '''
<DragLabel>:
# Define the properties for the DragLabel
drag_rectangle: self.x, self.y, self.width, self.height
drag_timeout: 10000000
drag_distance: 0
FloatLayout:
# Define the root widget
DragLabel:
size_hint: 0.25, 0.2
text: 'Drag me'
'''
class DragLabel(DragBehavior, Label):
pass
class TestApp(App):
def build(self):
return Builder.load_string(kv)
TestApp().run()
Related
I'm currently learning kivy and was following a tutorial, while following the tutorial I ran into a problem where uppon running my code only a black screen appears
this is what my .py file looks like:
from kivy.uix.widget import Widget
from kivy.uix.stacklayout import StackLayout
from kivy.uix.button import Button
from kivy.metrics import dp
from kivy.app import App
class stack_layout_example(StackLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
"""
# orientation without the kv
self.orientation = "lr-bt"
"""
for i in range(0, 100):
size = 100
button = Button(
text = str(i+1),
size_hint=(None, None),
# ( width , height )
size=(size, size)
)
self.add_widget(button)
class the_labApp(App):
pass
the_labApp().run()
and this is my .kv file:
scroll_view_example:
<scroll_view_example#ScrollView>:
stack_layout_example:
<stack_layout_example>:
You're missing the build method in the the_labApp app. It should be like the following code snippet:
class the_labApp(App):
def build(self):
return stack_layout_example()
Thank You very much for your answers guys... I already found the solution in the kivy discord
i just re-arrange the .kv file to
<ScrollViewExample#ScrollView>:
StackLayoutExample:
size_hint: 1, None
height: self.minimum_height
<StackLayoutExample>:
ScrollViewExample:
also the kv looks a bit different now because it now follows pep8(i think)
import kivy
from kivy.lang.builder import Builder
from kivy.app import App
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.widget import Widget
from kivy.clock import Clock
Builder.load_string('''
<apper>
input_val : input_t
BoxLayout:
size: root.size
Label:
id: label_t
text: root.texter
TextInput:
id: input_t
Button:
on_press : root.doer()
''')
class apper(Widget):
texter = StringProperty()
input_val = ObjectProperty(None)
run = 0
def doer(self, dt):
self.run+=1 # keep track of number of times this function ran
#self.texter = self.ids.input_t.text
print(self.ids.input_t.text, self.run) #prints an empty string for self.ids.input_t.text
self.texter = self.input_val.text
class runs(App):
def build(self):
Clock.schedule_interval(apper().doer, 1.0/2.0)
return apper()
runs().run()
#the code works when you remove the Clock statement and the second argument or apper.doer() and you have to press the button
#to rename the label
#how comes it doesnt work when you introduce the clock statement
#Note that I am new to kivy but not new to programming
When I use a button to run the function on press the correct values from text input are returned but using a clock it doesn't work, can anyone help.
Also when the program should be running properly with the Clock then the button is unnecessary since it updates the label with the text of the TextInput every 0.5 seconds.
Is there any way the code can be rewritten or mended such that the TextInput returns a value and not an empty string.
move the clock to ur apper class: and put it like this
Clock.schedule_interval(self.doer, 1/2)
and declare doer like this:
def doer(self, *args):
and feel free to check this tuto i uploaded recently
https://www.youtube.com/watch?v=DbX-CdVob6E&t=57s
Can someone explain why below code adds this Close Button on the bottom of the window you can see on the pic? How to get rid of this?
CODE
from kivy.app import App
from kivy.lang import Builder
kv = '''
<MenuSpinner#Spinner>
<Menu#BoxLayout>
orientation: 'vertical'
MenuSpinner:
text: 'SPINNER'
values: ['1', '2']
BoxLayout:
Menu:
'''
sm = Builder.load_string(kv)
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
The button is coming from the MenuSpinner, which is already present in Kivy (mostly internal, used by kivy.uix.settings). That class should probably be named differently on the Kivy side, but in any case renaming your version should fix the problem.
I'm doing a proyect using kivy but i have a problem with the checkboxes. At first I'm trying to do the program like python coding (I know it is'nt clean, but I understand more) And i have a first screen with this coding:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.checkbox import CheckBox
class MainScreen(GridLayout):
def __init__(self,**kwargs):
e=[]
super(MainScreen, self).__init__(**kwargs)
self.cols=2
def on_checkbox_active(checkbox, value):
if value:
e.append(value)
print e
else:
print('The checkbox', checkbox, 'is inactive')
self.add_widget(Label(text='Inserta assignatures desitjades',font_size=35))
self.add_widget(Label(text=''))
ch1 = CheckBox()
self.add_widget(ch1)
self.add_widget(Label(text='Termotecnia'))
ch2 = CheckBox()
self.add_widget(ch2)
self.add_widget(Label(text='Termotecnia'))
ch3 = CheckBox()
self.add_widget(ch3)
self.add_widget(Label(text='Termotecnia'))
ch4 = CheckBox()
self.add_widget(ch4)
self.add_widget(Label(text='Termotecnia'))
b1=Button(text='Exit',background_color=[0.7,0.7,1,1],font_size=24)
self.add_widget(b1)
b2=Button(text='Next',font_size=24,font_color=[1,3,4,0],background_color=[1,2,3,6])
self.add_widget(b2)
ch1.bind(active=on_checkbox_active)
ch2.bind(active=on_checkbox_active)
b1.bind(on_press=exit)
b2.bind(on_press=reloaded)
...
class SimpleKivy(App):
def build(self):
return MainScreen()
if __name__=='__main__':
SimpleKivy().run()
I want to select two or three options for example, and save it for the next screen, like a type of selection. If anyone knows how to do it and save information for the next screen it woul help me a lot, because i have the code of the next screen for all the options, but i want to preselect in the first screen and then only use which i have selected. Also if anyone can help me, i want to know hoy to do the transition to another class (screen) when the button "Next" is pressed. I know this question are pretty simple but I'm new in kivy programming and some concepts are pretty difficult. Thanks.
What you want is accessing variables in other classes. Sometimes this can be annoying and you can do it either hard way with all __init__() and stuff, or... a simplier way comes along: it's get_running_app().
You can create a dictionary or something else, where you can store any value your other classes need to access. It's similar to using globals and it costs you less lines of code. For example in your case you could use a dictionary(or nested dictionaries, json, ...) to store for example 'checkboxes':'<names of checked ones>' and in each init you can loop over these values to make checkboxes active
Basically all you need is a = App.get_running_app() somewhere and something to access in main - App - class.
Example:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
Builder.load_string('''
<Root>:
MainScreen:
name: 'main'
AnotherScreen:
name: 'another'
<MainScreen>:
BoxLayout:
Button:
text: 'next screen'
on_release: root.parent.current='another'
Button:
text: 'ping!'
on_release: root.ping()
<AnotherScreen>:
BoxLayout:
Button:
text: 'previous screen'
on_release: root.parent.current='main'
Button:
text: 'ping!'
on_release: root.ping()
''')
class MainScreen(Screen):
def __init__(self, **kw):
super(MainScreen, self).__init__(**kw)
self.a = App.get_running_app()
def ping(self):
print self.a.big_dict['hi']
class AnotherScreen(Screen):
def ping(self):
b = App.get_running_app()
print b.big_dict['hi']
class Root(ScreenManager):
pass
class SimpleKivy(App):
big_dict={'hi':'hi there!'}
def build(self):
return Root()
SimpleKivy().run()
You can see there's no need to call __init__(), no need to write more lines of code if you really don't need to.
I am having problems understanding the usage of custom Properities and ways of binding methods to events.
Here's my code:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import StringProperty
kivy_lang = '''
<MainWidget>:
on_my_property: my_label.text = 'from button bind method via StringProperty' + my_property
Label:
id: my_label
text: root.my_property
Button:
id: my_button
text: 'intro button'
'''
class MainWidget(BoxLayout):
# bind some properties
my_property = StringProperty('0')
def __init__(self, **kwargs):
super(MainWidget, self).__init__(**kwargs)
# if needed to do sth on widget construction
self.ids.my_button.bind(on_press=self.my_method)
def my_method(self,*args,**kwargs):
self.my_property = str(int(self.my_property)+1)
self.ids.my_button.text = 'new'
class MyApp(App):
def build(self):
Builder.load_string(kivy_lang)
return MainWidget()
if __name__ == '__main__':
MyApp().run()
When I run it it renders OK, but when I click a button, as a result I get
NameError: name 'my_property' is not defined
I tried binding method for Button in kv lang with (and removing whole 'init()' on python side):
on_press: root.my_method
and then when I press button the app doesn't crash but nothing happens
Can someone explain me how to adjust this code to work?
I understand the code is a little 'mixed techniques' but I did it that way to get to know different approaches, so I would appreciate if You don't turn it all around :)
1/ you are missing 'self' before 'my_property' in 'on_my_property' bindind, hence the crash
2/ in kv bindings. the python code is called as written, so you need '()' after 'root.my_method', or the statement has no effect.