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.
Related
.kv file
#:import Clock kivy.clock.Clock
#:import threading threading
#:import partial functools.partial
<MainScreen>:
BoxLayout:
size: root.size
orientation: "vertical"
BoxLayout:
Label:
id: wordcount
pos_hint: {'center_x':0.5,'y':0.6}
size_hint: 0.2,0.2
text: root.wordcount
Label:
pos_hint: {'center_x':0.5,'y':0.6}
size_hint: 0.2,0.2
id: BESTOPTIONS
text: root.entrophyvaluesbest
CustomBox:
id: layout
cols:5
Button:
pos_hint: {'center_x':0.5,'y':0.67}
size_hint: 0.5,0.1
text: "Click here to start!"
on_release: root.StartGame()
Button:
text: "Check your word!"
size_hint: 0.5,0.1
pos_hint:{'center_x':0.5,'y':0.4}
on_press:
a=threading.Thread(target=root.Check)
a.start()
a.join()
b=threading.Thread(target=root.ShowPreviousWord)
b.start()
b.join()
c=threading.Thread(target=root.ClearLetters)
c.start()
c.join()
d=threading.Thread(target=partial(Clock.schedule_once,root.FocusFirst,0.5))
d.start()
Label:
pos_hint:{'center_x':0.5,'y':-0.35}
id: OUTPUT
markup: True
My .py code is long, so I will try asking without that - My functions which occur while I click Button "Check your word" are sometimes taking to long - if the function a ( it is the only time consuming function there) takes too much time, then the Clock.schedule_once doesn't proc the FocusFirst function and because of that - nothing is focused then.
I want to change the focus after all functions takes place - I know that main gui is in Main Thread, so it's not happening because of that, but I wonder if I am able to just make all functions happen first and then just change the focus and if so - how to do that.
I tried adding Clock.schedule_once without time argument, which makes it even worse.
I know that I can fix it by adding bigger time - for example 30 seconds, but I want the TextInput focus right after functions happen, not 30 seconds after that.
I resolved the issue and probably resolved the issue of GUI change block by some functions.
I simply took the function out of on_press and placed it to on_release, the button is being locked untill functions inside happen, then the button is released, so the function I wanted to postpone happens.
I have a ScrollView inside of a BoxLayout that changes size rather dramatically when the screen size changes. I am making an iOS app that displays text inside of a ScrollView in the top half of the screen, I then have a non scroll Label directly under that.
I have been using an iPhone 12/13 for the layout design however when I run it on an iPhone 8 (with the smaller screen real estate), the ScrollView overlaps the Label text under it considerably. When I run the two different Xcode phone simulators side by side, the ScrollView area on the iPhone 8 actually seems to increase in size for some weird reason.
I have been using size_hint and pos_hint for all the widgets, which has generally been working okay, just not really with this ScrollView. I have tried adjusting all of the sizes of everything but there doesn't seem like a happy middle that I can use to suit both screen types.
I have been using height in my BoxLayout as the parent for the ScrollView, and not sure if I'm using it right either.
I will include my BoxLayout with the ScrollView in it. Please could someone have a look to see if I'm doing something obviously wrong here? I hope I don't need to make different layouts for every different screen type.
BoxLayout:
pos_hint: {"top": .9, "center_x": .5}
size_hint: 1, .3
size_hint_y: None
height: 460
ScrollView:
Label:
id: brief_res_1
markup: True
font_size: '13sp'
do_scroll_x: True
size_hint_y: None
size_hint_x: None
size: self.texture_size
halign: "left"
valign: "center"
text: ""
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
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.