Can I just put more function in this on release or this wont work. I want to have more pop functions and pictures displayed, maybe some audio, etc. This is .kv file:
<Root>:
orientation: 'vertical'
RecordButton:
id: record_button
background_color: 1,1.01,0.90,1
text: 'Order'
on_release:
self.record()
root.pop1()
height: '100dp'
size_hint_y: None
TextInput:
text: record_button.output
readonly: True
Defining an event callback as sequence of statements.
Inside the KV file
Indentation and thus structuring control-flow readable is limited in a KV file. As inclement commented there are basically 2 ways for defining a callback sequence:
statements per line (same indentation)
semicolon separated statements
on_release:
self.record()
root.pop1()
on_press: print('pressed'); self.insert_text("pressed!")
See Kivy-language syntax Valid expressions inside :
[..] multiple single line statements are valid, including those that escape their newline, as long as they don’t add an indentation level.
Define a function in Python
You have more flexibility to define the a function inside the Python script and declare this callback on the event inside the KV file.
For example the function as method of your RecordButton (assume its a class extending Button) in Python:
class RecordButton(Button):
# callback function tells when button released
# It tells the state and instance of button.
def record_and_pop(self, instance):
print("Button is released")
print('The button <%s> state is <%s>' % (instance.text, instance.state))
self.record()
root.pop1()
then used inside the KV:
RecordButton:
on_release: self.record_and_more()
See also
kivy: firing multiple functions on 1 button click
Kivy API: Button class
Related
For example we created with kivy language simple BoxLayout1 that contains button1 and another BoxLayout2. When you click button1 it adds a new button in BoxLayout2 but it's written in python.
Is it possible to acces existing layout in kv language, in python code? Or only solution is writting whole window in python?
I couldn't find any info in kivy docs, maybe I've just missed something.
EDIT:
I've something like this
Kv:
<CreateWindow>:
BoxLayout:
Button:
text: "test"
on_release: root.press()
BoxLayout:
Label:
text: "Label"
Python:
class CreateWindow(Screen):
def press(self):
I want to add a new button near Label by activating press function
in python will be like this
class CreateWindow(Screen):
def press(self):
# the first box is the first child in the children list of the CreateWindow widget so
box1=self.children[0]
box2=self.children[1]
# and now you can decide which box you want to use add_widget method with
# in your case it should be
box2.add_widget(Button())
I'm trying create new TabbedPanelItem with properties already created widget. But i'm getting new empty widget or replace exist.
.py
class MainScreen(Screen):
def add(self, tabbed_item):
new_tabbed_item = TabbedPanelItem()
new_tabbed_item.properties = copy(tabbed_item)
new_tabbed_item.text = "2"
self.ids.tab_panel.add_widget(new_tabbed_item)
.kv
<MainScreen>:
AnchorLayout:
canvas.before:
...
TabbedPanel:
id: tab_panel
...
TabbedPanelItem:
Button:
on_press: root.add(tab_item)
TabbedPanelItem:
id: tab_item
....
When I try to run you're code nothing pops up. You don't have enough code to test. I'm not sure what your goal is, but if you want to have a TabbedPanelItem with stuff already created without having to reproduce the same code (if that's your goal), try using #. An example: MyTabbedPanel#TabbedPanelItem:. Then you can add everything you want it to do, and reuse it instead of retyping out the code everytime.
Why does this code get a KeyError, from line #21?
I've tried different versions of similar code, but this is the only file that gets the KeyError.
Gist: https://gist.github.com/Crowbrammer/464ae3ae3ddd7d33a9eb64d856acacd0
Why is it missing the id's of each element in the Kivy file?
How come the function beneath the init() function works, with that exact same line of code--but the init() function doesn't?
I don't think record_new_model gets called.
Your constructor fails so the rest doesn't matter.
You aren't setting the ids properly.
You need to do something like this
<ModelAddLayout>:
model_add_name: model_add_name
orientation: 'vertical'
padding: 20, 20
Label:
id: title_label
text: 'Model Add Screen'
font_size: '30dp'
# text_size: '15dp'
TextInput:
id: model_add_name
text: 'Add your model name here'
multiline: False
When you are adding an id to a child it doesn't get added to the parent. You also need to add the id to the parent: model_add_name: model_add_name.
The root determines what elements get loaded into the code first.
For this code is ScreenManagement. The root for others is ModelAddLayout.
So, for the code I linked, it loads the elements of the kv file later than I expect, so there are no keys in the ids attribute to call.
What I did get to work, then, was to put everything except super() into a new function, late_init(self, keys, **largs).
After that, I put Clock.schedule_once(self.late_init, 0) after init()'s super.
This gave the app time to populate the ids, enabling my dropdown list to become a reality.
(From the comment to Radu Dita's answer.)
For some process in my app, I use the internet to acquire some data. So for those processed I want a simple popup box(with a text Loading...) to appear at the begining of the process, but when I ran the test code, I observed that the popup box displays at the end of the process rather than at the begining of the process which makes it useless. Here is the test code I am using. Your help is appreciated, thanks.
class ScreenManagement(ScreenManager):
def popup(self):
self.pop_up=Popup(title='Loading...')
self.pop_up.open()
def popup_done(self):
self.pop_up.dismiss()
def ite(self):
for i in range(100):
App.get_running_app().root.current='second'
return i
def thread_it(self,fx):
self.popup()
mythread = threading.Thread(target=fx)
mythread.start()
def ite(self,num):
for i in range(num):
txt=str(i)*40
self.ids.lbl.text=txt
print txt
#if i==num-1: #this is not working
# self.popup_done()
class labelApp(App):
def build(self):
pass
labelApp().run()
.kv file
ScreenManagement:
Screen:
BoxLayout:
Button:
#on_press:root.popup()
#on_release:root.popup_done()
on_press:root.thread_it(root.ite(40000))
on_press:root.current='second'
Screen:
name:'second'
BoxLayout:
Label:
id:lbl
text: 'hello'
The problem is with your ScreenManagement.ite() method. It doesn't run in thread and you've already noticed that anything that could compete with Kivy's main loop and doesn't run in Thread will freeze the main loop. Kivy has Clock which might interest you too.
For this exact code however you'll need partial, which will freeze a function in time and return a thing you can pass as argument, so that it wouldn't be executed in-place where you want to add it as an argument to a thread function (e.g. if ite() means executing, partial will remove those brackets and let Thread add them when it's necessary)
Thread(target=fx) means after passing the ite() method basically this:
Thread(target=root.ite(40000))
i.e. runs that thing in-place and as ite() method doesn't return anything, it'll do this:
# freeze main loop
# after done, call Thread
Thread(target=None)
and starts it. So you freeze your main loop and after the ite() ends, the Popup gets its turn to show up. Let's fix it with partial:
#:import partial functools.partial
<ScreenManagement>:
Screen:
BoxLayout:
Button:
#on_press:root.popup()
#on_release:root.popup_done()
on_press: root.thread_it(partial(root.ite,400))
on_press: root.current='second'
If I have a class that I define in the Python source file as a child of Widget, is it necessary for me add a FloatLayout a child, or can I just position the elements inside the Widget directly, without using a FloatLayout at all?
# Python source
class FooBar(Widget):
pass
# Kivy source
<FooBar>:
FloatLayout: # Is this necessary?
SomeChildWidget:
...
AnotherChildWidget:
...
There is nothing wrong with embed widgets inside widgets. You are in complete control of the position and sizing.
The add_widget method (and children property) is part of the Widget class, and Layout just inherits from Widget. As an example, the Kivy pong tutorial doesn't have any layouts.
Note: If you are start wondering about the difference of using Widget and FloatLayout. Basically, the latter honours Widget.pos_hint and Widget.size_hint attributes. It allows you to use proportional values to the size of the Widget for positioning.
A quick look over the Kv language documentation suggests that no, you don't need a layout inside the widget. Consider the example they give under the template section:
<MyWidget>:
Button:
text: "Hello world, watch this text wrap inside the button"
text_size: self.size
font_size: '25sp'
markup: True
Button:
text: "Even absolute is relative to itself"
text_size: self.size
font_size: '25sp'
markup: True
Button:
text: "Repeating the same thing over and over in a comp = fail"
text_size: self.size
font_size: '25sp'
markup: True
Here 3 button widgets have been placed directly under the <MyWidget> declaration.